buffet: Extracted libweave into separate directory
It still has references to dbus, buffet and other ChromeOS specific
stuff.
BUG=brillo:1235
TEST=FEATURES=test emerge-gizmo buffet
Change-Id: Ib108960ee88afcf2ecdddf37ce30bd5f168c0034
Reviewed-on: https://chromium-review.googlesource.com/283509
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/base_api_handler.cc b/buffet/base_api_handler.cc
deleted file mode 100644
index 16e9ec3..0000000
--- a/buffet/base_api_handler.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/base_api_handler.h"
-
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/command_manager.h"
-#include "buffet/device_registration_info.h"
-#include "buffet/states/state_manager.h"
-
-namespace buffet {
-
-namespace {
-
-// Helps to get parameters from native_types::Object representing
-// CommandInstance parameters.
-class ParametersReader final {
- public:
- explicit ParametersReader(const native_types::Object* parameters)
- : parameters_{parameters} {}
-
- bool GetParameter(const std::string& name, std::string* value) const {
- auto it = parameters_->find(name);
- if (it == parameters_->end())
- return false;
- const StringValue* string_value = it->second->GetString();
- if (!string_value)
- return false;
- *value = string_value->GetValue();
- return true;
- }
-
- bool GetParameter(const std::string& name, bool* value) const {
- auto it = parameters_->find(name);
- if (it == parameters_->end())
- return false;
- const BooleanValue* bool_value = it->second->GetBoolean();
- if (!bool_value)
- return false;
- *value = bool_value->GetValue();
- return true;
- }
-
- private:
- const native_types::Object* parameters_;
-};
-
-} // namespace
-
-BaseApiHandler::BaseApiHandler(
- const base::WeakPtr<DeviceRegistrationInfo>& device_info,
- const std::shared_ptr<StateManager>& state_manager,
- const std::shared_ptr<CommandManager>& command_manager)
- : device_info_{device_info}, state_manager_{state_manager} {
- command_manager->AddOnCommandAddedCallback(base::Bind(
- &BaseApiHandler::OnCommandAdded, weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BaseApiHandler::OnCommandAdded(CommandInstance* command) {
- if (command->GetStatus() != CommandInstance::kStatusQueued)
- return;
-
- if (command->GetName() == "base.updateBaseConfiguration")
- return UpdateBaseConfiguration(command);
-
- if (command->GetName() == "base.updateDeviceInfo")
- return UpdateDeviceInfo(command);
-}
-
-void BaseApiHandler::UpdateBaseConfiguration(CommandInstance* command) {
- command->SetProgress({});
-
- const BuffetConfig& config{device_info_->GetConfig()};
- std::string anonymous_access_role{config.local_anonymous_access_role()};
- bool discovery_enabled{config.local_discovery_enabled()};
- bool pairing_enabled{config.local_pairing_enabled()};
-
- ParametersReader parameters{&command->GetParameters()};
- parameters.GetParameter("localAnonymousAccessMaxRole",
- &anonymous_access_role);
- parameters.GetParameter("localDiscoveryEnabled", &discovery_enabled);
- parameters.GetParameter("localPairingEnabled", &pairing_enabled);
-
- chromeos::VariantDictionary state{
- {"base.localAnonymousAccessMaxRole", anonymous_access_role},
- {"base.localDiscoveryEnabled", discovery_enabled},
- {"base.localPairingEnabled", pairing_enabled},
- };
- if (!state_manager_->SetProperties(state, nullptr)) {
- return command->Abort();
- }
-
- if (!device_info_->UpdateBaseConfig(anonymous_access_role, discovery_enabled,
- pairing_enabled, nullptr)) {
- return command->Abort();
- }
-
- command->Done();
-}
-
-void BaseApiHandler::UpdateDeviceInfo(CommandInstance* command) {
- command->SetProgress({});
-
- const BuffetConfig& config{device_info_->GetConfig()};
- std::string name{config.name()};
- std::string description{config.description()};
- std::string location{config.location()};
-
- ParametersReader parameters(&command->GetParameters());
- parameters.GetParameter("name", &name);
- parameters.GetParameter("description", &description);
- parameters.GetParameter("location", &location);
-
- if (!device_info_->UpdateDeviceInfo(name, description, location, nullptr)) {
- return command->Abort();
- }
-
- command->Done();
-}
-
-} // namespace buffet
diff --git a/buffet/base_api_handler.h b/buffet/base_api_handler.h
deleted file mode 100644
index 9c9bcb0..0000000
--- a/buffet/base_api_handler.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_BASE_API_HANDLER_H_
-#define BUFFET_BASE_API_HANDLER_H_
-
-#include <memory>
-#include <string>
-
-#include <base/memory/weak_ptr.h>
-
-namespace buffet {
-
-class CommandInstance;
-class CommandManager;
-class DeviceRegistrationInfo;
-class StateManager;
-
-// Handles commands from 'base' package.
-// Objects of the class subscribe for notification from CommandManager and
-// execute incoming commands.
-// Handled commands:
-// base.updateDeviceInfo
-// base.updateBaseConfiguration
-class BaseApiHandler final {
- public:
- BaseApiHandler(const base::WeakPtr<DeviceRegistrationInfo>& device_info,
- const std::shared_ptr<StateManager>& state_manager,
- const std::shared_ptr<CommandManager>& command_manager);
-
- private:
- void OnCommandAdded(CommandInstance* command);
- void UpdateBaseConfiguration(CommandInstance* command);
- void UpdateDeviceInfo(CommandInstance* command);
-
- base::WeakPtr<DeviceRegistrationInfo> device_info_;
- std::shared_ptr<StateManager> state_manager_;
-
- base::WeakPtrFactory<BaseApiHandler> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(BaseApiHandler);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_BASE_API_HANDLER_H_
diff --git a/buffet/base_api_handler_unittest.cc b/buffet/base_api_handler_unittest.cc
deleted file mode 100644
index c7df9bb..0000000
--- a/buffet/base_api_handler_unittest.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/base_api_handler.h"
-
-#include <base/strings/string_number_conversions.h>
-#include <base/values.h>
-#include <chromeos/http/http_transport_fake.h>
-#include <gtest/gtest.h>
-
-#include "buffet/buffet_config.h"
-#include "buffet/commands/command_manager.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/device_registration_info.h"
-#include "buffet/states/mock_state_change_queue_interface.h"
-#include "buffet/states/state_manager.h"
-#include "buffet/storage_impls.h"
-
-namespace buffet {
-
-class BaseApiHandlerTest : public ::testing::Test {
- protected:
- void SetUp() override {
- transport_ = std::make_shared<chromeos::http::fake::Transport>();
- command_manager_ = std::make_shared<CommandManager>();
- state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
- auto state_definition = unittests::CreateDictionaryValue(R"({
- 'base': {
- 'firmwareVersion': 'string',
- 'localDiscoveryEnabled': 'boolean',
- 'localAnonymousAccessMaxRole': [ 'none', 'viewer', 'user' ],
- 'localPairingEnabled': 'boolean',
- 'network': {
- 'properties': {
- 'name': 'string'
- }
- }
- }
- })");
- auto state_defaults = unittests::CreateDictionaryValue(R"({
- 'base': {
- 'firmwareVersion': '123123',
- 'localDiscoveryEnabled': false,
- 'localAnonymousAccessMaxRole': 'none',
- 'localPairingEnabled': false
- }
- })");
- ASSERT_TRUE(state_manager_->LoadStateDefinition(*state_definition, "base",
- nullptr));
- ASSERT_TRUE(state_manager_->LoadStateDefaults(*state_defaults, nullptr));
- dev_reg_.reset(new DeviceRegistrationInfo(
- command_manager_, state_manager_,
- std::unique_ptr<BuffetConfig>{new BuffetConfig{
- std::unique_ptr<StorageInterface>{new MemStorage}}},
- transport_, nullptr, true, nullptr));
- handler_.reset(new BaseApiHandler{
- dev_reg_->AsWeakPtr(), state_manager_, command_manager_});
- }
-
- void LoadCommands(const std::string& command_definitions) {
- auto json = unittests::CreateDictionaryValue(command_definitions.c_str());
- EXPECT_TRUE(command_manager_->LoadBaseCommands(*json, nullptr));
- EXPECT_TRUE(command_manager_->LoadCommands(*json, "", nullptr));
- }
-
- void AddCommand(const std::string& command) {
- auto command_instance = buffet::CommandInstance::FromJson(
- unittests::CreateDictionaryValue(command.c_str()).get(),
- commands::attributes::kCommand_Visibility_Local,
- command_manager_->GetCommandDictionary(), nullptr, nullptr);
- EXPECT_TRUE(!!command_instance);
-
- std::string id{base::IntToString(++command_id_)};
- command_instance->SetID(id);
- command_manager_->AddCommand(std::move(command_instance));
- EXPECT_EQ(CommandInstance::kStatusDone,
- command_manager_->FindCommand(id)->GetStatus());
- }
-
- std::shared_ptr<chromeos::http::fake::Transport> transport_;
- std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
- std::shared_ptr<CommandManager> command_manager_;
- testing::NiceMock<MockStateChangeQueueInterface> mock_state_change_queue_;
- std::shared_ptr<StateManager> state_manager_;
- std::unique_ptr<BaseApiHandler> handler_;
- int command_id_{0};
-};
-
-TEST_F(BaseApiHandlerTest, UpdateBaseConfiguration) {
- LoadCommands(R"({
- 'base': {
- 'updateBaseConfiguration': {
- 'parameters': {
- 'localDiscoveryEnabled': 'boolean',
- 'localAnonymousAccessMaxRole': [ 'none', 'viewer', 'user' ],
- 'localPairingEnabled': 'boolean'
- },
- 'results': {}
- }
- }
- })");
-
- const BuffetConfig& config{dev_reg_->GetConfig()};
-
- AddCommand(R"({
- 'name' : 'base.updateBaseConfiguration',
- 'parameters': {
- 'localDiscoveryEnabled': false,
- 'localAnonymousAccessMaxRole': 'none',
- 'localPairingEnabled': false
- }
- })");
- EXPECT_EQ("none", config.local_anonymous_access_role());
- EXPECT_FALSE(config.local_discovery_enabled());
- EXPECT_FALSE(config.local_pairing_enabled());
-
- auto expected = R"({
- 'base': {
- 'firmwareVersion': '123123',
- 'localAnonymousAccessMaxRole': 'none',
- 'localDiscoveryEnabled': false,
- 'localPairingEnabled': false,
- 'network': {}
- }
- })";
- EXPECT_JSON_EQ(expected, *state_manager_->GetStateValuesAsJson(nullptr));
-
- AddCommand(R"({
- 'name' : 'base.updateBaseConfiguration',
- 'parameters': {
- 'localDiscoveryEnabled': true,
- 'localAnonymousAccessMaxRole': 'user',
- 'localPairingEnabled': true
- }
- })");
- EXPECT_EQ("user", config.local_anonymous_access_role());
- EXPECT_TRUE(config.local_discovery_enabled());
- EXPECT_TRUE(config.local_pairing_enabled());
- expected = R"({
- 'base': {
- 'firmwareVersion': '123123',
- 'localAnonymousAccessMaxRole': 'user',
- 'localDiscoveryEnabled': true,
- 'localPairingEnabled': true,
- 'network': {}
- }
- })";
- EXPECT_JSON_EQ(expected, *state_manager_->GetStateValuesAsJson(nullptr));
-}
-
-TEST_F(BaseApiHandlerTest, UpdateDeviceInfo) {
- LoadCommands(R"({
- 'base': {
- 'updateDeviceInfo': {
- 'parameters': {
- 'description': 'string',
- 'name': {
- 'type': 'string',
- 'minLength': 1
- },
- 'location': 'string'
- },
- 'results': {}
- }
- }
- })");
-
- AddCommand(R"({
- 'name' : 'base.updateDeviceInfo',
- 'parameters': {
- 'name': 'testName',
- 'description': 'testDescription',
- 'location': 'testLocation'
- }
- })");
-
- const BuffetConfig& config{dev_reg_->GetConfig()};
- EXPECT_EQ("testName", config.name());
- EXPECT_EQ("testDescription", config.description());
- EXPECT_EQ("testLocation", config.location());
-}
-
-} // namespace buffet
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index f8c0a5a..7b92439 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -10,7 +10,11 @@
'system_api',
],
},
- 'include_dirs': ['.'],
+ 'include_dirs': [
+ '.',
+ # TODO(vitalybuka): Remove both.
+ '../libweave/include',
+ ],
},
'targets': [
{
@@ -21,53 +25,53 @@
'dbus_service_config': 'dbus_bindings/dbus-service-config.json',
},
'sources': [
- 'base_api_handler.cc',
- 'buffet_config.cc',
- 'commands/command_definition.cc',
- 'commands/command_dictionary.cc',
- 'commands/command_instance.cc',
- 'commands/command_manager.cc',
- 'commands/command_queue.cc',
- 'commands/dbus_command_dispatcher.cc',
- 'commands/dbus_command_proxy.cc',
- 'commands/cloud_command_proxy.cc',
- 'commands/object_schema.cc',
- 'commands/prop_constraints.cc',
- 'commands/prop_types.cc',
- 'commands/prop_values.cc',
- 'commands/schema_constants.cc',
- 'commands/schema_utils.cc',
- 'commands/user_role.cc',
- 'device_registration_info.cc',
'dbus_bindings/org.chromium.Buffet.Command.xml',
'dbus_bindings/org.chromium.Buffet.Manager.xml',
'dbus_constants.cc',
'manager.cc',
- 'notification/notification_parser.cc',
- 'notification/pull_channel.cc',
- 'notification/xml_node.cc',
- 'notification/xmpp_channel.cc',
- 'notification/xmpp_iq_stanza_handler.cc',
- 'notification/xmpp_stream_parser.cc',
- 'privet/ap_manager_client.cc',
- 'privet/cloud_delegate.cc',
- 'privet/constants.cc',
- 'privet/device_delegate.cc',
- 'privet/openssl_utils.cc',
- 'privet/peerd_client.cc',
- 'privet/privet_handler.cc',
- 'privet/privet_manager.cc',
- 'privet/security_manager.cc',
- 'privet/shill_client.cc',
- 'privet/wifi_bootstrap_manager.cc',
- 'privet/wifi_ssid_generator.cc',
- 'registration_status.cc',
- 'storage_impls.cc',
- 'states/error_codes.cc',
- 'states/state_change_queue.cc',
- 'states/state_manager.cc',
- 'states/state_package.cc',
- 'utils.cc',
+ '../libweave/src/base_api_handler.cc',
+ '../libweave/src/buffet_config.cc',
+ '../libweave/src/commands/cloud_command_proxy.cc',
+ '../libweave/src/commands/command_definition.cc',
+ '../libweave/src/commands/command_dictionary.cc',
+ '../libweave/src/commands/command_instance.cc',
+ '../libweave/src/commands/command_manager.cc',
+ '../libweave/src/commands/command_queue.cc',
+ '../libweave/src/commands/dbus_command_dispatcher.cc',
+ '../libweave/src/commands/dbus_command_proxy.cc',
+ '../libweave/src/commands/object_schema.cc',
+ '../libweave/src/commands/prop_constraints.cc',
+ '../libweave/src/commands/prop_types.cc',
+ '../libweave/src/commands/prop_values.cc',
+ '../libweave/src/commands/schema_constants.cc',
+ '../libweave/src/commands/schema_utils.cc',
+ '../libweave/src/commands/user_role.cc',
+ '../libweave/src/device_registration_info.cc',
+ '../libweave/src/notification/notification_parser.cc',
+ '../libweave/src/notification/pull_channel.cc',
+ '../libweave/src/notification/xml_node.cc',
+ '../libweave/src/notification/xmpp_channel.cc',
+ '../libweave/src/notification/xmpp_iq_stanza_handler.cc',
+ '../libweave/src/notification/xmpp_stream_parser.cc',
+ '../libweave/src/privet/ap_manager_client.cc',
+ '../libweave/src/privet/cloud_delegate.cc',
+ '../libweave/src/privet/constants.cc',
+ '../libweave/src/privet/device_delegate.cc',
+ '../libweave/src/privet/openssl_utils.cc',
+ '../libweave/src/privet/peerd_client.cc',
+ '../libweave/src/privet/privet_handler.cc',
+ '../libweave/src/privet/privet_manager.cc',
+ '../libweave/src/privet/security_manager.cc',
+ '../libweave/src/privet/shill_client.cc',
+ '../libweave/src/privet/wifi_bootstrap_manager.cc',
+ '../libweave/src/privet/wifi_ssid_generator.cc',
+ '../libweave/src/registration_status.cc',
+ '../libweave/src/states/error_codes.cc',
+ '../libweave/src/states/state_change_queue.cc',
+ '../libweave/src/states/state_manager.cc',
+ '../libweave/src/states/state_package.cc',
+ '../libweave/src/storage_impls.cc',
+ '../libweave/src/utils.cc',
],
'includes': ['../common-mk/generate-dbus-adaptors.gypi'],
'actions': [
@@ -176,32 +180,32 @@
},
'includes': ['../common-mk/common_test.gypi'],
'sources': [
- 'base_api_handler_unittest.cc',
- 'buffet_testrunner.cc',
- 'buffet_config_unittest.cc',
- 'commands/cloud_command_proxy_unittest.cc',
- 'commands/command_definition_unittest.cc',
- 'commands/command_dictionary_unittest.cc',
- 'commands/command_instance_unittest.cc',
- 'commands/command_manager_unittest.cc',
- 'commands/command_queue_unittest.cc',
- 'commands/dbus_command_dispatcher_unittest.cc',
- 'commands/dbus_command_proxy_unittest.cc',
- 'commands/object_schema_unittest.cc',
- 'commands/schema_utils_unittest.cc',
- 'commands/unittest_utils.cc',
- 'device_registration_info_unittest.cc',
- 'notification/notification_parser_unittest.cc',
- 'notification/xml_node_unittest.cc',
- 'notification/xmpp_channel_unittest.cc',
- 'notification/xmpp_iq_stanza_handler_unittest.cc',
- 'notification/xmpp_stream_parser_unittest.cc',
- 'privet/privet_handler_unittest.cc',
- 'privet/security_manager_unittest.cc',
- 'privet/wifi_ssid_generator_unittest.cc',
- 'states/state_change_queue_unittest.cc',
- 'states/state_manager_unittest.cc',
- 'states/state_package_unittest.cc',
+ '../libweave/src/base_api_handler_unittest.cc',
+ '../libweave/src/buffet_config_unittest.cc',
+ '../libweave/src/buffet_testrunner.cc',
+ '../libweave/src/commands/cloud_command_proxy_unittest.cc',
+ '../libweave/src/commands/command_definition_unittest.cc',
+ '../libweave/src/commands/command_dictionary_unittest.cc',
+ '../libweave/src/commands/command_instance_unittest.cc',
+ '../libweave/src/commands/command_manager_unittest.cc',
+ '../libweave/src/commands/command_queue_unittest.cc',
+ '../libweave/src/commands/dbus_command_dispatcher_unittest.cc',
+ '../libweave/src/commands/dbus_command_proxy_unittest.cc',
+ '../libweave/src/commands/object_schema_unittest.cc',
+ '../libweave/src/commands/schema_utils_unittest.cc',
+ '../libweave/src/commands/unittest_utils.cc',
+ '../libweave/src/device_registration_info_unittest.cc',
+ '../libweave/src/notification/notification_parser_unittest.cc',
+ '../libweave/src/notification/xml_node_unittest.cc',
+ '../libweave/src/notification/xmpp_channel_unittest.cc',
+ '../libweave/src/notification/xmpp_iq_stanza_handler_unittest.cc',
+ '../libweave/src/notification/xmpp_stream_parser_unittest.cc',
+ '../libweave/src/privet/privet_handler_unittest.cc',
+ '../libweave/src/privet/security_manager_unittest.cc',
+ '../libweave/src/privet/wifi_ssid_generator_unittest.cc',
+ '../libweave/src/states/state_change_queue_unittest.cc',
+ '../libweave/src/states/state_manager_unittest.cc',
+ '../libweave/src/states/state_package_unittest.cc',
],
},
],
diff --git a/buffet/buffet_config.cc b/buffet/buffet_config.cc
deleted file mode 100644
index 72f8338..0000000
--- a/buffet/buffet_config.cc
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/buffet_config.h"
-
-#include <set>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/storage_impls.h"
-#include "buffet/storage_interface.h"
-
-namespace {
-
-// TODO(vitalybuka): Remove this when deviceKind is gone from server.
-std::string GetDeviceKind(const std::string& manifest_id) {
- CHECK_EQ(5u, manifest_id.size());
- std::string kind = manifest_id.substr(0, 2);
- if (kind == "AC")
- return "accessPoint";
- if (kind == "AK")
- return "aggregator";
- if (kind == "AM")
- return "camera";
- if (kind == "AB")
- return "developmentBoard";
- if (kind == "AE")
- return "printer";
- if (kind == "AF")
- return "scanner";
- if (kind == "AD")
- return "speaker";
- if (kind == "AL")
- return "storage";
- if (kind == "AJ")
- return "toy";
- if (kind == "AA")
- return "vendor";
- if (kind == "AN")
- return "video";
- LOG(FATAL) << "Invalid model id: " << manifest_id;
- return std::string();
-}
-
-bool IsValidAccessRole(const std::string& role) {
- return role == "none" || role == "viewer" || role == "user";
-}
-
-bool StringToTimeDelta(const std::string& value, base::TimeDelta* delta) {
- uint64_t ms{0};
- if (!base::StringToUint64(value, &ms))
- return false;
- *delta = base::TimeDelta::FromMilliseconds(ms);
- return true;
-}
-
-} // namespace
-
-namespace buffet {
-
-namespace config_keys {
-
-const char kClientId[] = "client_id";
-const char kClientSecret[] = "client_secret";
-const char kApiKey[] = "api_key";
-const char kOAuthURL[] = "oauth_url";
-const char kServiceURL[] = "service_url";
-const char kName[] = "name";
-const char kDescription[] = "description";
-const char kLocation[] = "location";
-const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role";
-const char kLocalDiscoveryEnabled[] = "local_discovery_enabled";
-const char kLocalPairingEnabled[] = "local_pairing_enabled";
-const char kOemName[] = "oem_name";
-const char kModelName[] = "model_name";
-const char kModelId[] = "model_id";
-const char kPollingPeriodMs[] = "polling_period_ms";
-const char kBackupPollingPeriodMs[] = "backup_polling_period_ms";
-const char kRefreshToken[] = "refresh_token";
-const char kDeviceId[] = "device_id";
-const char kRobotAccount[] = "robot_account";
-const char kWifiAutoSetupEnabled[] = "wifi_auto_setup_enabled";
-const char kEmbeddedCodePath[] = "embedded_code_path";
-const char kPairingModes[] = "pairing_modes";
-const char kLastConfiguredSsid[] = "last_configured_ssid";
-
-} // namespace config_keys
-
-BuffetConfig::BuffetConfig(std::unique_ptr<StorageInterface> storage)
- : storage_{std::move(storage)} {
-}
-
-BuffetConfig::BuffetConfig(const base::FilePath& state_path)
- : BuffetConfig{
- std::unique_ptr<StorageInterface>{new FileStorage{state_path}}} {
-}
-
-void BuffetConfig::Load(const base::FilePath& config_path) {
- chromeos::KeyValueStore store;
- if (base::PathExists(config_path)) {
- CHECK(store.Load(config_path)) << "Unable to read or parse config file at"
- << config_path.value();
- }
- Load(store);
-}
-
-void BuffetConfig::Load(const chromeos::KeyValueStore& store) {
- Transaction change{this};
- change.save_ = false;
-
- store.GetString(config_keys::kClientId, &client_id_);
- CHECK(!client_id_.empty());
-
- store.GetString(config_keys::kClientSecret, &client_secret_);
- CHECK(!client_secret_.empty());
-
- store.GetString(config_keys::kApiKey, &api_key_);
- CHECK(!api_key_.empty());
-
- store.GetString(config_keys::kOAuthURL, &oauth_url_);
- CHECK(!oauth_url_.empty());
-
- store.GetString(config_keys::kServiceURL, &service_url_);
- CHECK(!service_url_.empty());
-
- store.GetString(config_keys::kOemName, &oem_name_);
- CHECK(!oem_name_.empty());
-
- store.GetString(config_keys::kModelName, &model_name_);
- CHECK(!model_name_.empty());
-
- store.GetString(config_keys::kModelId, &model_id_);
- device_kind_ = GetDeviceKind(model_id_);
-
- std::string polling_period_str;
- if (store.GetString(config_keys::kPollingPeriodMs, &polling_period_str))
- CHECK(StringToTimeDelta(polling_period_str, &polling_period_));
-
- if (store.GetString(config_keys::kBackupPollingPeriodMs, &polling_period_str))
- CHECK(StringToTimeDelta(polling_period_str, &backup_polling_period_));
-
- store.GetBoolean(config_keys::kWifiAutoSetupEnabled,
- &wifi_auto_setup_enabled_);
-
- std::string embedded_code_path;
- if (store.GetString(config_keys::kEmbeddedCodePath, &embedded_code_path)) {
- embedded_code_path_ = base::FilePath(embedded_code_path);
- if (!embedded_code_path_.empty())
- pairing_modes_ = {privetd::PairingType::kEmbeddedCode};
- }
-
- std::string modes_str;
- if (store.GetString(config_keys::kPairingModes, &modes_str)) {
- std::set<privetd::PairingType> pairing_modes;
- for (const std::string& mode :
- chromeos::string_utils::Split(modes_str, ",", true, true)) {
- privetd::PairingType pairing_mode;
- CHECK(privetd::StringToPairingType(mode, &pairing_mode));
- pairing_modes.insert(pairing_mode);
- }
- pairing_modes_ = std::move(pairing_modes);
- }
-
- // Empty name set by user or server is allowed, still we expect some
- // meaningfull config value.
- store.GetString(config_keys::kName, &name_);
- CHECK(!name_.empty());
-
- store.GetString(config_keys::kDescription, &description_);
- store.GetString(config_keys::kLocation, &location_);
-
- store.GetString(config_keys::kLocalAnonymousAccessRole,
- &local_anonymous_access_role_);
- CHECK(IsValidAccessRole(local_anonymous_access_role_))
- << "Invalid role: " << local_anonymous_access_role_;
-
- store.GetBoolean(config_keys::kLocalDiscoveryEnabled,
- &local_discovery_enabled_);
- store.GetBoolean(config_keys::kLocalPairingEnabled, &local_pairing_enabled_);
-
- change.LoadState();
-}
-
-void BuffetConfig::Transaction::LoadState() {
- if (!config_->storage_)
- return;
- auto value = config_->storage_->Load();
- const base::DictionaryValue* dict = nullptr;
- if (!value || !value->GetAsDictionary(&dict))
- return;
-
- std::string tmp;
- bool tmp_bool{false};
-
- if (dict->GetString(config_keys::kClientId, &tmp))
- set_client_id(tmp);
-
- if (dict->GetString(config_keys::kClientSecret, &tmp))
- set_client_secret(tmp);
-
- if (dict->GetString(config_keys::kApiKey, &tmp))
- set_api_key(tmp);
-
- if (dict->GetString(config_keys::kOAuthURL, &tmp))
- set_oauth_url(tmp);
-
- if (dict->GetString(config_keys::kServiceURL, &tmp))
- set_service_url(tmp);
-
- if (dict->GetString(config_keys::kName, &tmp))
- set_name(tmp);
-
- if (dict->GetString(config_keys::kDescription, &tmp))
- set_description(tmp);
-
- if (dict->GetString(config_keys::kLocation, &tmp))
- set_location(tmp);
-
- if (dict->GetString(config_keys::kLocalAnonymousAccessRole, &tmp))
- set_local_anonymous_access_role(tmp);
-
- if (dict->GetBoolean(config_keys::kLocalDiscoveryEnabled, &tmp_bool))
- set_local_discovery_enabled(tmp_bool);
-
- if (dict->GetBoolean(config_keys::kLocalPairingEnabled, &tmp_bool))
- set_local_pairing_enabled(tmp_bool);
-
- if (dict->GetString(config_keys::kRefreshToken, &tmp))
- set_refresh_token(tmp);
-
- if (dict->GetString(config_keys::kRobotAccount, &tmp))
- set_robot_account(tmp);
-
- if (dict->GetString(config_keys::kLastConfiguredSsid, &tmp))
- set_last_configured_ssid(tmp);
-
- if (dict->GetString(config_keys::kDeviceId, &tmp))
- set_device_id(tmp);
-}
-
-bool BuffetConfig::Save() {
- if (!storage_)
- return false;
- base::DictionaryValue dict;
- dict.SetString(config_keys::kClientId, client_id_);
- dict.SetString(config_keys::kClientSecret, client_secret_);
- dict.SetString(config_keys::kApiKey, api_key_);
- dict.SetString(config_keys::kOAuthURL, oauth_url_);
- dict.SetString(config_keys::kServiceURL, service_url_);
- dict.SetString(config_keys::kRefreshToken, refresh_token_);
- dict.SetString(config_keys::kDeviceId, device_id_);
- dict.SetString(config_keys::kRobotAccount, robot_account_);
- dict.SetString(config_keys::kLastConfiguredSsid, last_configured_ssid_);
- dict.SetString(config_keys::kName, name_);
- dict.SetString(config_keys::kDescription, description_);
- dict.SetString(config_keys::kLocation, location_);
- dict.SetString(config_keys::kLocalAnonymousAccessRole,
- local_anonymous_access_role_);
- dict.SetBoolean(config_keys::kLocalDiscoveryEnabled,
- local_discovery_enabled_);
- dict.SetBoolean(config_keys::kLocalPairingEnabled, local_pairing_enabled_);
-
- return storage_->Save(dict);
-}
-
-BuffetConfig::Transaction::~Transaction() {
- Commit();
-}
-
-bool BuffetConfig::Transaction::set_local_anonymous_access_role(
- const std::string& role) {
- if (!IsValidAccessRole(role)) {
- LOG(ERROR) << "Invalid role: " << role;
- return false;
- }
- config_->local_anonymous_access_role_ = role;
- return true;
-}
-
-void BuffetConfig::Transaction::Commit() {
- if (!config_)
- return;
- if (save_)
- config_->Save();
- for (const auto& cb : config_->on_changed_)
- cb.Run(*config_);
- config_ = nullptr;
-}
-
-} // namespace buffet
diff --git a/buffet/buffet_config.h b/buffet/buffet_config.h
deleted file mode 100644
index a2b25d9..0000000
--- a/buffet/buffet_config.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_BUFFET_CONFIG_H_
-#define BUFFET_BUFFET_CONFIG_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/files/file_path.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/key_value_store.h>
-
-#include "buffet/privet/security_delegate.h"
-
-namespace buffet {
-
-class StorageInterface;
-
-// Handles reading buffet config and state files.
-class BuffetConfig final {
- public:
- using OnChangedCallback = base::Callback<void(const BuffetConfig&)>;
-
- explicit BuffetConfig(std::unique_ptr<StorageInterface> storage);
-
- explicit BuffetConfig(const base::FilePath& state_path);
-
- void AddOnChangedCallback(const OnChangedCallback& callback) {
- on_changed_.push_back(callback);
- // Force to read current state.
- callback.Run(*this);
- }
-
- void Load(const base::FilePath& config_path);
- void Load(const chromeos::KeyValueStore& store);
-
- // Allows editing of config. Makes sure that callbacks were called and changes
- // were saved.
- // User can commit changes by calling Commit method or by destroying the
- // object.
- class Transaction final {
- public:
- explicit Transaction(BuffetConfig* config) : config_(config) {
- CHECK(config_);
- }
-
- ~Transaction();
-
- void set_client_id(const std::string& id) { config_->client_id_ = id; }
- void set_client_secret(const std::string& secret) {
- config_->client_secret_ = secret;
- }
- void set_api_key(const std::string& key) { config_->api_key_ = key; }
- void set_oauth_url(const std::string& url) { config_->oauth_url_ = url; }
- void set_service_url(const std::string& url) {
- config_->service_url_ = url;
- }
- void set_name(const std::string& name) { config_->name_ = name; }
- void set_description(const std::string& description) {
- config_->description_ = description;
- }
- void set_location(const std::string& location) {
- config_->location_ = location;
- }
- bool set_local_anonymous_access_role(const std::string& role);
- void set_local_discovery_enabled(bool enabled) {
- config_->local_discovery_enabled_ = enabled;
- }
- void set_local_pairing_enabled(bool enabled) {
- config_->local_pairing_enabled_ = enabled;
- }
- void set_device_id(const std::string& id) { config_->device_id_ = id; }
- void set_refresh_token(const std::string& token) {
- config_->refresh_token_ = token;
- }
- void set_robot_account(const std::string& account) {
- config_->robot_account_ = account;
- }
- void set_last_configured_ssid(const std::string& ssid) {
- config_->last_configured_ssid_ = ssid;
- }
-
- void Commit();
-
- private:
- friend class BuffetConfig;
- void LoadState();
- BuffetConfig* config_;
- bool save_{true};
- };
-
- const std::string& client_id() const { return client_id_; }
- const std::string& client_secret() const { return client_secret_; }
- const std::string& api_key() const { return api_key_; }
- const std::string& oauth_url() const { return oauth_url_; }
- const std::string& service_url() const { return service_url_; }
- const std::string& oem_name() const { return oem_name_; }
- const std::string& model_name() const { return model_name_; }
- const std::string& model_id() const { return model_id_; }
- const std::string& device_kind() const { return device_kind_; }
- base::TimeDelta polling_period() const { return polling_period_; }
- base::TimeDelta backup_polling_period() const {
- return backup_polling_period_;
- }
-
- bool wifi_auto_setup_enabled() const { return wifi_auto_setup_enabled_; }
- const std::set<privetd::PairingType>& pairing_modes() const {
- return pairing_modes_;
- }
- const base::FilePath& embedded_code_path() const {
- return embedded_code_path_;
- }
-
- const std::string& name() const { return name_; }
- const std::string& description() const { return description_; }
- const std::string& location() const { return location_; }
- const std::string& local_anonymous_access_role() const {
- return local_anonymous_access_role_;
- }
- bool local_pairing_enabled() const { return local_pairing_enabled_; }
- bool local_discovery_enabled() const { return local_discovery_enabled_; }
-
- const std::string& device_id() const { return device_id_; }
- const std::string& refresh_token() const { return refresh_token_; }
- const std::string& robot_account() const { return robot_account_; }
- const std::string& last_configured_ssid() const {
- return last_configured_ssid_;
- }
-
- private:
- bool Save();
-
- std::string client_id_{"58855907228.apps.googleusercontent.com"};
- std::string client_secret_{"eHSAREAHrIqPsHBxCE9zPPBi"};
- std::string api_key_{"AIzaSyDSq46gG-AxUnC3zoqD9COIPrjolFsMfMA"};
- std::string oauth_url_{"https://accounts.google.com/o/oauth2/"};
- std::string service_url_{"https://www.googleapis.com/clouddevices/v1/"};
- std::string name_{"Developer device"};
- std::string description_;
- std::string location_;
- std::string local_anonymous_access_role_{"viewer"};
- bool local_discovery_enabled_{true};
- bool local_pairing_enabled_{true};
- std::string oem_name_{"Chromium"};
- std::string model_name_{"Brillo"};
- std::string model_id_{"AAAAA"};
- std::string device_kind_{"vendor"};
- base::TimeDelta polling_period_{base::TimeDelta::FromSeconds(7)};
- base::TimeDelta backup_polling_period_{base::TimeDelta::FromMinutes(30)};
-
- bool wifi_auto_setup_enabled_{true};
- std::set<privetd::PairingType> pairing_modes_{privetd::PairingType::kPinCode};
- base::FilePath embedded_code_path_;
-
- std::string device_id_;
- std::string refresh_token_;
- std::string robot_account_;
- std::string last_configured_ssid_;
-
- // Serialization interface to save and load buffet state.
- std::unique_ptr<StorageInterface> storage_;
-
- std::vector<OnChangedCallback> on_changed_;
-
- DISALLOW_COPY_AND_ASSIGN(BuffetConfig);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_BUFFET_CONFIG_H_
diff --git a/buffet/buffet_config_unittest.cc b/buffet/buffet_config_unittest.cc
deleted file mode 100644
index 7fa1933..0000000
--- a/buffet/buffet_config_unittest.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/buffet_config.h"
-
-#include <set>
-
-#include <base/bind.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/storage_impls.h"
-
-using testing::_;
-
-namespace buffet {
-
-class BuffetConfigTest : public ::testing::Test {
- protected:
- void SetUp() override {
- EXPECT_CALL(*this, OnConfigChanged(_))
- .Times(1); // Called from AddOnChangedCallback
-
- std::unique_ptr<StorageInterface> storage{new MemStorage};
- storage_ = storage.get();
- config_.reset(new BuffetConfig{std::move(storage)});
-
- config_->AddOnChangedCallback(
- base::Bind(&BuffetConfigTest::OnConfigChanged, base::Unretained(this)));
- }
-
- MOCK_METHOD1(OnConfigChanged, void(const BuffetConfig&));
-
- StorageInterface* storage_{nullptr};
- std::unique_ptr<BuffetConfig> config_;
- const BuffetConfig default_{nullptr};
-};
-
-TEST_F(BuffetConfigTest, NoStorage) {
- BuffetConfig config{nullptr};
- BuffetConfig::Transaction change{&config};
- change.Commit();
-}
-
-TEST_F(BuffetConfigTest, Defaults) {
- EXPECT_EQ("58855907228.apps.googleusercontent.com", config_->client_id());
- EXPECT_EQ("eHSAREAHrIqPsHBxCE9zPPBi", config_->client_secret());
- EXPECT_EQ("AIzaSyDSq46gG-AxUnC3zoqD9COIPrjolFsMfMA", config_->api_key());
- EXPECT_EQ("https://accounts.google.com/o/oauth2/", config_->oauth_url());
- EXPECT_EQ("https://www.googleapis.com/clouddevices/v1/",
- config_->service_url());
- EXPECT_EQ("Chromium", config_->oem_name());
- EXPECT_EQ("Brillo", config_->model_name());
- EXPECT_EQ("AAAAA", config_->model_id());
- EXPECT_EQ("vendor", config_->device_kind());
- EXPECT_EQ(base::TimeDelta::FromSeconds(7), config_->polling_period());
- EXPECT_EQ(base::TimeDelta::FromMinutes(30), config_->backup_polling_period());
- EXPECT_TRUE(config_->wifi_auto_setup_enabled());
- EXPECT_EQ(std::set<privetd::PairingType>{privetd::PairingType::kPinCode},
- config_->pairing_modes());
- EXPECT_EQ("", config_->embedded_code_path().value());
- EXPECT_EQ("Developer device", config_->name());
- EXPECT_EQ("", config_->description());
- EXPECT_EQ("", config_->location());
- EXPECT_EQ("viewer", config_->local_anonymous_access_role());
- EXPECT_TRUE(config_->local_pairing_enabled());
- EXPECT_TRUE(config_->local_discovery_enabled());
- EXPECT_EQ("", config_->device_id());
- EXPECT_EQ("", config_->refresh_token());
- EXPECT_EQ("", config_->robot_account());
- EXPECT_EQ("", config_->last_configured_ssid());
-}
-
-TEST_F(BuffetConfigTest, LoadConfig) {
- chromeos::KeyValueStore config_store;
- config_store.SetString("client_id", "conf_client_id");
- config_store.SetString("client_secret", "conf_client_secret");
- config_store.SetString("api_key", "conf_api_key");
- config_store.SetString("oauth_url", "conf_oauth_url");
- config_store.SetString("service_url", "conf_service_url");
- config_store.SetString("oem_name", "conf_oem_name");
- config_store.SetString("model_name", "conf_model_name");
- config_store.SetString("model_id", "ABCDE");
- config_store.SetString("polling_period_ms", "12345");
- config_store.SetString("backup_polling_period_ms", "6589");
- config_store.SetBoolean("wifi_auto_setup_enabled", false);
- config_store.SetString("pairing_modes",
- "pinCode,embeddedCode,ultrasound32,audible32");
- config_store.SetString("embedded_code_path", "/conf_code");
- config_store.SetString("name", "conf_name");
- config_store.SetString("description", "conf_description");
- config_store.SetString("location", "conf_location");
- config_store.SetString("local_anonymous_access_role", "user");
- config_store.SetBoolean("local_pairing_enabled", false);
- config_store.SetBoolean("local_discovery_enabled", false);
-
- // Following will be ignored.
- config_store.SetString("device_kind", "conf_device_kind");
- config_store.SetString("device_id", "conf_device_id");
- config_store.SetString("refresh_token", "conf_refresh_token");
- config_store.SetString("robot_account", "conf_robot_account");
- config_store.SetString("last_configured_ssid", "conf_last_configured_ssid");
-
- EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
- config_->Load(config_store);
-
- EXPECT_EQ("conf_client_id", config_->client_id());
- EXPECT_EQ("conf_client_secret", config_->client_secret());
- EXPECT_EQ("conf_api_key", config_->api_key());
- EXPECT_EQ("conf_oauth_url", config_->oauth_url());
- EXPECT_EQ("conf_service_url", config_->service_url());
- EXPECT_EQ("conf_oem_name", config_->oem_name());
- EXPECT_EQ("conf_model_name", config_->model_name());
- EXPECT_EQ("ABCDE", config_->model_id());
- EXPECT_EQ("developmentBoard", config_->device_kind());
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(12345),
- config_->polling_period());
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(6589),
- config_->backup_polling_period());
- EXPECT_FALSE(config_->wifi_auto_setup_enabled());
- std::set<privetd::PairingType> pairing_types{
- privetd::PairingType::kPinCode, privetd::PairingType::kEmbeddedCode,
- privetd::PairingType::kUltrasound32, privetd::PairingType::kAudible32};
- EXPECT_EQ(pairing_types, config_->pairing_modes());
- EXPECT_EQ("/conf_code", config_->embedded_code_path().value());
- EXPECT_EQ("conf_name", config_->name());
- EXPECT_EQ("conf_description", config_->description());
- EXPECT_EQ("conf_location", config_->location());
- EXPECT_EQ("user", config_->local_anonymous_access_role());
- EXPECT_FALSE(config_->local_pairing_enabled());
- EXPECT_FALSE(config_->local_discovery_enabled());
-
- // Not from config.
- EXPECT_EQ(default_.device_id(), config_->device_id());
- EXPECT_EQ(default_.refresh_token(), config_->refresh_token());
- EXPECT_EQ(default_.robot_account(), config_->robot_account());
- EXPECT_EQ(default_.last_configured_ssid(), config_->last_configured_ssid());
-
- // Nothing should be saved yet.
- EXPECT_JSON_EQ("{}", *storage_->Load());
-
- BuffetConfig::Transaction change{config_.get()};
- EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
- change.Commit();
-
- auto expected = R"({
- 'api_key': 'conf_api_key',
- 'client_id': 'conf_client_id',
- 'client_secret': 'conf_client_secret',
- 'description': 'conf_description',
- 'device_id': '',
- 'local_anonymous_access_role': 'user',
- 'local_discovery_enabled': false,
- 'local_pairing_enabled': false,
- 'location': 'conf_location',
- 'name': 'conf_name',
- 'oauth_url': 'conf_oauth_url',
- 'refresh_token': '',
- 'robot_account': '',
- 'last_configured_ssid': '',
- 'service_url': 'conf_service_url'
- })";
- EXPECT_JSON_EQ(expected, *storage_->Load());
-}
-
-TEST_F(BuffetConfigTest, LoadState) {
- auto state = R"({
- 'api_key': 'state_api_key',
- 'client_id': 'state_client_id',
- 'client_secret': 'state_client_secret',
- 'description': 'state_description',
- 'device_id': 'state_device_id',
- 'local_anonymous_access_role': 'user',
- 'local_discovery_enabled': false,
- 'local_pairing_enabled': false,
- 'location': 'state_location',
- 'name': 'state_name',
- 'oauth_url': 'state_oauth_url',
- 'refresh_token': 'state_refresh_token',
- 'robot_account': 'state_robot_account',
- 'last_configured_ssid': 'state_last_configured_ssid',
- 'service_url': 'state_service_url'
- })";
- storage_->Save(*buffet::unittests::CreateDictionaryValue(state));
-
- chromeos::KeyValueStore config_store;
- EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
- config_->Load(config_store);
-
- // Clear storage.
- storage_->Save(base::DictionaryValue());
-
- EXPECT_EQ("state_client_id", config_->client_id());
- EXPECT_EQ("state_client_secret", config_->client_secret());
- EXPECT_EQ("state_api_key", config_->api_key());
- EXPECT_EQ("state_oauth_url", config_->oauth_url());
- EXPECT_EQ("state_service_url", config_->service_url());
- EXPECT_EQ(default_.oem_name(), config_->oem_name());
- EXPECT_EQ(default_.model_name(), config_->model_name());
- EXPECT_EQ(default_.model_id(), config_->model_id());
- EXPECT_EQ(default_.device_kind(), config_->device_kind());
- EXPECT_EQ(default_.polling_period(), config_->polling_period());
- EXPECT_EQ(default_.backup_polling_period(), config_->backup_polling_period());
- EXPECT_EQ(default_.wifi_auto_setup_enabled(),
- config_->wifi_auto_setup_enabled());
- EXPECT_EQ(default_.pairing_modes(), config_->pairing_modes());
- EXPECT_EQ(default_.embedded_code_path(), config_->embedded_code_path());
- EXPECT_EQ("state_name", config_->name());
- EXPECT_EQ("state_description", config_->description());
- EXPECT_EQ("state_location", config_->location());
- EXPECT_EQ("user", config_->local_anonymous_access_role());
- EXPECT_FALSE(config_->local_pairing_enabled());
- EXPECT_FALSE(config_->local_discovery_enabled());
- EXPECT_EQ("state_device_id", config_->device_id());
- EXPECT_EQ("state_refresh_token", config_->refresh_token());
- EXPECT_EQ("state_robot_account", config_->robot_account());
- EXPECT_EQ("state_last_configured_ssid", config_->last_configured_ssid());
-
- // Nothing should be saved yet.
- EXPECT_JSON_EQ("{}", *storage_->Load());
-
- BuffetConfig::Transaction change{config_.get()};
- EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
- change.Commit();
-
- EXPECT_JSON_EQ(state, *storage_->Load());
-}
-
-TEST_F(BuffetConfigTest, Setters) {
- BuffetConfig::Transaction change{config_.get()};
-
- change.set_client_id("set_client_id");
- EXPECT_EQ("set_client_id", config_->client_id());
-
- change.set_client_secret("set_client_secret");
- EXPECT_EQ("set_client_secret", config_->client_secret());
-
- change.set_api_key("set_api_key");
- EXPECT_EQ("set_api_key", config_->api_key());
-
- change.set_oauth_url("set_oauth_url");
- EXPECT_EQ("set_oauth_url", config_->oauth_url());
-
- change.set_service_url("set_service_url");
- EXPECT_EQ("set_service_url", config_->service_url());
-
- change.set_name("set_name");
- EXPECT_EQ("set_name", config_->name());
-
- change.set_description("set_description");
- EXPECT_EQ("set_description", config_->description());
-
- change.set_location("set_location");
- EXPECT_EQ("set_location", config_->location());
-
- change.set_local_anonymous_access_role("viewer");
- EXPECT_EQ("viewer", config_->local_anonymous_access_role());
-
- change.set_local_anonymous_access_role("none");
- EXPECT_EQ("none", config_->local_anonymous_access_role());
-
- change.set_local_anonymous_access_role("user");
- EXPECT_EQ("user", config_->local_anonymous_access_role());
-
- change.set_local_discovery_enabled(false);
- EXPECT_FALSE(config_->local_discovery_enabled());
-
- change.set_local_pairing_enabled(false);
- EXPECT_FALSE(config_->local_pairing_enabled());
-
- change.set_local_discovery_enabled(true);
- EXPECT_TRUE(config_->local_discovery_enabled());
-
- change.set_local_pairing_enabled(true);
- EXPECT_TRUE(config_->local_pairing_enabled());
-
- change.set_device_id("set_id");
- EXPECT_EQ("set_id", config_->device_id());
-
- change.set_refresh_token("set_token");
- EXPECT_EQ("set_token", config_->refresh_token());
-
- change.set_robot_account("set_account");
- EXPECT_EQ("set_account", config_->robot_account());
-
- change.set_last_configured_ssid("set_last_configured_ssid");
- EXPECT_EQ("set_last_configured_ssid", config_->last_configured_ssid());
-
- EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
- change.Commit();
-
- auto expected = R"({
- 'api_key': 'set_api_key',
- 'client_id': 'set_client_id',
- 'client_secret': 'set_client_secret',
- 'description': 'set_description',
- 'device_id': 'set_id',
- 'local_anonymous_access_role': 'user',
- 'local_discovery_enabled': true,
- 'local_pairing_enabled': true,
- 'location': 'set_location',
- 'name': 'set_name',
- 'oauth_url': 'set_oauth_url',
- 'refresh_token': 'set_token',
- 'robot_account': 'set_account',
- 'last_configured_ssid': 'set_last_configured_ssid',
- 'service_url': 'set_service_url'
- })";
- EXPECT_JSON_EQ(expected, *storage_->Load());
-}
-} // namespace buffet
diff --git a/buffet/buffet_testrunner.cc b/buffet/buffet_testrunner.cc
deleted file mode 100644
index 575f952..0000000
--- a/buffet/buffet_testrunner.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <base/at_exit.h>
-#include <gtest/gtest.h>
-
-int main(int argc, char **argv) {
- base::AtExitManager exit_manager;
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/buffet/commands/cloud_command_proxy.cc b/buffet/commands/cloud_command_proxy.cc
deleted file mode 100644
index 127e63b..0000000
--- a/buffet/commands/cloud_command_proxy.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/cloud_command_proxy.h"
-
-#include <base/bind.h>
-
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/prop_constraints.h"
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-CloudCommandProxy::CloudCommandProxy(
- CommandInstance* command_instance,
- CloudCommandUpdateInterface* cloud_command_updater,
- StateChangeQueueInterface* state_change_queue,
- std::unique_ptr<chromeos::BackoffEntry> backoff_entry,
- const scoped_refptr<base::TaskRunner>& task_runner)
- : command_instance_{command_instance},
- cloud_command_updater_{cloud_command_updater},
- state_change_queue_{state_change_queue},
- task_runner_{task_runner},
- cloud_backoff_entry_{std::move(backoff_entry)} {
- callback_token_ = state_change_queue_->AddOnStateUpdatedCallback(
- base::Bind(&CloudCommandProxy::OnDeviceStateUpdated,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void CloudCommandProxy::OnResultsChanged() {
- std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
- auto json = TypedValueToJson(command_instance_->GetResults(), nullptr);
- patch->Set(commands::attributes::kCommand_Results, json.release());
- QueueCommandUpdate(std::move(patch));
-}
-
-void CloudCommandProxy::OnStatusChanged() {
- std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
- patch->SetString(commands::attributes::kCommand_State,
- command_instance_->GetStatus());
- QueueCommandUpdate(std::move(patch));
-}
-
-void CloudCommandProxy::OnProgressChanged() {
- std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
- auto json = TypedValueToJson(command_instance_->GetProgress(), nullptr);
- patch->Set(commands::attributes::kCommand_Progress, json.release());
- QueueCommandUpdate(std::move(patch));
-}
-
-void CloudCommandProxy::QueueCommandUpdate(
- std::unique_ptr<base::DictionaryValue> patch) {
- UpdateID id = state_change_queue_->GetLastStateChangeId();
- if (update_queue_.empty() || update_queue_.back().first != id) {
- // If queue is currently empty or the device state has changed since the
- // last patch request queued, add a new request to the queue.
- update_queue_.push_back(std::make_pair(id, std::move(patch)));
- } else {
- // Device state hasn't changed since the last time this command update
- // was queued. We can coalesce the command update patches, unless the
- // current request is already in flight to the server.
- if (update_queue_.size() == 1 && command_update_in_progress_) {
- // Can't update the request which is being sent to the server.
- // Queue a new update.
- update_queue_.push_back(std::make_pair(id, std::move(patch)));
- } else {
- // Coalesce the patches.
- update_queue_.back().second->MergeDictionary(patch.get());
- }
- }
- // Send out an update request to the server, if needed.
- SendCommandUpdate();
-}
-
-void CloudCommandProxy::SendCommandUpdate() {
- if (command_update_in_progress_ || update_queue_.empty())
- return;
-
- // Check if we have any pending updates ready to be sent to the server.
- // We can only send updates for which the device state at the time the
- // requests have been queued were successfully propagated to the server.
- // That is, if the pending device state updates that we recorded while the
- // command update was queued haven't been acknowledged by the server, we
- // will hold the corresponding command updates until the related device state
- // has been successfully updated on the server.
- if (update_queue_.front().first > last_state_update_id_)
- return;
-
- backoff_weak_ptr_factory_.InvalidateWeakPtrs();
- if (cloud_backoff_entry_->ShouldRejectRequest()) {
- VLOG(1) << "Cloud request delayed for "
- << cloud_backoff_entry_->GetTimeUntilRelease()
- << " due to backoff policy";
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&CloudCommandProxy::SendCommandUpdate,
- backoff_weak_ptr_factory_.GetWeakPtr()),
- cloud_backoff_entry_->GetTimeUntilRelease());
- return;
- }
-
- // Coalesce any pending updates that were queued prior to the current device
- // state known to be propagated to the server successfully.
- auto iter = update_queue_.begin();
- auto start = ++iter;
- while (iter != update_queue_.end()) {
- if (iter->first > last_state_update_id_)
- break;
- update_queue_.front().first = iter->first;
- update_queue_.front().second->MergeDictionary(iter->second.get());
- ++iter;
- }
- // Remove all the intermediate items that have been merged into the first
- // entry.
- update_queue_.erase(start, iter);
- command_update_in_progress_ = true;
- cloud_command_updater_->UpdateCommand(
- command_instance_->GetID(), *update_queue_.front().second,
- base::Bind(&CloudCommandProxy::OnUpdateCommandFinished,
- weak_ptr_factory_.GetWeakPtr(), true),
- base::Bind(&CloudCommandProxy::OnUpdateCommandFinished,
- weak_ptr_factory_.GetWeakPtr(), false));
-}
-
-void CloudCommandProxy::ResendCommandUpdate() {
- command_update_in_progress_ = false;
- SendCommandUpdate();
-}
-
-void CloudCommandProxy::OnUpdateCommandFinished(bool success) {
- command_update_in_progress_ = false;
- cloud_backoff_entry_->InformOfRequest(success);
- if (success) {
- // Remove the succeeded update from the queue.
- update_queue_.pop_front();
- }
- // If we have more pending updates, send a new request to the server
- // immediately, if possible.
- SendCommandUpdate();
-}
-
-void CloudCommandProxy::OnDeviceStateUpdated(UpdateID update_id) {
- last_state_update_id_ = update_id;
- // Try to send out any queued command updates that could be performed after
- // a device state is updated.
- SendCommandUpdate();
-}
-
-} // namespace buffet
diff --git a/buffet/commands/cloud_command_proxy.h b/buffet/commands/cloud_command_proxy.h
deleted file mode 100644
index 55eb552..0000000
--- a/buffet/commands/cloud_command_proxy.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_CLOUD_COMMAND_PROXY_H_
-#define BUFFET_COMMANDS_CLOUD_COMMAND_PROXY_H_
-
-#include <deque>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <base/memory/weak_ptr.h>
-#include <base/task_runner.h>
-#include <chromeos/backoff_entry.h>
-
-#include "buffet/commands/cloud_command_update_interface.h"
-#include "buffet/commands/command_proxy_interface.h"
-#include "buffet/states/state_change_queue_interface.h"
-
-namespace buffet {
-
-class CommandInstance;
-
-// Command proxy which publishes command updates to the cloud.
-class CloudCommandProxy final : public CommandProxyInterface {
- public:
- CloudCommandProxy(CommandInstance* command_instance,
- CloudCommandUpdateInterface* cloud_command_updater,
- StateChangeQueueInterface* state_change_queue,
- std::unique_ptr<chromeos::BackoffEntry> backoff_entry,
- const scoped_refptr<base::TaskRunner>& task_runner);
- ~CloudCommandProxy() override = default;
-
- // CommandProxyInterface implementation/overloads.
- void OnResultsChanged() override;
- void OnStatusChanged() override;
- void OnProgressChanged() override;
-
- private:
- using UpdateID = StateChangeQueueInterface::UpdateID;
- using UpdateQueueEntry =
- std::pair<UpdateID, std::unique_ptr<base::DictionaryValue>>;
-
- // Puts a command update data into the update queue, and optionally sends an
- // asynchronous request to GCD server to update the command resource, if there
- // are no pending device status updates.
- void QueueCommandUpdate(std::unique_ptr<base::DictionaryValue> patch);
-
- // Sends an asynchronous request to GCD server to update the command resource,
- // if there are no pending device status updates.
- void SendCommandUpdate();
-
- // Retry the last failed command update request to the server.
- void ResendCommandUpdate();
-
- // Callback invoked by the asynchronous PATCH request to the server.
- // Called both in a case of successfully updating server command resource
- // and in case of an error, indicated by the |success| parameter.
- void OnUpdateCommandFinished(bool success);
-
- // Callback invoked by the device state change queue to notify of the
- // successful device state update. |update_id| is the ID of the state that
- // has been updated on the server.
- void OnDeviceStateUpdated(UpdateID update_id);
-
- CommandInstance* command_instance_;
- CloudCommandUpdateInterface* cloud_command_updater_;
- StateChangeQueueInterface* state_change_queue_;
- scoped_refptr<base::TaskRunner> task_runner_;
-
- // Backoff for SendCommandUpdate() method.
- std::unique_ptr<chromeos::BackoffEntry> cloud_backoff_entry_;
-
- // Set to true while a pending PATCH request is in flight to the server.
- bool command_update_in_progress_{false};
- // Update queue with all the command update requests ready to be sent to
- // the server.
- std::deque<UpdateQueueEntry> update_queue_;
-
- // Callback token from the state change queue for OnDeviceStateUpdated()
- // callback for ask the device state change queue to call when the state
- // is updated on the server.
- StateChangeQueueInterface::Token callback_token_;
-
- // Last device state update ID that has been sent out to the server
- // successfully.
- UpdateID last_state_update_id_{0};
-
- base::WeakPtrFactory<CloudCommandProxy> backoff_weak_ptr_factory_{this};
- base::WeakPtrFactory<CloudCommandProxy> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(CloudCommandProxy);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_CLOUD_COMMAND_PROXY_H_
diff --git a/buffet/commands/cloud_command_proxy_unittest.cc b/buffet/commands/cloud_command_proxy_unittest.cc
deleted file mode 100644
index 0f0d19c..0000000
--- a/buffet/commands/cloud_command_proxy_unittest.cc
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/cloud_command_proxy.h"
-
-#include <memory>
-#include <queue>
-
-#include <base/test/simple_test_clock.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/command_dictionary.h"
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/states/mock_state_change_queue_interface.h"
-
-using testing::SaveArg;
-using testing::Invoke;
-using testing::Return;
-using testing::ReturnPointee;
-using testing::_;
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-using unittests::CreateValue;
-
-namespace {
-
-const char kCmdID[] = "abcd";
-
-MATCHER_P(MatchJson, str, "") {
- return arg.Equals(CreateValue(str).get());
-}
-
-class MockCloudCommandUpdateInterface : public CloudCommandUpdateInterface {
- public:
- MOCK_METHOD4(UpdateCommand, void(const std::string&,
- const base::DictionaryValue&,
- const base::Closure&,
- const base::Closure&));
-};
-
-// Mock-like task runner that allow the tests to inspect the calls to
-// TaskRunner::PostDelayedTask and verify the delays.
-class TestTaskRunner : public base::TaskRunner {
- public:
- MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&,
- const base::Closure&,
- base::TimeDelta));
-
- bool RunsTasksOnCurrentThread() const override { return true; }
-};
-
-// Test back-off entry that uses the test clock.
-class TestBackoffEntry : public chromeos::BackoffEntry {
- public:
- TestBackoffEntry(const Policy* const policy, base::Clock* clock)
- : chromeos::BackoffEntry{policy}, clock_{clock} {
- creation_time_ = clock->Now();
- }
-
- private:
- // Override from chromeos::BackoffEntry to use the custom test clock for
- // the backoff calculations.
- base::TimeTicks ImplGetTimeNow() const override {
- return base::TimeTicks::FromInternalValue(clock_->Now().ToInternalValue());
- }
-
- base::Clock* clock_;
- base::Time creation_time_;
-};
-
-class CloudCommandProxyTest : public ::testing::Test {
- protected:
- void SetUp() override {
- // Set up the test StateChangeQueue.
- auto callback = [this](
- const base::Callback<void(StateChangeQueueInterface::UpdateID)>& call) {
- return callbacks_.Add(call).release();
- };
- EXPECT_CALL(state_change_queue_, MockAddOnStateUpdatedCallback(_))
- .WillRepeatedly(Invoke(callback));
- EXPECT_CALL(state_change_queue_, GetLastStateChangeId())
- .WillRepeatedly(testing::ReturnPointee(¤t_state_update_id_));
-
- // Set up the task runner.
- task_runner_ = new TestTaskRunner();
-
- auto on_post_task = [this](const tracked_objects::Location& from_here,
- const base::Closure& task,
- base::TimeDelta delay) -> bool {
- clock_.Advance(delay);
- task_queue_.push(task);
- return true;
- };
-
- ON_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .WillByDefault(testing::Invoke(on_post_task));
-
- clock_.SetNow(base::Time::Now());
-
- // Set up the command schema.
- auto json = CreateDictionaryValue(R"({
- 'calc': {
- 'add': {
- 'parameters': {
- 'value1': 'integer',
- 'value2': 'integer'
- },
- 'progress': {
- 'status' : 'string'
- },
- 'results': {
- 'sum' : 'integer'
- }
- }
- }
- })");
- CHECK(json.get());
- CHECK(command_dictionary_.LoadCommands(*json, "calcd", nullptr, nullptr))
- << "Failed to parse test command dictionary";
-
- CreateCommandInstance();
- }
-
- void CreateCommandInstance() {
- auto command_json = CreateDictionaryValue(R"({
- 'name': 'calc.add',
- 'id': 'abcd',
- 'parameters': {
- 'value1': 10,
- 'value2': 20
- }
- })");
- CHECK(command_json.get());
-
- command_instance_ = CommandInstance::FromJson(
- command_json.get(), "cloud", command_dictionary_, nullptr, nullptr);
- CHECK(command_instance_.get());
-
- // Backoff - start at 1s and double with each backoff attempt and no jitter.
- static const chromeos::BackoffEntry::Policy policy{
- 0, 1000, 2.0, 0.0, 20000, -1, false};
- std::unique_ptr<TestBackoffEntry> backoff{
- new TestBackoffEntry{&policy, &clock_}};
-
- // Finally construct the CloudCommandProxy we are going to test here.
- std::unique_ptr<CloudCommandProxy> proxy{new CloudCommandProxy{
- command_instance_.get(), &cloud_updater_, &state_change_queue_,
- std::move(backoff), task_runner_}};
- command_instance_->AddProxy(std::move(proxy));
- }
-
- StateChangeQueueInterface::UpdateID current_state_update_id_{0};
- base::CallbackList<void(StateChangeQueueInterface::UpdateID)> callbacks_;
- testing::StrictMock<MockCloudCommandUpdateInterface> cloud_updater_;
- testing::StrictMock<MockStateChangeQueueInterface> state_change_queue_;
- base::SimpleTestClock clock_;
- scoped_refptr<TestTaskRunner> task_runner_;
- std::queue<base::Closure> task_queue_;
- CommandDictionary command_dictionary_;
- std::unique_ptr<CommandInstance> command_instance_;
-};
-
-} // anonymous namespace
-
-TEST_F(CloudCommandProxyTest, ImmediateUpdate) {
- const char expected[] = "{'state':'done'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- command_instance_->Done();
-}
-
-TEST_F(CloudCommandProxyTest, DelayedUpdate) {
- // Simulate that the current device state has changed.
- current_state_update_id_ = 20;
- // No command update is expected here.
- command_instance_->Done();
- // Still no command update here...
- callbacks_.Notify(19);
- // Now we should get the update...
- const char expected[] = "{'state':'done'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- callbacks_.Notify(20);
-}
-
-TEST_F(CloudCommandProxyTest, InFlightRequest) {
- // SetProgress causes two consecutive updates:
- // state=inProgress
- // progress={...}
- // The first state update is sent immediately, the second should be delayed.
- base::Closure on_success;
- EXPECT_CALL(cloud_updater_,
- UpdateCommand(kCmdID, MatchJson("{'state':'inProgress'}"), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
-
- // Now simulate the first request completing.
- // The second request should be sent now.
- const char expected[] = "{'progress':{'status':'ready'}}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- on_success.Run();
-}
-
-TEST_F(CloudCommandProxyTest, CombineMultiple) {
- // Simulate that the current device state has changed.
- current_state_update_id_ = 20;
- // SetProgress causes two consecutive updates:
- // state=inProgress
- // progress={...}
- // Both updates will be held until device state is updated.
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
-
- // Now simulate the device state updated. Both updates should come in one
- // request.
- const char expected[] = R"({
- 'progress': {'status':'ready'},
- 'state':'inProgress'
- })";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- callbacks_.Notify(20);
-}
-
-TEST_F(CloudCommandProxyTest, RetryFailed) {
- base::Closure on_error;
- const char expect1[] = "{'state':'inProgress'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect1), _, _))
- .WillOnce(SaveArg<3>(&on_error));
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
-
- // Now pretend the first command update request has failed.
- // We should retry with both state and progress fields updated this time,
- // after the initial backoff (which should be 1s in our case).
- base::TimeDelta expected_delay = base::TimeDelta::FromSeconds(1);
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, expected_delay));
- on_error.Run();
-
- // Execute the delayed request. But pretend that it failed too.
- const char expect2[] = R"({
- 'progress': {'status':'ready'},
- 'state':'inProgress'
- })";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect2), _, _))
- .WillOnce(SaveArg<3>(&on_error));
- task_queue_.back().Run();
- task_queue_.pop();
-
- // Now backoff should be 2 seconds.
- expected_delay = base::TimeDelta::FromSeconds(2);
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, expected_delay));
- on_error.Run();
-
- // Retry the task.
- base::Closure on_success;
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect2), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- task_queue_.back().Run();
- task_queue_.pop();
-
- // Pretend it succeeds this time.
- on_success.Run();
-}
-
-TEST_F(CloudCommandProxyTest, GateOnStateUpdates) {
- current_state_update_id_ = 20;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
- current_state_update_id_ = 21;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("busy")}});
- current_state_update_id_ = 22;
- command_instance_->Done();
-
- // Device state #20 updated.
- base::Closure on_success;
- const char expect1[] = R"({
- 'progress': {'status':'ready'},
- 'state':'inProgress'
- })";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect1), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- callbacks_.Notify(20);
- on_success.Run();
-
- // Device state #21 updated.
- const char expect2[] = "{'progress': {'status':'busy'}}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect2), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- callbacks_.Notify(21);
-
- // Device state #22 updated. Nothing happens here since the previous command
- // update request hasn't completed yet.
- callbacks_.Notify(22);
-
- // Now the command update is complete, send out the patch that happened after
- // the state #22 was updated.
- const char expect3[] = "{'state': 'done'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect3), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- on_success.Run();
-}
-
-TEST_F(CloudCommandProxyTest, CombineSomeStates) {
- current_state_update_id_ = 20;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
- current_state_update_id_ = 21;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("busy")}});
- current_state_update_id_ = 22;
- command_instance_->Done();
-
- // Device state 20-21 updated.
- base::Closure on_success;
- const char expect1[] = R"({
- 'progress': {'status':'busy'},
- 'state':'inProgress'
- })";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect1), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- callbacks_.Notify(21);
- on_success.Run();
-
- // Device state #22 updated.
- const char expect2[] = "{'state': 'done'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expect2), _, _))
- .WillOnce(SaveArg<2>(&on_success));
- callbacks_.Notify(22);
- on_success.Run();
-}
-
-TEST_F(CloudCommandProxyTest, CombineAllStates) {
- current_state_update_id_ = 20;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
- current_state_update_id_ = 21;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("busy")}});
- current_state_update_id_ = 22;
- command_instance_->Done();
-
- // Device state 30 updated.
- const char expected[] = R"({
- 'progress': {'status':'busy'},
- 'state':'done'
- })";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- callbacks_.Notify(30);
-}
-
-TEST_F(CloudCommandProxyTest, CoalesceUpdates) {
- current_state_update_id_ = 20;
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("ready")}});
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("busy")}});
- command_instance_->SetProgress(
- {{"status", unittests::make_string_prop_value("finished")}});
- command_instance_->SetResults({{"sum", unittests::make_int_prop_value(30)}});
- command_instance_->Done();
-
- const char expected[] = R"({
- 'progress': {'status':'finished'},
- 'results': {'sum':30},
- 'state':'done'
- })";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- callbacks_.Notify(30);
-}
-
-TEST_F(CloudCommandProxyTest, EmptyStateChangeQueue) {
- // Assume the device state update queue was empty and was at update ID 20.
- current_state_update_id_ = 20;
-
- // Recreate the command instance and proxy with the new state change queue.
- CreateCommandInstance();
-
- // Empty queue will immediately call back with the state change notification.
- callbacks_.Notify(20);
-
- // As soon as we change the command, the update to the server should be sent.
- const char expected[] = "{'state':'done'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- command_instance_->Done();
-}
-
-TEST_F(CloudCommandProxyTest, NonEmptyStateChangeQueue) {
- // Assume the device state update queue was NOT empty when the command
- // instance was created.
- current_state_update_id_ = 20;
-
- // Recreate the command instance and proxy with the new state change queue.
- CreateCommandInstance();
-
- // No command updates right now.
- command_instance_->Done();
-
- // Only when the state #20 is published we should update the command
- const char expected[] = "{'state':'done'}";
- EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _, _));
- callbacks_.Notify(20);
-}
-
-} // namespace buffet
diff --git a/buffet/commands/cloud_command_update_interface.h b/buffet/commands/cloud_command_update_interface.h
deleted file mode 100644
index d18ec85..0000000
--- a/buffet/commands/cloud_command_update_interface.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_CLOUD_COMMAND_UPDATE_INTERFACE_H_
-#define BUFFET_COMMANDS_CLOUD_COMMAND_UPDATE_INTERFACE_H_
-
-#include <string>
-
-#include <base/callback_forward.h>
-#include <base/values.h>
-
-namespace buffet {
-
-// An abstract interface to allow for sending command update requests to the
-// cloud server.
-class CloudCommandUpdateInterface {
- public:
- virtual void UpdateCommand(const std::string& command_id,
- const base::DictionaryValue& command_patch,
- const base::Closure& on_success,
- const base::Closure& on_error) = 0;
-
- protected:
- virtual ~CloudCommandUpdateInterface() = default;
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_CLOUD_COMMAND_UPDATE_INTERFACE_H_
diff --git a/buffet/commands/command_definition.cc b/buffet/commands/command_definition.cc
deleted file mode 100644
index 260cb3d..0000000
--- a/buffet/commands/command_definition.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_definition.h"
-
-#include <vector>
-
-#include <chromeos/errors/error.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-bool CommandDefinition::Visibility::FromString(const std::string& str,
- chromeos::ErrorPtr* error) {
- // This special case is useful for places where we want to make a command
- // to ALL clients, even if new clients are added in the future.
- if (str == commands::attributes::kCommand_Visibility_All) {
- local = true;
- cloud = true;
- return true;
- }
-
- // Clear any bits first.
- local = false;
- cloud = false;
- if (str == commands::attributes::kCommand_Visibility_None)
- return true;
-
- for (const std::string& value : chromeos::string_utils::Split(str, ",")) {
- if (value == commands::attributes::kCommand_Visibility_Local) {
- local = true;
- } else if (value == commands::attributes::kCommand_Visibility_Cloud) {
- cloud = true;
- } else {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid command visibility value '%s'", value.c_str());
- return false;
- }
- }
- return true;
-}
-
-std::string CommandDefinition::Visibility::ToString() const {
- if (local && cloud)
- return commands::attributes::kCommand_Visibility_All;
- if (!local && !cloud)
- return commands::attributes::kCommand_Visibility_None;
- if (local)
- return commands::attributes::kCommand_Visibility_Local;
- return commands::attributes::kCommand_Visibility_Cloud;
-}
-
-CommandDefinition::CommandDefinition(
- const std::string& category,
- std::unique_ptr<const ObjectSchema> parameters,
- std::unique_ptr<const ObjectSchema> progress,
- std::unique_ptr<const ObjectSchema> results)
- : category_{category},
- parameters_{std::move(parameters)},
- progress_{std::move(progress)},
- results_{std::move(results)} {
- // Set to be available to all clients by default.
- visibility_ = Visibility::GetAll();
-}
-
-void CommandDefinition::SetVisibility(const Visibility& visibility) {
- visibility_ = visibility;
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_definition.h b/buffet/commands/command_definition.h
deleted file mode 100644
index ea8e5e6..0000000
--- a/buffet/commands/command_definition.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_COMMAND_DEFINITION_H_
-#define BUFFET_COMMANDS_COMMAND_DEFINITION_H_
-
-#include <memory>
-#include <string>
-
-#include <base/macros.h>
-
-#include "buffet/commands/object_schema.h"
-#include "buffet/commands/user_role.h"
-
-namespace buffet {
-
-// A simple GCD command definition. This class contains the command category
-// and a full object schema describing the command parameter types and
-// constraints. See comments for CommandDefinitions::LoadCommands for the
-// detailed description of what command categories are and what they are used
-// for.
-class CommandDefinition final {
- public:
- struct Visibility {
- Visibility() = default;
- Visibility(bool is_local, bool is_cloud)
- : local{is_local}, cloud{is_cloud} {}
-
- // Converts a comma-separated string of visibility identifiers into the
- // Visibility bitset (|str| is a string like "local,cloud").
- // Special string value "all" is treated as a list of every possible
- // visibility values and "none" to have all the bits cleared.
- bool FromString(const std::string& str, chromeos::ErrorPtr* error);
-
- // Converts the visibility bitset to a string.
- std::string ToString() const;
-
- static Visibility GetAll() { return Visibility{true, true}; }
- static Visibility GetLocal() { return Visibility{true, false}; }
- static Visibility GetCloud() { return Visibility{false, true}; }
- static Visibility GetNone() { return Visibility{false, false}; }
-
- bool local{false}; // Command is available to local clients.
- bool cloud{false}; // Command is available to cloud clients.
- };
-
- CommandDefinition(const std::string& category,
- std::unique_ptr<const ObjectSchema> parameters,
- std::unique_ptr<const ObjectSchema> progress,
- std::unique_ptr<const ObjectSchema> results);
-
- // Gets the category this command belongs to.
- const std::string& GetCategory() const { return category_; }
- // Gets the object schema for command parameters.
- const ObjectSchema* GetParameters() const { return parameters_.get(); }
- // Gets the object schema for command progress.
- const ObjectSchema* GetProgress() const { return progress_.get(); }
- // Gets the object schema for command results.
- const ObjectSchema* GetResults() const { return results_.get(); }
- // Returns the command visibility.
- const Visibility& GetVisibility() const { return visibility_; }
- // Changes the command visibility.
- void SetVisibility(const Visibility& visibility);
- // Returns the role required to execute command.
- UserRole GetMinimalRole() const { return minimal_role_; }
- // Changes the role required to execute command.
- void SetMinimalRole(UserRole minimal_role) { minimal_role_ = minimal_role; }
-
- private:
- std::string category_; // Cmd category. Could be "powerd" for "base.reboot".
- std::unique_ptr<const ObjectSchema> parameters_; // Command parameters def.
- std::unique_ptr<const ObjectSchema> progress_; // Command progress def.
- std::unique_ptr<const ObjectSchema> results_; // Command results def.
- Visibility visibility_; // Available to all by default.
- // Minimal role required to execute command.
- UserRole minimal_role_{UserRole::kUser};
-
- DISALLOW_COPY_AND_ASSIGN(CommandDefinition);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_COMMAND_DEFINITION_H_
diff --git a/buffet/commands/command_definition_unittest.cc b/buffet/commands/command_definition_unittest.cc
deleted file mode 100644
index e422324..0000000
--- a/buffet/commands/command_definition_unittest.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_definition.h"
-
-#include <gtest/gtest.h>
-
-namespace buffet {
-
-TEST(CommandVisibility, DefaultConstructor) {
- CommandDefinition::Visibility visibility;
- EXPECT_FALSE(visibility.local);
- EXPECT_FALSE(visibility.cloud);
-}
-
-TEST(CommandVisibility, InitialState) {
- auto visibility = CommandDefinition::Visibility::GetAll();
- EXPECT_TRUE(visibility.local);
- EXPECT_TRUE(visibility.cloud);
-
- visibility = CommandDefinition::Visibility::GetLocal();
- EXPECT_TRUE(visibility.local);
- EXPECT_FALSE(visibility.cloud);
-
- visibility = CommandDefinition::Visibility::GetCloud();
- EXPECT_FALSE(visibility.local);
- EXPECT_TRUE(visibility.cloud);
-
- visibility = CommandDefinition::Visibility::GetNone();
- EXPECT_FALSE(visibility.local);
- EXPECT_FALSE(visibility.cloud);
-}
-
-TEST(CommandVisibility, FromString) {
- CommandDefinition::Visibility visibility;
-
- ASSERT_TRUE(visibility.FromString("local", nullptr));
- EXPECT_TRUE(visibility.local);
- EXPECT_FALSE(visibility.cloud);
-
- ASSERT_TRUE(visibility.FromString("cloud", nullptr));
- EXPECT_FALSE(visibility.local);
- EXPECT_TRUE(visibility.cloud);
-
- ASSERT_TRUE(visibility.FromString("cloud,local", nullptr));
- EXPECT_TRUE(visibility.local);
- EXPECT_TRUE(visibility.cloud);
-
- ASSERT_TRUE(visibility.FromString("none", nullptr));
- EXPECT_FALSE(visibility.local);
- EXPECT_FALSE(visibility.cloud);
-
- ASSERT_TRUE(visibility.FromString("all", nullptr));
- EXPECT_TRUE(visibility.local);
- EXPECT_TRUE(visibility.cloud);
-
- ASSERT_TRUE(visibility.FromString("", nullptr));
- EXPECT_FALSE(visibility.local);
- EXPECT_FALSE(visibility.cloud);
-
- chromeos::ErrorPtr error;
- ASSERT_FALSE(visibility.FromString("cloud,all", &error));
- EXPECT_EQ("invalid_parameter_value", error->GetCode());
- EXPECT_EQ("Invalid command visibility value 'all'", error->GetMessage());
-}
-
-TEST(CommandVisibility, ToString) {
- EXPECT_EQ("none", CommandDefinition::Visibility::GetNone().ToString());
- EXPECT_EQ("local", CommandDefinition::Visibility::GetLocal().ToString());
- EXPECT_EQ("cloud", CommandDefinition::Visibility::GetCloud().ToString());
- EXPECT_EQ("all", CommandDefinition::Visibility::GetAll().ToString());
-}
-
-TEST(CommandDefinition, Test) {
- std::unique_ptr<const ObjectSchema> params{ObjectSchema::Create()};
- std::unique_ptr<const ObjectSchema> progress{ObjectSchema::Create()};
- std::unique_ptr<const ObjectSchema> results{ObjectSchema::Create()};
- const ObjectSchema* param_ptr = params.get();
- const ObjectSchema* progress_ptr = progress.get();
- const ObjectSchema* results_ptr = results.get();
- CommandDefinition def{
- "powerd", std::move(params), std::move(progress), std::move(results)};
- EXPECT_EQ("powerd", def.GetCategory());
- EXPECT_EQ(param_ptr, def.GetParameters());
- EXPECT_EQ(progress_ptr, def.GetProgress());
- EXPECT_EQ(results_ptr, def.GetResults());
- EXPECT_EQ("all", def.GetVisibility().ToString());
-
- def.SetVisibility(CommandDefinition::Visibility::GetLocal());
- EXPECT_EQ("local", def.GetVisibility().ToString());
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_dictionary.cc b/buffet/commands/command_dictionary.cc
deleted file mode 100644
index 2de0f36..0000000
--- a/buffet/commands/command_dictionary.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_dictionary.h"
-
-#include <base/values.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/commands/command_definition.h"
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-std::vector<std::string> CommandDictionary::GetCommandNamesByCategory(
- const std::string& category) const {
- std::vector<std::string> names;
- for (const auto& pair : definitions_) {
- if (pair.second->GetCategory() == category)
- names.push_back(pair.first);
- }
- return names;
-}
-
-bool CommandDictionary::LoadCommands(const base::DictionaryValue& json,
- const std::string& category,
- const CommandDictionary* base_commands,
- chromeos::ErrorPtr* error) {
- CommandMap new_defs;
-
- // |json| contains a list of nested objects with the following structure:
- // {"<pkg_name>": {"<cmd_name>": {"parameters": {object_schema}}, ...}, ...}
- // Iterate over packages
- base::DictionaryValue::Iterator package_iter(json);
- while (!package_iter.IsAtEnd()) {
- std::string package_name = package_iter.key();
- const base::DictionaryValue* package_value = nullptr;
- if (!package_iter.value().GetAsDictionary(&package_value)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kTypeMismatch,
- "Expecting an object for package '%s'",
- package_name.c_str());
- return false;
- }
- // Iterate over command definitions within the current package.
- base::DictionaryValue::Iterator command_iter(*package_value);
- while (!command_iter.IsAtEnd()) {
- std::string command_name = command_iter.key();
- if (command_name.empty()) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidCommandName,
- "Unnamed command encountered in package '%s'",
- package_name.c_str());
- return false;
- }
- const base::DictionaryValue* command_def_json = nullptr;
- if (!command_iter.value().GetAsDictionary(&command_def_json)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kDomain,
- errors::commands::kTypeMismatch,
- "Expecting an object for command '%s'",
- command_name.c_str());
- return false;
- }
- // Construct the compound command name as "pkg_name.cmd_name".
- std::string full_command_name =
- chromeos::string_utils::Join(".", package_name, command_name);
-
- const ObjectSchema* base_parameters_def = nullptr;
- const ObjectSchema* base_progress_def = nullptr;
- const ObjectSchema* base_results_def = nullptr;
- // By default make it available to all clients.
- auto visibility = CommandDefinition::Visibility::GetAll();
- UserRole minimal_role{UserRole::kUser};
- if (base_commands) {
- auto cmd = base_commands->FindCommand(full_command_name);
- if (cmd) {
- base_parameters_def = cmd->GetParameters();
- base_progress_def = cmd->GetProgress();
- base_results_def = cmd->GetResults();
- visibility = cmd->GetVisibility();
- minimal_role = cmd->GetMinimalRole();
- }
-
- // If the base command dictionary was provided but the command was not
- // found in it, this must be a custom (vendor) command. GCD spec states
- // that all custom command names must begin with "_". Let's enforce
- // this rule here.
- if (!cmd) {
- if (command_name.front() != '_') {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidCommandName,
- "The name of custom command '%s' in package '%s'"
- " must start with '_'",
- command_name.c_str(), package_name.c_str());
- return false;
- }
- }
- }
-
- auto parameters_schema = BuildObjectSchema(
- command_def_json,
- commands::attributes::kCommand_Parameters,
- base_parameters_def,
- full_command_name,
- error);
- if (!parameters_schema)
- return false;
-
- auto progress_schema = BuildObjectSchema(
- command_def_json, commands::attributes::kCommand_Progress,
- base_progress_def, full_command_name, error);
- if (!progress_schema)
- return false;
-
- auto results_schema = BuildObjectSchema(
- command_def_json,
- commands::attributes::kCommand_Results,
- base_results_def,
- full_command_name,
- error);
- if (!results_schema)
- return false;
-
- std::string value;
- if (command_def_json->GetString(commands::attributes::kCommand_Visibility,
- &value)) {
- if (!visibility.FromString(value, error)) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidCommandVisibility,
- "Error parsing command '%s'", full_command_name.c_str());
- return false;
- }
- }
-
- if (command_def_json->GetString(commands::attributes::kCommand_Role,
- &value)) {
- if (!FromString(value, &minimal_role, error)) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidMinimalRole,
- "Error parsing command '%s'", full_command_name.c_str());
- return false;
- }
- }
-
- std::unique_ptr<CommandDefinition> command_def{
- new CommandDefinition{category,
- std::move(parameters_schema),
- std::move(progress_schema),
- std::move(results_schema)}};
- command_def->SetVisibility(visibility);
- command_def->SetMinimalRole(minimal_role);
- new_defs.emplace(full_command_name, std::move(command_def));
-
- command_iter.Advance();
- }
- package_iter.Advance();
- }
-
- // Verify that newly loaded command definitions do not override existing
- // definitions in another category. This is unlikely, but we don't want to let
- // one vendor daemon to define the same commands already handled by another
- // daemon on the same device.
- for (const auto& pair : new_defs) {
- auto iter = definitions_.find(pair.first);
- CHECK(iter == definitions_.end())
- << "Definition for command '" << pair.first
- << "' overrides an earlier definition in category '"
- << iter->second->GetCategory().c_str() << "'";
- }
-
- // Now that we successfully loaded all the command definitions,
- // remove previous definitions of commands from the same category.
- std::vector<std::string> names = GetCommandNamesByCategory(category);
- for (const std::string& name : names)
- definitions_.erase(name);
-
- // Insert new definitions into the global map.
- for (auto& pair : new_defs)
- definitions_.emplace(pair.first, std::move(pair.second));
- return true;
-}
-
-std::unique_ptr<ObjectSchema> CommandDictionary::BuildObjectSchema(
- const base::DictionaryValue* command_def_json,
- const char* property_name,
- const ObjectSchema* base_def,
- const std::string& command_name,
- chromeos::ErrorPtr* error) {
- auto object_schema = ObjectSchema::Create();
-
- const base::DictionaryValue* schema_def = nullptr;
- if (!command_def_json->GetDictionaryWithoutPathExpansion(property_name,
- &schema_def)) {
- if (base_def)
- return base_def->Clone();
- return object_schema;
- }
-
- if (!object_schema->FromJson(schema_def, base_def, error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Invalid definition for command '%s'",
- command_name.c_str());
- return {};
- }
-
- return object_schema;
-}
-
-std::unique_ptr<base::DictionaryValue> CommandDictionary::GetCommandsAsJson(
- const std::function<bool(const CommandDefinition*)>& filter,
- bool full_schema,
- chromeos::ErrorPtr* error) const {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- for (const auto& pair : definitions_) {
- // Check if the command definition has the desired visibility.
- // If not, then skip it.
- if (!filter(pair.second.get()))
- continue;
-
- std::unique_ptr<base::DictionaryValue> parameters =
- pair.second->GetParameters()->ToJson(full_schema, error);
- if (!parameters)
- return {};
- // Progress and results are not part of public commandDefs.
-
- auto cmd_name_parts = chromeos::string_utils::SplitAtFirst(pair.first, ".");
- std::string package_name = cmd_name_parts.first;
- std::string command_name = cmd_name_parts.second;
- base::DictionaryValue* package = nullptr;
- if (!dict->GetDictionaryWithoutPathExpansion(package_name, &package)) {
- // If this is the first time we encounter this package, create a JSON
- // object for it.
- package = new base::DictionaryValue;
- dict->SetWithoutPathExpansion(package_name, package);
- }
- base::DictionaryValue* command_def = new base::DictionaryValue;
- command_def->Set(commands::attributes::kCommand_Parameters,
- parameters.release());
- command_def->SetString(commands::attributes::kCommand_Role,
- ToString(pair.second->GetMinimalRole()));
- package->SetWithoutPathExpansion(command_name, command_def);
- }
- return dict;
-}
-
-const CommandDefinition* CommandDictionary::FindCommand(
- const std::string& command_name) const {
- auto pair = definitions_.find(command_name);
- return (pair != definitions_.end()) ? pair->second.get() : nullptr;
-}
-
-CommandDefinition* CommandDictionary::FindCommand(
- const std::string& command_name) {
- auto pair = definitions_.find(command_name);
- return (pair != definitions_.end()) ? pair->second.get() : nullptr;
-}
-
-void CommandDictionary::Clear() {
- definitions_.clear();
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_dictionary.h b/buffet/commands/command_dictionary.h
deleted file mode 100644
index 97ab596..0000000
--- a/buffet/commands/command_dictionary.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_COMMAND_DICTIONARY_H_
-#define BUFFET_COMMANDS_COMMAND_DICTIONARY_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/command_definition.h"
-
-namespace base {
-class Value;
-class DictionaryValue;
-} // namespace base
-
-namespace buffet {
-
-class ObjectSchema;
-
-// CommandDictionary is a wrapper around a map of command name and the
-// corresponding command definition schema. The command name (the key in
-// the map) is a compound name in a form of "package_name.command_name",
-// where "package_name" is a name of command package such as "base", "printers",
-// and others. So the full command name could be "base.reboot", for example.
-class CommandDictionary final {
- public:
- CommandDictionary() = default;
-
- // Gets the list of names of commands that belong to the given category.
- std::vector<std::string> GetCommandNamesByCategory(
- const std::string& category) const;
-
- // Loads command definitions from a JSON object. This is done at the daemon
- // startup and whenever a device daemon decides to update its command list.
- // |json| is a JSON dictionary that describes the complete commands contained
- // in a particular |category|. Usually, |categories| are 1:1 with daemons on
- // a device. For instance, the power manager daemon might provide a category
- // "power_man" that provides the "base.reboot" and "base.shutdown" commands.
- // However, nothing prohibits a daemon providing commands in two categories.
- // When LoadCommands is called, all previous definitions of commands from the
- // same category are removed, effectively replacing all the commands in the
- // given category.
- // Optional |base_commands| parameter specifies the definition of standard
- // GCD commands for parameter schema validation. Can be set to nullptr if
- // no validation is needed.
- // Returns false on failure and |error| provides additional error information
- // when provided.
- bool LoadCommands(const base::DictionaryValue& json,
- const std::string& category,
- const CommandDictionary* base_commands,
- chromeos::ErrorPtr* error);
- // Converts all the command definitions to a JSON object for CDD/Device
- // draft.
- // |filter| is a predicate used to filter out the command definitions to
- // be returned by this method. Only command definitions for which the
- // predicate returns true will be included in the resulting JSON.
- // |full_schema| specifies whether full command definitions must be generated
- // (true) for CDD or only overrides from the base schema (false).
- // Returns empty unique_ptr in case of an error and fills in the additional
- // error details in |error|.
- std::unique_ptr<base::DictionaryValue> GetCommandsAsJson(
- const std::function<bool(const CommandDefinition*)>& filter,
- bool full_schema,
- chromeos::ErrorPtr* error) const;
- // Returns the number of command definitions in the dictionary.
- size_t GetSize() const { return definitions_.size(); }
- // Checks if the dictionary has no command definitions.
- bool IsEmpty() const { return definitions_.empty(); }
- // Remove all the command definitions from the dictionary.
- void Clear();
- // Finds a definition for the given command.
- const CommandDefinition* FindCommand(const std::string& command_name) const;
- CommandDefinition* FindCommand(const std::string& command_name);
-
- private:
- using CommandMap = std::map<std::string, std::unique_ptr<CommandDefinition>>;
-
- std::unique_ptr<ObjectSchema> BuildObjectSchema(
- const base::DictionaryValue* command_def_json,
- const char* property_name,
- const ObjectSchema* base_def,
- const std::string& command_name,
- chromeos::ErrorPtr* error);
-
- CommandMap definitions_; // List of all available command definitions.
- DISALLOW_COPY_AND_ASSIGN(CommandDictionary);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_COMMAND_DICTIONARY_H_
diff --git a/buffet/commands/command_dictionary_unittest.cc b/buffet/commands/command_dictionary_unittest.cc
deleted file mode 100644
index 7b649a5..0000000
--- a/buffet/commands/command_dictionary_unittest.cc
+++ /dev/null
@@ -1,587 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_dictionary.h"
-
-#include <gtest/gtest.h>
-
-#include "buffet/commands/unittest_utils.h"
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-using unittests::IsEqualValue;
-
-TEST(CommandDictionary, Empty) {
- CommandDictionary dict;
- EXPECT_TRUE(dict.IsEmpty());
- EXPECT_EQ(nullptr, dict.FindCommand("robot.jump"));
- EXPECT_TRUE(dict.GetCommandNamesByCategory("robotd").empty());
-}
-
-TEST(CommandDictionary, LoadCommands) {
- auto json = CreateDictionaryValue(R"({
- 'robot': {
- 'jump': {
- 'parameters': {
- 'height': 'integer',
- '_jumpType': ['_withAirFlip', '_withSpin', '_withKick']
- },
- 'progress': {
- 'progress': 'integer'
- },
- 'results': {}
- }
- }
- })");
- CommandDictionary dict;
- EXPECT_TRUE(dict.LoadCommands(*json, "robotd", nullptr, nullptr));
- EXPECT_EQ(1, dict.GetSize());
- EXPECT_NE(nullptr, dict.FindCommand("robot.jump"));
- json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'}
- },
- 'shutdown': {
- }
- }
- })");
- EXPECT_TRUE(dict.LoadCommands(*json, "powerd", nullptr, nullptr));
- EXPECT_EQ(3, dict.GetSize());
- EXPECT_NE(nullptr, dict.FindCommand("robot.jump"));
- EXPECT_NE(nullptr, dict.FindCommand("base.reboot"));
- EXPECT_NE(nullptr, dict.FindCommand("base.shutdown"));
- EXPECT_EQ(nullptr, dict.FindCommand("foo.bar"));
- std::vector<std::string> expected_commands{"base.reboot", "base.shutdown"};
- EXPECT_EQ(expected_commands, dict.GetCommandNamesByCategory("powerd"));
-}
-
-TEST(CommandDictionary, LoadWithInheritance) {
- auto json = CreateDictionaryValue(R"({
- 'robot': {
- 'jump': {
- 'minimalRole': 'viewer',
- 'visibility':'local',
- 'parameters': {
- 'height': 'integer'
- },
- 'progress': {
- 'progress': 'integer'
- },
- 'results': {
- 'success': 'boolean'
- }
- }
- }
- })");
- CommandDictionary base_dict;
- EXPECT_TRUE(base_dict.LoadCommands(*json, "test1", nullptr, nullptr));
- EXPECT_EQ(1, base_dict.GetSize());
- json = CreateDictionaryValue(R"({'robot': {'jump': {}}})");
-
- CommandDictionary dict;
- EXPECT_TRUE(dict.LoadCommands(*json, "test2", &base_dict, nullptr));
- EXPECT_EQ(1, dict.GetSize());
-
- auto cmd = dict.FindCommand("robot.jump");
- EXPECT_NE(nullptr, cmd);
-
- EXPECT_EQ("local", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kViewer, cmd->GetMinimalRole());
-
- EXPECT_JSON_EQ("{'height': {'type': 'integer'}}",
- *cmd->GetParameters()->ToJson(true, nullptr));
- EXPECT_JSON_EQ("{'progress': {'type': 'integer'}}",
- *cmd->GetProgress()->ToJson(true, nullptr));
- EXPECT_JSON_EQ("{'success': {'type': 'boolean'}}",
- *cmd->GetResults()->ToJson(true, nullptr));
-}
-
-TEST(CommandDictionary, LoadCommands_Failures) {
- CommandDictionary dict;
- chromeos::ErrorPtr error;
-
- // Command definition is not an object.
- auto json = CreateDictionaryValue("{'robot':{'jump':0}}");
- EXPECT_FALSE(dict.LoadCommands(*json, "robotd", nullptr, &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- EXPECT_EQ("Expecting an object for command 'jump'", error->GetMessage());
- error.reset();
-
- // Package definition is not an object.
- json = CreateDictionaryValue("{'robot':'blah'}");
- EXPECT_FALSE(dict.LoadCommands(*json, "robotd", nullptr, &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- EXPECT_EQ("Expecting an object for package 'robot'", error->GetMessage());
- error.reset();
-
- // Invalid command definition is not an object.
- json = CreateDictionaryValue(
- "{'robot':{'jump':{'parameters':{'flip':0},'results':{}}}}");
- EXPECT_FALSE(dict.LoadCommands(*json, "robotd", nullptr, &error));
- EXPECT_EQ("invalid_object_schema", error->GetCode());
- EXPECT_EQ("Invalid definition for command 'robot.jump'", error->GetMessage());
- EXPECT_NE(nullptr, error->GetInnerError()); // Must have additional info.
- error.reset();
-
- // Empty command name.
- json = CreateDictionaryValue("{'robot':{'':{'parameters':{},'results':{}}}}");
- EXPECT_FALSE(dict.LoadCommands(*json, "robotd", nullptr, &error));
- EXPECT_EQ("invalid_command_name", error->GetCode());
- EXPECT_EQ("Unnamed command encountered in package 'robot'",
- error->GetMessage());
- error.reset();
-}
-
-TEST(CommandDictionaryDeathTest, LoadCommands_RedefineInDifferentCategory) {
- // Redefine commands in different category.
- CommandDictionary dict;
- chromeos::ErrorPtr error;
- auto json = CreateDictionaryValue("{'robot':{'jump':{}}}");
- dict.LoadCommands(*json, "category1", nullptr, &error);
- ASSERT_DEATH(dict.LoadCommands(*json, "category2", nullptr, &error),
- ".*Definition for command 'robot.jump' overrides an "
- "earlier definition in category 'category1'");
-}
-
-TEST(CommandDictionary, LoadCommands_CustomCommandNaming) {
- // Custom command must start with '_'.
- CommandDictionary base_dict;
- CommandDictionary dict;
- chromeos::ErrorPtr error;
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {}
- }
- }
- })");
- base_dict.LoadCommands(*json, "", nullptr, &error);
- EXPECT_TRUE(dict.LoadCommands(*json, "robotd", &base_dict, &error));
- auto json2 = CreateDictionaryValue(
- "{'base':{'jump':{'parameters':{},'results':{}}}}");
- EXPECT_FALSE(dict.LoadCommands(*json2, "robotd", &base_dict, &error));
- EXPECT_EQ("invalid_command_name", error->GetCode());
- EXPECT_EQ("The name of custom command 'jump' in package 'base' must start "
- "with '_'", error->GetMessage());
- error.reset();
-
- // If the command starts with "_", then it's Ok.
- json2 = CreateDictionaryValue(
- "{'base':{'_jump':{'parameters':{},'results':{}}}}");
- EXPECT_TRUE(dict.LoadCommands(*json2, "robotd", &base_dict, nullptr));
-}
-
-TEST(CommandDictionary, LoadCommands_RedefineStdCommand) {
- // Redefine commands parameter type.
- CommandDictionary base_dict;
- CommandDictionary dict;
- chromeos::ErrorPtr error;
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {'version': 'integer'}
- }
- }
- })");
- base_dict.LoadCommands(*json, "", nullptr, &error);
-
- auto json2 = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'string'},
- 'results': {'version': 'integer'}
- }
- }
- })");
- EXPECT_FALSE(dict.LoadCommands(*json2, "robotd", &base_dict, &error));
- EXPECT_EQ("invalid_object_schema", error->GetCode());
- EXPECT_EQ("Invalid definition for command 'base.reboot'",
- error->GetMessage());
- EXPECT_EQ("invalid_parameter_definition", error->GetInnerError()->GetCode());
- EXPECT_EQ("Error in definition of property 'delay'",
- error->GetInnerError()->GetMessage());
- EXPECT_EQ("param_type_changed", error->GetFirstError()->GetCode());
- EXPECT_EQ("Redefining a property of type integer as string",
- error->GetFirstError()->GetMessage());
- error.reset();
-
- auto json3 = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {'version': 'string'}
- }
- }
- })");
- EXPECT_FALSE(dict.LoadCommands(*json3, "robotd", &base_dict, &error));
- EXPECT_EQ("invalid_object_schema", error->GetCode());
- EXPECT_EQ("Invalid definition for command 'base.reboot'",
- error->GetMessage());
- // TODO(antonm): remove parameter from error below and use some generic.
- EXPECT_EQ("invalid_parameter_definition", error->GetInnerError()->GetCode());
- EXPECT_EQ("Error in definition of property 'version'",
- error->GetInnerError()->GetMessage());
- EXPECT_EQ("param_type_changed", error->GetFirstError()->GetCode());
- EXPECT_EQ("Redefining a property of type integer as string",
- error->GetFirstError()->GetMessage());
- error.reset();
-}
-
-TEST(CommandDictionary, GetCommandsAsJson) {
- auto json_base = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': {'maximum': 100}},
- 'results': {}
- },
- 'shutdown': {
- 'parameters': {},
- 'results': {}
- }
- }
- })");
- CommandDictionary base_dict;
- base_dict.LoadCommands(*json_base, "base", nullptr, nullptr);
-
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': {'minimum': 10}},
- 'results': {}
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {'_height': 'integer'},
- 'results': {}
- }
- }
- })");
- CommandDictionary dict;
- dict.LoadCommands(*json, "device", &base_dict, nullptr);
-
- json = dict.GetCommandsAsJson(
- [](const CommandDefinition* def) { return true; }, false, nullptr);
- ASSERT_NE(nullptr, json.get());
- auto expected = R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': {'minimum': 10}},
- 'minimalRole': 'user'
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {'_height': 'integer'},
- 'minimalRole': 'user'
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *json);
-
- json = dict.GetCommandsAsJson(
- [](const CommandDefinition* def) { return true; }, true, nullptr);
- ASSERT_NE(nullptr, json.get());
- expected = R"({
- 'base': {
- 'reboot': {
- 'parameters': {
- 'delay': {
- 'maximum': 100,
- 'minimum': 10,
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {
- '_height': {
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *json);
-}
-
-TEST(CommandDictionary, GetCommandsAsJsonWithVisibility) {
- auto json = CreateDictionaryValue(R"({
- 'test': {
- 'command1': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'none'
- },
- 'command2': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'local'
- },
- 'command3': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'cloud'
- },
- 'command4': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'all'
- },
- 'command5': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'none'
- },
- 'command6': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'local'
- },
- 'command7': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'cloud'
- },
- 'command8': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'all'
- }
- }
- })");
- CommandDictionary dict;
- ASSERT_TRUE(dict.LoadCommands(*json, "test", nullptr, nullptr));
-
- json = dict.GetCommandsAsJson(
- [](const CommandDefinition* def) { return true; }, false, nullptr);
- ASSERT_NE(nullptr, json.get());
- auto expected = R"({
- 'test': {
- 'command1': {'parameters': {}, 'minimalRole': 'user'},
- 'command2': {'parameters': {}, 'minimalRole': 'user'},
- 'command3': {'parameters': {}, 'minimalRole': 'user'},
- 'command4': {'parameters': {}, 'minimalRole': 'user'},
- 'command5': {'parameters': {}, 'minimalRole': 'user'},
- 'command6': {'parameters': {}, 'minimalRole': 'user'},
- 'command7': {'parameters': {}, 'minimalRole': 'user'},
- 'command8': {'parameters': {}, 'minimalRole': 'user'}
- }
- })";
- EXPECT_JSON_EQ(expected, *json);
-
- json = dict.GetCommandsAsJson(
- [](const CommandDefinition* def) { return def->GetVisibility().local; },
- false, nullptr);
- ASSERT_NE(nullptr, json.get());
- expected = R"({
- 'test': {
- 'command2': {'parameters': {}, 'minimalRole': 'user'},
- 'command4': {'parameters': {}, 'minimalRole': 'user'},
- 'command6': {'parameters': {}, 'minimalRole': 'user'},
- 'command8': {'parameters': {}, 'minimalRole': 'user'}
- }
- })";
- EXPECT_JSON_EQ(expected, *json);
-
- json = dict.GetCommandsAsJson(
- [](const CommandDefinition* def) { return def->GetVisibility().cloud; },
- false, nullptr);
- ASSERT_NE(nullptr, json.get());
- expected = R"({
- 'test': {
- 'command3': {'parameters': {}, 'minimalRole': 'user'},
- 'command4': {'parameters': {}, 'minimalRole': 'user'},
- 'command7': {'parameters': {}, 'minimalRole': 'user'},
- 'command8': {'parameters': {}, 'minimalRole': 'user'}
- }
- })";
- EXPECT_JSON_EQ(expected, *json);
-
- json = dict.GetCommandsAsJson(
- [](const CommandDefinition* def) {
- return def->GetVisibility().local && def->GetVisibility().cloud;
- }, false, nullptr);
- ASSERT_NE(nullptr, json.get());
- expected = R"({
- 'test': {
- 'command4': {'parameters': {}, 'minimalRole': 'user'},
- 'command8': {'parameters': {}, 'minimalRole': 'user'}
- }
- })";
- EXPECT_JSON_EQ(expected, *json);
-}
-
-TEST(CommandDictionary, LoadWithPermissions) {
- CommandDictionary base_dict;
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'command1': {
- 'parameters': {},
- 'results': {},
- 'visibility':'none'
- },
- 'command2': {
- 'minimalRole': 'viewer',
- 'parameters': {},
- 'results': {},
- 'visibility':'local'
- },
- 'command3': {
- 'minimalRole': 'user',
- 'parameters': {},
- 'results': {},
- 'visibility':'cloud'
- },
- 'command4': {
- 'minimalRole': 'manager',
- 'parameters': {},
- 'results': {},
- 'visibility':'all'
- },
- 'command5': {
- 'minimalRole': 'owner',
- 'parameters': {},
- 'results': {},
- 'visibility':'local,cloud'
- }
- }
- })");
- EXPECT_TRUE(base_dict.LoadCommands(*json, "testd", nullptr, nullptr));
-
- auto cmd = base_dict.FindCommand("base.command1");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("none", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kUser, cmd->GetMinimalRole());
-
- cmd = base_dict.FindCommand("base.command2");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("local", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kViewer, cmd->GetMinimalRole());
-
- cmd = base_dict.FindCommand("base.command3");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("cloud", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kUser, cmd->GetMinimalRole());
-
- cmd = base_dict.FindCommand("base.command4");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("all", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kManager, cmd->GetMinimalRole());
-
- cmd = base_dict.FindCommand("base.command5");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("all", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kOwner, cmd->GetMinimalRole());
-
- CommandDictionary dict;
- json = CreateDictionaryValue(R"({
- 'base': {
- 'command1': {
- 'parameters': {},
- 'results': {}
- },
- 'command2': {
- 'parameters': {},
- 'results': {}
- },
- 'command3': {
- 'parameters': {},
- 'results': {}
- },
- 'command4': {
- 'parameters': {},
- 'results': {}
- },
- 'command5': {
- 'parameters': {},
- 'results': {}
- },
- '_command6': {
- 'parameters': {},
- 'results': {}
- }
- }
- })");
- EXPECT_TRUE(dict.LoadCommands(*json, "testd", &base_dict, nullptr));
-
- cmd = dict.FindCommand("base.command1");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("none", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kUser, cmd->GetMinimalRole());
-
- cmd = dict.FindCommand("base.command2");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("local", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kViewer, cmd->GetMinimalRole());
-
- cmd = dict.FindCommand("base.command3");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("cloud", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kUser, cmd->GetMinimalRole());
-
- cmd = dict.FindCommand("base.command4");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("all", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kManager, cmd->GetMinimalRole());
-
- cmd = dict.FindCommand("base.command5");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("all", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kOwner, cmd->GetMinimalRole());
-
- cmd = dict.FindCommand("base._command6");
- ASSERT_NE(nullptr, cmd);
- EXPECT_EQ("all", cmd->GetVisibility().ToString());
- EXPECT_EQ(UserRole::kUser, cmd->GetMinimalRole());
-}
-
-TEST(CommandDictionary, LoadWithPermissions_InvalidVisibility) {
- CommandDictionary dict;
- chromeos::ErrorPtr error;
-
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'jump': {
- 'parameters': {},
- 'results': {},
- 'visibility':'foo'
- }
- }
- })");
- EXPECT_FALSE(dict.LoadCommands(*json, "testd", nullptr, &error));
- EXPECT_EQ("invalid_command_visibility", error->GetCode());
- EXPECT_EQ("invalid_parameter_value", error->GetInnerError()->GetCode());
- error.reset();
-}
-
-TEST(CommandDictionary, LoadWithPermissions_InvalidRole) {
- CommandDictionary dict;
- chromeos::ErrorPtr error;
-
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'jump': {
- 'parameters': {},
- 'results': {},
- 'visibility':'local,cloud',
- 'minimalRole':'foo'
- }
- }
- })");
- EXPECT_FALSE(dict.LoadCommands(*json, "testd", nullptr, &error));
- EXPECT_EQ("invalid_minimal_role", error->GetCode());
- EXPECT_EQ("invalid_parameter_value", error->GetInnerError()->GetCode());
- error.reset();
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_instance.cc b/buffet/commands/command_instance.cc
deleted file mode 100644
index a2e098f..0000000
--- a/buffet/commands/command_instance.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_instance.h"
-
-#include <base/values.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/errors/error_codes.h>
-
-#include "buffet/commands/command_definition.h"
-#include "buffet/commands/command_dictionary.h"
-#include "buffet/commands/command_proxy_interface.h"
-#include "buffet/commands/command_queue.h"
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/schema_constants.h"
-#include "buffet/commands/schema_utils.h"
-
-namespace buffet {
-
-const char CommandInstance::kStatusQueued[] = "queued";
-const char CommandInstance::kStatusInProgress[] = "inProgress";
-const char CommandInstance::kStatusPaused[] = "paused";
-const char CommandInstance::kStatusError[] = "error";
-const char CommandInstance::kStatusDone[] = "done";
-const char CommandInstance::kStatusCancelled[] = "cancelled";
-const char CommandInstance::kStatusAborted[] = "aborted";
-const char CommandInstance::kStatusExpired[] = "expired";
-
-CommandInstance::CommandInstance(const std::string& name,
- const std::string& origin,
- const CommandDefinition* command_definition,
- const native_types::Object& parameters)
- : name_{name},
- origin_{origin},
- command_definition_{command_definition},
- parameters_{parameters} {
- CHECK(command_definition_);
-}
-
-CommandInstance::~CommandInstance() = default;
-
-const std::string& CommandInstance::GetCategory() const {
- return command_definition_->GetCategory();
-}
-
-const PropValue* CommandInstance::FindParameter(const std::string& name) const {
- auto p = parameters_.find(name);
- return (p != parameters_.end()) ? p->second.get() : nullptr;
-}
-
-namespace {
-
-// Helper method to retrieve command parameters from the command definition
-// object passed in as |json| and corresponding command definition schema
-// specified in |command_def|.
-// On success, returns |true| and the validated parameters and values through
-// |parameters|. Otherwise returns |false| and additional error information in
-// |error|.
-bool GetCommandParameters(const base::DictionaryValue* json,
- const CommandDefinition* command_def,
- native_types::Object* parameters,
- chromeos::ErrorPtr* error) {
- // Get the command parameters from 'parameters' property.
- base::DictionaryValue no_params; // Placeholder when no params are specified.
- const base::DictionaryValue* params = nullptr;
- const base::Value* params_value = nullptr;
- if (json->Get(commands::attributes::kCommand_Parameters, ¶ms_value)) {
- // Make sure the "parameters" property is actually an object.
- if (!params_value->GetAsDictionary(¶ms)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- chromeos::errors::json::kDomain,
- chromeos::errors::json::kObjectExpected,
- "Property '%s' must be a JSON object",
- commands::attributes::kCommand_Parameters);
- return false;
- }
- } else {
- // "parameters" are not specified. Assume empty param list.
- params = &no_params;
- }
-
- // Now read in the parameters and validate their values against the command
- // definition schema.
- ObjectPropType obj_prop_type;
- obj_prop_type.SetObjectSchema(command_def->GetParameters()->Clone());
- if (!TypedValueFromJson(params, &obj_prop_type, parameters, error)) {
- return false;
- }
- return true;
-}
-
-} // anonymous namespace
-
-std::unique_ptr<CommandInstance> CommandInstance::FromJson(
- const base::Value* value,
- const std::string& origin,
- const CommandDictionary& dictionary,
- std::string* command_id,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<CommandInstance> instance;
- std::string command_id_buffer; // used if |command_id| was nullptr.
- if (!command_id)
- command_id = &command_id_buffer;
-
- // Get the command JSON object from the value.
- const base::DictionaryValue* json = nullptr;
- if (!value->GetAsDictionary(&json)) {
- chromeos::Error::AddTo(error, FROM_HERE, chromeos::errors::json::kDomain,
- chromeos::errors::json::kObjectExpected,
- "Command instance is not a JSON object");
- command_id->clear();
- return instance;
- }
-
- // Get the command ID from 'id' property.
- if (!json->GetString(commands::attributes::kCommand_Id, command_id))
- command_id->clear();
-
- // Get the command name from 'name' property.
- std::string command_name;
- if (!json->GetString(commands::attributes::kCommand_Name, &command_name)) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kPropertyMissing,
- "Command name is missing");
- return instance;
- }
- // Make sure we know how to handle the command with this name.
- auto command_def = dictionary.FindCommand(command_name);
- if (!command_def) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidCommandName,
- "Unknown command received: %s",
- command_name.c_str());
- return instance;
- }
-
- native_types::Object parameters;
- if (!GetCommandParameters(json, command_def, ¶meters, error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kCommandFailed,
- "Failed to validate command '%s'",
- command_name.c_str());
- return instance;
- }
-
- instance.reset(
- new CommandInstance{command_name, origin, command_def, parameters});
-
- if (!command_id->empty())
- instance->SetID(*command_id);
-
- return instance;
-}
-
-std::unique_ptr<base::DictionaryValue> CommandInstance::ToJson() const {
- std::unique_ptr<base::DictionaryValue> json{new base::DictionaryValue};
-
- json->SetString(commands::attributes::kCommand_Id, id_);
- json->SetString(commands::attributes::kCommand_Name, name_);
- json->Set(commands::attributes::kCommand_Parameters,
- TypedValueToJson(parameters_, nullptr).release());
- json->Set(commands::attributes::kCommand_Progress,
- TypedValueToJson(progress_, nullptr).release());
- json->Set(commands::attributes::kCommand_Results,
- TypedValueToJson(results_, nullptr).release());
- json->SetString(commands::attributes::kCommand_State, status_);
-
- return json;
-}
-
-void CommandInstance::AddProxy(std::unique_ptr<CommandProxyInterface> proxy) {
- proxies_.push_back(std::move(proxy));
-}
-
-bool CommandInstance::SetResults(const native_types::Object& results) {
- // TODO(antonm): Add validation.
- if (results != results_) {
- results_ = results;
- for (auto& proxy : proxies_) {
- proxy->OnResultsChanged();
- }
- }
- return true;
-}
-
-bool CommandInstance::SetProgress(const native_types::Object& progress) {
- // Change status even if progress unchanged, e.g. 0% -> 0%.
- SetStatus(kStatusInProgress);
- if (progress != progress_) {
- progress_ = progress;
- for (auto& proxy : proxies_) {
- proxy->OnProgressChanged();
- }
- }
- return true;
-}
-
-void CommandInstance::Abort() {
- SetStatus(kStatusAborted);
- RemoveFromQueue();
- // The command will be destroyed after that, so do not access any members.
-}
-
-void CommandInstance::Cancel() {
- SetStatus(kStatusCancelled);
- RemoveFromQueue();
- // The command will be destroyed after that, so do not access any members.
-}
-
-void CommandInstance::Done() {
- SetStatus(kStatusDone);
- RemoveFromQueue();
- // The command will be destroyed after that, so do not access any members.
-}
-
-void CommandInstance::SetStatus(const std::string& status) {
- if (status != status_) {
- status_ = status;
- for (auto& proxy : proxies_) {
- proxy->OnStatusChanged();
- }
- }
-}
-
-void CommandInstance::RemoveFromQueue() {
- if (queue_)
- queue_->DelayedRemove(GetID());
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_instance.h b/buffet/commands/command_instance.h
deleted file mode 100644
index 6ce7036..0000000
--- a/buffet/commands/command_instance.h
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_COMMAND_INSTANCE_H_
-#define BUFFET_COMMANDS_COMMAND_INSTANCE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_utils.h"
-
-namespace base {
-class Value;
-} // namespace base
-
-namespace buffet {
-
-class CommandDefinition;
-class CommandDictionary;
-class CommandProxyInterface;
-class CommandQueue;
-
-class CommandInstance final {
- public:
- // Construct a command instance given the full command |name| which must
- // be in format "<package_name>.<command_name>", a command |category| and
- // a list of parameters and their values specified in |parameters|.
- CommandInstance(const std::string& name,
- const std::string& origin,
- const CommandDefinition* command_definition,
- const native_types::Object& parameters);
- ~CommandInstance();
-
- // Returns the full command ID.
- const std::string& GetID() const { return id_; }
- // Returns the full name of the command.
- const std::string& GetName() const { return name_; }
- // Returns the command category.
- const std::string& GetCategory() const;
- // Returns the command parameters and their values.
- const native_types::Object& GetParameters() const { return parameters_; }
- // Returns the command results and their values.
- const native_types::Object& GetResults() const { return results_; }
- // Finds a command parameter value by parameter |name|. If the parameter
- // with given name does not exist, returns nullptr.
- const PropValue* FindParameter(const std::string& name) const;
- // Returns the full name of the command.
- const std::string& GetOrigin() const { return origin_; }
-
- // Returns command definition.
- const CommandDefinition* GetCommandDefinition() const {
- return command_definition_;
- }
-
- // Parses a command instance JSON definition and constructs a CommandInstance
- // object, checking the JSON |value| against the command definition schema
- // found in command |dictionary|. On error, returns null unique_ptr and
- // fills in error details in |error|.
- // |command_id| is the ID of the command returned, as parsed from the |value|.
- // The command ID extracted (if present in the JSON object) even if other
- // parsing/validation error occurs and command instance is not constructed.
- // This is used to report parse failures back to the server.
- static std::unique_ptr<CommandInstance> FromJson(
- const base::Value* value,
- const std::string& origin,
- const CommandDictionary& dictionary,
- std::string* command_id,
- chromeos::ErrorPtr* error);
-
- // Returns JSON representation of the command.
- std::unique_ptr<base::DictionaryValue> ToJson() const;
-
- // Sets the command ID (normally done by CommandQueue when the command
- // instance is added to it).
- void SetID(const std::string& id) { id_ = id; }
- // Adds a proxy for this command.
- // The proxy object is not owned by this class.
- void AddProxy(std::unique_ptr<CommandProxyInterface> proxy);
- // Sets the pointer to queue this command is part of.
- void SetCommandQueue(CommandQueue* queue) { queue_ = queue; }
-
- // Updates the command progress. The |progress| should match the schema.
- // Returns false if |results| value is incorrect.
- bool SetProgress(const native_types::Object& progress);
-
- // Updates the command results. The |results| should match the schema.
- // Returns false if |results| value is incorrect.
- bool SetResults(const native_types::Object& results);
-
- // Aborts command execution.
- void Abort();
- // Cancels command execution.
- void Cancel();
- // Marks the command as completed successfully.
- void Done();
-
- // Command state getters.
- const native_types::Object& GetProgress() const { return progress_; }
- const std::string& GetStatus() const { return status_; }
-
- // Values for command execution status.
- static const char kStatusQueued[];
- static const char kStatusInProgress[];
- static const char kStatusPaused[];
- static const char kStatusError[];
- static const char kStatusDone[];
- static const char kStatusCancelled[];
- static const char kStatusAborted[];
- static const char kStatusExpired[];
-
- private:
- // Helper function to update the command status.
- // Used by Abort(), Cancel(), Done() methods.
- void SetStatus(const std::string& status);
- // Helper method that removes this command from the command queue.
- // Note that since the command queue owns the lifetime of the command instance
- // object, removing a command from the queue will also destroy it.
- void RemoveFromQueue();
-
- // Unique command ID within a command queue.
- std::string id_;
- // Full command name as "<package_name>.<command_name>".
- std::string name_;
- // The origin of the command, either "local" or "cloud".
- std::string origin_;
- // Command definition.
- const CommandDefinition* command_definition_;
- // Command parameters and their values.
- native_types::Object parameters_;
- // Current command execution progress.
- native_types::Object progress_;
- // Command results.
- native_types::Object results_;
- // Current command status.
- std::string status_ = kStatusQueued;
- // Command proxies for the command.
- std::vector<std::unique_ptr<CommandProxyInterface>> proxies_;
- // Pointer to the command queue this command instance is added to.
- // The queue owns the command instance, so it outlives this object.
- CommandQueue* queue_ = nullptr;
-
- friend class DBusCommandDispacherTest;
- friend class DBusCommandProxyTest;
- DISALLOW_COPY_AND_ASSIGN(CommandInstance);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_COMMAND_INSTANCE_H_
diff --git a/buffet/commands/command_instance_unittest.cc b/buffet/commands/command_instance_unittest.cc
deleted file mode 100644
index f7744b0..0000000
--- a/buffet/commands/command_instance_unittest.cc
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_instance.h"
-
-#include <gtest/gtest.h>
-
-#include "buffet/commands/command_dictionary.h"
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/schema_utils.h"
-#include "buffet/commands/unittest_utils.h"
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-using unittests::CreateValue;
-
-namespace {
-
-class CommandInstanceTest : public ::testing::Test {
- protected:
- void SetUp() override {
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {},
- 'results': {}
- }
- },
- 'robot': {
- 'jump': {
- 'parameters': {
- 'height': {
- 'type': 'integer',
- 'minimum': 0,
- 'maximum': 100
- },
- '_jumpType': {
- 'type': 'string',
- 'enum': ['_withAirFlip', '_withSpin', '_withKick']
- }
- },
- 'results': {}
- },
- 'speak': {
- 'parameters': {
- 'phrase': {
- 'type': 'string',
- 'enum': ['beamMeUpScotty', 'iDontDigOnSwine',
- 'iPityDaFool', 'dangerWillRobinson']
- },
- 'volume': {
- 'type': 'integer',
- 'minimum': 0,
- 'maximum': 10
- }
- },
- 'results': {}
- }
- }
- })");
- CHECK(dict_.LoadCommands(*json, "robotd", nullptr, nullptr))
- << "Failed to parse test command dictionary";
- }
- CommandDictionary dict_;
-};
-
-} // anonymous namespace
-
-TEST_F(CommandInstanceTest, Test) {
- StringPropType str_prop;
- IntPropType int_prop;
- native_types::Object params;
- params["phrase"] = str_prop.CreateValue(std::string("iPityDaFool"),
- nullptr);
- params["volume"] = int_prop.CreateValue(5, nullptr);
- CommandInstance instance{
- "robot.speak", "cloud", dict_.FindCommand("robot.speak"), params};
-
- native_types::Object results;
- results["foo"] = int_prop.CreateValue(239, nullptr);
- instance.SetResults(results);
-
- EXPECT_EQ("", instance.GetID());
- EXPECT_EQ("robot.speak", instance.GetName());
- EXPECT_EQ("robotd", instance.GetCategory());
- EXPECT_EQ("cloud", instance.GetOrigin());
- EXPECT_EQ(params, instance.GetParameters());
- EXPECT_EQ("iPityDaFool",
- instance.FindParameter("phrase")->GetString()->GetValue());
- EXPECT_EQ(5, instance.FindParameter("volume")->GetInt()->GetValue());
- EXPECT_EQ(nullptr, instance.FindParameter("blah"));
- EXPECT_EQ(results, instance.GetResults());
-
- CommandInstance instance2{
- "base.reboot", "local", dict_.FindCommand("base.reboot"), {}};
- EXPECT_EQ("local", instance2.GetOrigin());
-}
-
-TEST_F(CommandInstanceTest, SetID) {
- CommandInstance instance{
- "base.reboot", "local", dict_.FindCommand("base.reboot"), {}};
- instance.SetID("command_id");
- EXPECT_EQ("command_id", instance.GetID());
-}
-
-TEST_F(CommandInstanceTest, FromJson) {
- auto json = CreateDictionaryValue(R"({
- 'name': 'robot.jump',
- 'id': 'abcd',
- 'parameters': {
- 'height': 53,
- '_jumpType': '_withKick'
- },
- 'results': {}
- })");
- std::string id;
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, &id, nullptr);
- EXPECT_EQ("abcd", id);
- EXPECT_EQ("abcd", instance->GetID());
- EXPECT_EQ("robot.jump", instance->GetName());
- EXPECT_EQ("robotd", instance->GetCategory());
- EXPECT_EQ(53, instance->FindParameter("height")->GetInt()->GetValue());
- EXPECT_EQ("_withKick",
- instance->FindParameter("_jumpType")->GetString()->GetValue());
-}
-
-TEST_F(CommandInstanceTest, FromJson_ParamsOmitted) {
- auto json = CreateDictionaryValue("{'name': 'base.reboot'}");
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, nullptr);
- EXPECT_EQ("base.reboot", instance->GetName());
- EXPECT_EQ("robotd", instance->GetCategory());
- EXPECT_TRUE(instance->GetParameters().empty());
-}
-
-TEST_F(CommandInstanceTest, FromJson_NotObject) {
- auto json = CreateValue("'string'");
- chromeos::ErrorPtr error;
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, &error);
- EXPECT_EQ(nullptr, instance.get());
- EXPECT_EQ("json_object_expected", error->GetCode());
- EXPECT_EQ("Command instance is not a JSON object", error->GetMessage());
-}
-
-TEST_F(CommandInstanceTest, FromJson_NameMissing) {
- auto json = CreateDictionaryValue("{'param': 'value'}");
- chromeos::ErrorPtr error;
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, &error);
- EXPECT_EQ(nullptr, instance.get());
- EXPECT_EQ("parameter_missing", error->GetCode());
- EXPECT_EQ("Command name is missing", error->GetMessage());
-}
-
-TEST_F(CommandInstanceTest, FromJson_UnknownCommand) {
- auto json = CreateDictionaryValue("{'name': 'robot.scream'}");
- chromeos::ErrorPtr error;
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, &error);
- EXPECT_EQ(nullptr, instance.get());
- EXPECT_EQ("invalid_command_name", error->GetCode());
- EXPECT_EQ("Unknown command received: robot.scream", error->GetMessage());
-}
-
-TEST_F(CommandInstanceTest, FromJson_ParamsNotObject) {
- auto json = CreateDictionaryValue(R"({
- 'name': 'robot.speak',
- 'parameters': 'hello'
- })");
- chromeos::ErrorPtr error;
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, &error);
- EXPECT_EQ(nullptr, instance.get());
- auto inner = error->GetInnerError();
- EXPECT_EQ("json_object_expected", inner->GetCode());
- EXPECT_EQ("Property 'parameters' must be a JSON object", inner->GetMessage());
- EXPECT_EQ("command_failed", error->GetCode());
- EXPECT_EQ("Failed to validate command 'robot.speak'", error->GetMessage());
-}
-
-TEST_F(CommandInstanceTest, FromJson_ParamError) {
- auto json = CreateDictionaryValue(R"({
- 'name': 'robot.speak',
- 'parameters': {
- 'phrase': 'iPityDaFool',
- 'volume': 20
- }
- })");
- chromeos::ErrorPtr error;
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, &error);
- EXPECT_EQ(nullptr, instance.get());
- auto first = error->GetFirstError();
- EXPECT_EQ("out_of_range", first->GetCode());
- EXPECT_EQ("Value 20 is out of range. It must not be greater than 10",
- first->GetMessage());
- auto inner = error->GetInnerError();
- EXPECT_EQ("invalid_parameter_value", inner->GetCode());
- EXPECT_EQ("Invalid value for property 'volume'",
- inner->GetMessage());
- EXPECT_EQ("command_failed", error->GetCode());
- EXPECT_EQ("Failed to validate command 'robot.speak'", error->GetMessage());
-}
-
-TEST_F(CommandInstanceTest, ToJson) {
- auto json = CreateDictionaryValue(R"({
- 'name': 'robot.jump',
- 'parameters': {
- 'height': 53,
- '_jumpType': '_withKick'
- },
- 'results': {}
- })");
- auto instance =
- CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, nullptr);
- instance->SetProgress(
- native_types::Object{{"progress", unittests::make_int_prop_value(15)}});
- instance->SetProgress(
- native_types::Object{{"progress", unittests::make_int_prop_value(15)}});
- instance->SetID("testId");
- native_types::Object results;
- instance->SetResults(
- native_types::Object{{"testResult", unittests::make_int_prop_value(17)}});
-
- json->MergeDictionary(CreateDictionaryValue(R"({
- 'id': 'testId',
- 'progress': {'progress': 15},
- 'state': 'inProgress',
- 'results': {'testResult': 17}
- })").get());
-
- auto converted = instance->ToJson();
- EXPECT_PRED2([](const base::Value& val1, const base::Value& val2) {
- return val1.Equals(&val2);
- }, *json, *converted);
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_manager.cc b/buffet/commands/command_manager.cc
deleted file mode 100644
index 71ea5a9..0000000
--- a/buffet/commands/command_manager.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_manager.h"
-
-#include <base/files/file_enumerator.h>
-#include <base/values.h>
-#include <chromeos/dbus/exported_object_manager.h>
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/schema_constants.h"
-#include "buffet/utils.h"
-
-using chromeos::dbus_utils::ExportedObjectManager;
-
-namespace buffet {
-
-CommandManager::CommandManager()
- : CommandManager(base::WeakPtr<ExportedObjectManager>{}) {
-}
-
-CommandManager::CommandManager(
- const base::WeakPtr<ExportedObjectManager>& object_manager)
- : command_dispatcher_(object_manager) {
- command_queue_.AddOnCommandAddedCallback(
- base::Bind(&DBusCommandDispacher::OnCommandAdded,
- base::Unretained(&command_dispatcher_)));
-}
-
-const CommandDictionary& CommandManager::GetCommandDictionary() const {
- return dictionary_;
-}
-
-bool CommandManager::LoadBaseCommands(const base::DictionaryValue& json,
- chromeos::ErrorPtr* error) {
- return base_dictionary_.LoadCommands(json, "", nullptr, error);
-}
-
-bool CommandManager::LoadBaseCommands(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const base::DictionaryValue> json = LoadJsonDict(
- json_file_path, error);
- if (!json)
- return false;
- return LoadBaseCommands(*json, error);
-}
-
-bool CommandManager::LoadCommands(const base::DictionaryValue& json,
- const std::string& category,
- chromeos::ErrorPtr* error) {
- bool result =
- dictionary_.LoadCommands(json, category, &base_dictionary_, error);
- for (const auto& cb : on_command_changed_)
- cb.Run();
- return result;
-}
-
-bool CommandManager::LoadCommands(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const base::DictionaryValue> json = LoadJsonDict(
- json_file_path, error);
- if (!json)
- return false;
- std::string category = json_file_path.BaseName().RemoveExtension().value();
- return LoadCommands(*json, category, error);
-}
-
-void CommandManager::Startup(const base::FilePath& definitions_path,
- const base::FilePath& test_definitions_path) {
- LOG(INFO) << "Initializing CommandManager.";
- // Load global standard GCD command dictionary.
- base::FilePath base_command_file{definitions_path.Append("gcd.json")};
- LOG(INFO) << "Loading standard commands from " << base_command_file.value();
- CHECK(LoadBaseCommands(base_command_file, nullptr))
- << "Failed to load the standard command definitions.";
-
- auto LoadPackages = [this](const base::FilePath& root,
- const base::FilePath::StringType& pattern) {
- base::FilePath device_command_dir{root.Append("commands")};
- VLOG(2) << "Looking for commands in " << root.value();
- base::FileEnumerator enumerator(device_command_dir, false,
- base::FileEnumerator::FILES,
- pattern);
- base::FilePath json_file_path = enumerator.Next();
- while (!json_file_path.empty()) {
- LOG(INFO) << "Loading command schema from " << json_file_path.value();
- CHECK(this->LoadCommands(json_file_path, nullptr))
- << "Failed to load the command definition file.";
- json_file_path = enumerator.Next();
- }
- };
- LoadPackages(definitions_path, FILE_PATH_LITERAL("*.json"));
- LoadPackages(test_definitions_path, FILE_PATH_LITERAL("*test.json"));
-}
-
-void CommandManager::AddCommand(
- std::unique_ptr<CommandInstance> command_instance) {
- command_queue_.Add(std::move(command_instance));
-}
-
-bool CommandManager::AddCommand(const base::DictionaryValue& command,
- UserRole role,
- std::string* id,
- chromeos::ErrorPtr* error) {
- auto command_instance = buffet::CommandInstance::FromJson(
- &command, commands::attributes::kCommand_Visibility_Local,
- GetCommandDictionary(), nullptr, error);
- if (!command_instance)
- return false;
-
- UserRole minimal_role =
- command_instance->GetCommandDefinition()->GetMinimalRole();
- if (role < minimal_role) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain, "access_denied",
- "User role '%s' less than minimal: '%s'", ToString(role).c_str(),
- ToString(minimal_role).c_str());
- return false;
- }
-
- *id = std::to_string(++next_command_id_);
- command_instance->SetID(*id);
- AddCommand(std::move(command_instance));
- return true;
-}
-
-CommandInstance* CommandManager::FindCommand(const std::string& id) const {
- return command_queue_.Find(id);
-}
-
-bool CommandManager::SetCommandVisibility(
- const std::vector<std::string>& command_names,
- CommandDefinition::Visibility visibility,
- chromeos::ErrorPtr* error) {
- if (command_names.empty())
- return true;
-
- std::vector<CommandDefinition*> definitions;
- definitions.reserve(command_names.size());
-
- // Find/validate command definitions first.
- for (const std::string& name : command_names) {
- CommandDefinition* def = dictionary_.FindCommand(name);
- if (!def) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidCommandName,
- "Command '%s' is unknown", name.c_str());
- return false;
- }
- definitions.push_back(def);
- }
-
- // Now that we know that all the command names were valid,
- // update the respective commands' visibility.
- for (CommandDefinition* def : definitions)
- def->SetVisibility(visibility);
- for (const auto& cb : on_command_changed_)
- cb.Run();
- return true;
-}
-
-void CommandManager::AddOnCommandAddedCallback(
- const CommandQueue::Callback& callback) {
- command_queue_.AddOnCommandAddedCallback(callback);
-}
-
-void CommandManager::AddOnCommandRemovedCallback(
- const CommandQueue::Callback& callback) {
- command_queue_.AddOnCommandRemovedCallback(callback);
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_manager.h b/buffet/commands/command_manager.h
deleted file mode 100644
index 3c2f720..0000000
--- a/buffet/commands/command_manager.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_COMMAND_MANAGER_H_
-#define BUFFET_COMMANDS_COMMAND_MANAGER_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-
-#include "buffet/commands/command_dictionary.h"
-#include "buffet/commands/command_queue.h"
-#include "buffet/commands/dbus_command_dispatcher.h"
-
-namespace chromeos {
-namespace dbus_utils {
-class ExportedObjectManager;
-} // namespace dbus_utils
-} // namespace chromeos
-
-
-namespace buffet {
-
-class CommandInstance;
-
-// CommandManager class that will have a list of all the device command
-// schemas as well as the live command queue of pending command instances
-// dispatched to the device.
-class CommandManager final {
- public:
- CommandManager();
- explicit CommandManager(
- const base::WeakPtr<chromeos::dbus_utils::ExportedObjectManager>&
- object_manager);
-
- // Sets callback which is called when command definitions is changed.
- void AddOnCommandDefChanged(const base::Closure& callback) {
- on_command_changed_.push_back(callback);
- callback.Run();
- }
-
- // Returns the command definitions for the device.
- const CommandDictionary& GetCommandDictionary() const;
-
- // Loads base/standard GCD command definitions.
- // |json| is the full JSON schema of standard GCD commands. These commands
- // are not necessarily supported by a particular device but rather
- // all the standard commands defined by GCD standard for all known/supported
- // device kinds.
- // On success, returns true. Otherwise, |error| contains additional
- // error information.
- bool LoadBaseCommands(const base::DictionaryValue& json,
- chromeos::ErrorPtr* error);
-
- // Same as the overload above, but takes a path to a json file to read
- // the base command definitions from.
- bool LoadBaseCommands(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error);
-
- // Loads device command schema for particular category.
- // See CommandDictionary::LoadCommands for detailed description of the
- // parameters.
- bool LoadCommands(const base::DictionaryValue& json,
- const std::string& category,
- chromeos::ErrorPtr* error);
-
- // Same as the overload above, but takes a path to a json file to read
- // the base command definitions from. Also, the command category is
- // derived from file name (without extension). So, if the path points to
- // "power_manager.json", the command category used will be "power_manager".
- bool LoadCommands(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error);
-
- // Startup method to be called by buffet daemon at startup.
- // Initializes the object and reads files in |definitions_path| to load
- // 1) the standard GCD command dictionary
- // 2) static vendor-provided command definitions
- // If |test_definitions_path| is not empty, we'll also look there for
- // additional commands.
- void Startup(const base::FilePath& definitions_path,
- const base::FilePath& test_definitions_path);
-
- // Adds a new command to the command queue.
- void AddCommand(std::unique_ptr<CommandInstance> command_instance);
- bool AddCommand(const base::DictionaryValue& command,
- UserRole role,
- std::string* id,
- chromeos::ErrorPtr* error);
-
- // Finds a command by the command |id|. Returns nullptr if the command with
- // the given |id| is not found. The returned pointer should not be persisted
- // for a long period of time.
- CommandInstance* FindCommand(const std::string& id) const;
-
- // Changes the visibility of commands.
- bool SetCommandVisibility(const std::vector<std::string>& command_names,
- CommandDefinition::Visibility visibility,
- chromeos::ErrorPtr* error);
-
- // Adds notifications callback for a new command being added to the queue.
- void AddOnCommandAddedCallback(const CommandQueue::Callback& callback);
-
- // Adds notifications callback for a command being removed from the queue.
- void AddOnCommandRemovedCallback(const CommandQueue::Callback& callback);
-
- private:
- CommandDictionary base_dictionary_; // Base/std command definitions/schemas.
- CommandDictionary dictionary_; // Command definitions/schemas.
- DBusCommandDispacher command_dispatcher_;
- CommandQueue command_queue_;
- std::vector<base::Callback<void()>> on_command_changed_;
- uint32_t next_command_id_{0};
-
- DISALLOW_COPY_AND_ASSIGN(CommandManager);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_COMMAND_MANAGER_H_
diff --git a/buffet/commands/command_manager_unittest.cc b/buffet/commands/command_manager_unittest.cc
deleted file mode 100644
index 81c2a5b..0000000
--- a/buffet/commands/command_manager_unittest.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_manager.h"
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/json/json_writer.h>
-#include <chromeos/bind_lambda.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/unittest_utils.h"
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-
-namespace {
-
-const char kTestBaseCommands[] = R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {}
- },
- 'shutdown': {
- 'parameters': {},
- 'results': {}
- }
- }
-})";
-
-const char kTestVendorCommands[] = R"({
- 'robot': {
- '_jump': {
- 'parameters': {'height': 'integer'},
- 'results': {}
- },
- '_speak': {
- 'parameters': {'phrase': 'string'},
- 'results': {}
- }
- }
-})";
-
-const char kTestTestCommands[] = R"({
- 'test': {
- '_yo': {
- 'parameters': {'name': 'string'},
- 'results': {}
- }
- }
-})";
-
-static void SaveJsonToFile(const base::DictionaryValue& dict,
- const base::FilePath& file_path) {
- std::string json;
- base::JSONWriter::Write(dict, &json);
- const int bytes_to_write = static_cast<int>(json.size());
- CHECK_EQ(bytes_to_write, WriteFile(file_path, json.data(), bytes_to_write));
-}
-
-static base::FilePath SaveJsonToTempFile(const base::DictionaryValue& dict) {
- base::FilePath temp_file;
- base::CreateTemporaryFile(&temp_file);
- SaveJsonToFile(dict, temp_file);
- return temp_file;
-}
-
-} // namespace
-
-TEST(CommandManager, Empty) {
- CommandManager manager;
- EXPECT_TRUE(manager.GetCommandDictionary().IsEmpty());
-}
-
-TEST(CommandManager, LoadBaseCommandsJSON) {
- CommandManager manager;
- auto json = CreateDictionaryValue(kTestBaseCommands);
- EXPECT_TRUE(manager.LoadBaseCommands(*json, nullptr));
-}
-
-TEST(CommandManager, LoadBaseCommandsFile) {
- CommandManager manager;
- auto json = CreateDictionaryValue(kTestBaseCommands);
- base::FilePath temp_file = SaveJsonToTempFile(*json);
- EXPECT_TRUE(manager.LoadBaseCommands(temp_file, nullptr));
- base::DeleteFile(temp_file, false);
-}
-
-TEST(CommandManager, LoadCommandsJSON) {
- CommandManager manager;
- auto json = CreateDictionaryValue(kTestVendorCommands);
- EXPECT_TRUE(manager.LoadCommands(*json, "category", nullptr));
-}
-
-TEST(CommandManager, LoadCommandsFile) {
- CommandManager manager;
- // Load some standard command definitions first.
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {}
- },
- 'shutdown': {
- 'parameters': {},
- 'results': {}
- }
- }
- })");
- manager.LoadBaseCommands(*json, nullptr);
- // Load device-supported commands.
- json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {}
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {'height': 'integer'},
- 'results': {}
- }
- }
- })");
- base::FilePath temp_file = SaveJsonToTempFile(*json);
- EXPECT_TRUE(manager.LoadCommands(temp_file, nullptr));
- base::DeleteFile(temp_file, false);
- EXPECT_EQ(2, manager.GetCommandDictionary().GetSize());
- EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("base.reboot"));
- EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("robot._jump"));
-}
-
-TEST(CommandManager, ShouldLoadStandardAndTestDefinitions) {
- CommandManager manager;
- base::ScopedTempDir temp;
- CHECK(temp.CreateUniqueTempDir());
- base::FilePath base_path{temp.path().Append("base_defs")};
- base::FilePath test_path{temp.path().Append("test_defs")};
- base::FilePath base_commands_path{base_path.Append("commands")};
- base::FilePath test_commands_path{test_path.Append("commands")};
- CHECK(CreateDirectory(base_commands_path));
- CHECK(CreateDirectory(test_commands_path));
- SaveJsonToFile(*CreateDictionaryValue(kTestBaseCommands),
- base_path.Append("gcd.json"));
- SaveJsonToFile(*CreateDictionaryValue(kTestVendorCommands),
- base_commands_path.Append("category.json"));
- SaveJsonToFile(*CreateDictionaryValue(kTestTestCommands),
- test_commands_path.Append("test.json"));
- manager.Startup(base_path, test_path);
- EXPECT_EQ(3, manager.GetCommandDictionary().GetSize());
- EXPECT_NE(nullptr,
- manager.GetCommandDictionary().FindCommand("robot._jump"));
- EXPECT_NE(nullptr,
- manager.GetCommandDictionary().FindCommand("robot._speak"));
- EXPECT_NE(nullptr,
- manager.GetCommandDictionary().FindCommand("test._yo"));
-}
-
-TEST(CommandManager, UpdateCommandVisibility) {
- CommandManager manager;
- int update_count = 0;
- auto on_command_change = [&update_count]() { update_count++; };
- manager.AddOnCommandDefChanged(base::Bind(on_command_change));
-
- auto json = CreateDictionaryValue(R"({
- 'foo': {
- '_baz': {
- 'parameters': {},
- 'results': {}
- },
- '_bar': {
- 'parameters': {},
- 'results': {}
- }
- },
- 'bar': {
- '_quux': {
- 'parameters': {},
- 'results': {},
- 'visibility': 'none'
- }
- }
- })");
- ASSERT_TRUE(manager.LoadCommands(*json, "test", nullptr));
- EXPECT_EQ(2, update_count);
- const CommandDictionary& dict = manager.GetCommandDictionary();
- EXPECT_TRUE(manager.SetCommandVisibility(
- {"foo._baz"}, CommandDefinition::Visibility::GetLocal(), nullptr));
- EXPECT_EQ(3, update_count);
- EXPECT_EQ("local", dict.FindCommand("foo._baz")->GetVisibility().ToString());
- EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString());
- EXPECT_EQ("none", dict.FindCommand("bar._quux")->GetVisibility().ToString());
-
- chromeos::ErrorPtr error;
- ASSERT_FALSE(manager.SetCommandVisibility(
- {"foo._baz", "foo._bar", "test.cmd"},
- CommandDefinition::Visibility::GetLocal(), &error));
- EXPECT_EQ(errors::commands::kInvalidCommandName, error->GetCode());
- EXPECT_EQ("Command 'test.cmd' is unknown", error->GetMessage());
- // The visibility state of commands shouldn't have changed.
- EXPECT_EQ(3, update_count);
- EXPECT_EQ("local", dict.FindCommand("foo._baz")->GetVisibility().ToString());
- EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString());
- EXPECT_EQ("none", dict.FindCommand("bar._quux")->GetVisibility().ToString());
-
- EXPECT_TRUE(manager.SetCommandVisibility(
- {"foo._baz", "bar._quux"}, CommandDefinition::Visibility::GetCloud(),
- nullptr));
- EXPECT_EQ(4, update_count);
- EXPECT_EQ("cloud", dict.FindCommand("foo._baz")->GetVisibility().ToString());
- EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString());
- EXPECT_EQ("cloud", dict.FindCommand("bar._quux")->GetVisibility().ToString());
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_proxy_interface.h b/buffet/commands/command_proxy_interface.h
deleted file mode 100644
index 0b5981c..0000000
--- a/buffet/commands/command_proxy_interface.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_COMMAND_PROXY_INTERFACE_H_
-#define BUFFET_COMMANDS_COMMAND_PROXY_INTERFACE_H_
-
-#include <string>
-
-#include "buffet/commands/schema_utils.h"
-
-namespace buffet {
-
-// This interface lets the command instance to update its proxy of command
-// state changes, so that the proxy can then notify clients of the changes over
-// their supported protocol (e.g. D-Bus).
-class CommandProxyInterface {
- public:
- virtual ~CommandProxyInterface() = default;
-
- virtual void OnResultsChanged() = 0;
- virtual void OnStatusChanged() = 0;
- virtual void OnProgressChanged() = 0;
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_COMMAND_PROXY_INTERFACE_H_
diff --git a/buffet/commands/command_queue.cc b/buffet/commands/command_queue.cc
deleted file mode 100644
index f4cda60..0000000
--- a/buffet/commands/command_queue.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_queue.h"
-
-#include <base/bind.h>
-#include <base/time/time.h>
-
-namespace buffet {
-
-namespace {
-const int kRemoveCommandDelayMin = 5;
-}
-
-void CommandQueue::AddOnCommandAddedCallback(const Callback& callback) {
- on_command_added_.push_back(callback);
- // Send all pre-existed commands.
- for (const auto& command : map_)
- callback.Run(command.second.get());
-}
-
-void CommandQueue::AddOnCommandRemovedCallback(const Callback& callback) {
- on_command_removed_.push_back(callback);
-}
-
-void CommandQueue::Add(std::unique_ptr<CommandInstance> instance) {
- std::string id = instance->GetID();
- LOG_IF(FATAL, id.empty()) << "Command has no ID";
- instance->SetCommandQueue(this);
- auto pair = map_.insert(std::make_pair(id, std::move(instance)));
- LOG_IF(FATAL, !pair.second) << "Command with ID '" << id
- << "' is already in the queue";
- for (const auto& cb : on_command_added_)
- cb.Run(pair.first->second.get());
- Cleanup();
-}
-
-void CommandQueue::DelayedRemove(const std::string& id) {
- auto p = map_.find(id);
- if (p == map_.end())
- return;
- remove_queue_.push(std::make_pair(
- base::Time::Now() + base::TimeDelta::FromMinutes(kRemoveCommandDelayMin),
- id));
- Cleanup();
-}
-
-bool CommandQueue::Remove(const std::string& id) {
- auto p = map_.find(id);
- if (p == map_.end())
- return false;
- std::unique_ptr<CommandInstance> instance{std::move(p->second)};
- instance->SetCommandQueue(nullptr);
- map_.erase(p);
- for (const auto& cb : on_command_removed_)
- cb.Run(instance.get());
- return true;
-}
-
-void CommandQueue::Cleanup() {
- while (!remove_queue_.empty() && remove_queue_.front().first < Now()) {
- Remove(remove_queue_.front().second);
- remove_queue_.pop();
- }
-}
-
-void CommandQueue::SetNowForTest(base::Time now) {
- test_now_ = now;
-}
-
-base::Time CommandQueue::Now() const {
- return test_now_.is_null() ? base::Time::Now() : test_now_;
-}
-
-CommandInstance* CommandQueue::Find(const std::string& id) const {
- auto p = map_.find(id);
- return (p != map_.end()) ? p->second.get() : nullptr;
-}
-
-} // namespace buffet
diff --git a/buffet/commands/command_queue.h b/buffet/commands/command_queue.h
deleted file mode 100644
index db6707c..0000000
--- a/buffet/commands/command_queue.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_COMMAND_QUEUE_H_
-#define BUFFET_COMMANDS_COMMAND_QUEUE_H_
-
-#include <map>
-#include <memory>
-#include <queue>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/macros.h>
-
-#include "buffet/commands/command_instance.h"
-
-namespace buffet {
-
-class CommandQueue final {
- public:
- using Callback = base::Callback<void(CommandInstance*)>;
- CommandQueue() = default;
-
- // Adds notifications callback for a new command is added to the queue.
- void AddOnCommandAddedCallback(const Callback& callback);
-
- // Adds notifications callback for a command is removed from the queue.
- void AddOnCommandRemovedCallback(const Callback& callback);
-
- // Checks if the command queue is empty.
- bool IsEmpty() const { return map_.empty(); }
-
- // Returns the number of commands in the queue.
- size_t GetCount() const { return map_.size(); }
-
- // Adds a new command to the queue. Each command in the queue has a unique
- // ID that identifies that command instance in this queue.
- // One shouldn't attempt to add a command with the same ID.
- void Add(std::unique_ptr<CommandInstance> instance);
-
- // Selects command identified by |id| ready for removal. Command will actually
- // be removed after some time.
- void DelayedRemove(const std::string& id);
-
- // Finds a command instance in the queue by the instance |id|. Returns
- // nullptr if the command with the given |id| is not found. The returned
- // pointer should not be persisted for a long period of time.
- CommandInstance* Find(const std::string& id) const;
-
- private:
- friend class CommandQueueTest;
- friend class DBusCommandDispacherTest;
-
- // Removes a command identified by |id| from the queue.
- bool Remove(const std::string& id);
-
- // Removes old commands selected with DelayedRemove.
- void Cleanup();
-
- // Overrides CommandQueue::Now() for tests.
- void SetNowForTest(base::Time now);
-
- // Returns current time.
- base::Time Now() const;
-
- // Overridden value to be returned from Now().
- base::Time test_now_;
-
- // ID-to-CommandInstance map.
- std::map<std::string, std::unique_ptr<CommandInstance>> map_;
-
- // Queue of commands to be removed.
- std::queue<std::pair<base::Time, std::string>> remove_queue_;
-
- using CallbackList = std::vector<Callback>;
- CallbackList on_command_added_;
- CallbackList on_command_removed_;
-
- DISALLOW_COPY_AND_ASSIGN(CommandQueue);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_COMMAND_QUEUE_H_
diff --git a/buffet/commands/command_queue_unittest.cc b/buffet/commands/command_queue_unittest.cc
deleted file mode 100644
index f29b03e..0000000
--- a/buffet/commands/command_queue_unittest.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/command_queue.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/memory/weak_ptr.h>
-#include <chromeos/strings/string_utils.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/command_definition.h"
-#include "buffet/commands/object_schema.h"
-
-namespace buffet {
-
-class CommandQueueTest : public testing::Test {
- public:
- std::unique_ptr<CommandInstance> CreateDummyCommandInstance(
- const std::string& name,
- const std::string& id) {
- std::unique_ptr<CommandInstance> cmd{
- new CommandInstance{name, "local", &command_definition_, {}}};
- cmd->SetID(id);
- return cmd;
- }
-
- bool Remove(const std::string& id) { return queue_.Remove(id); }
-
- void Cleanup(const base::TimeDelta& interval) {
- queue_.SetNowForTest(base::Time::Now() + interval);
- return queue_.Cleanup();
- }
-
- CommandQueue queue_;
-
- private:
- CommandDefinition command_definition_{"powerd",
- ObjectSchema::Create(),
- ObjectSchema::Create(),
- ObjectSchema::Create()};
-};
-
-// Keeps track of commands being added to and removed from the queue_.
-// Aborts if duplicate commands are added or non-existent commands are removed.
-class FakeDispatcher {
- public:
- explicit FakeDispatcher(CommandQueue* queue) {
- queue->AddOnCommandAddedCallback(
- base::Bind(&FakeDispatcher::OnCommandAdded,
- weak_ptr_factory_.GetWeakPtr()));
- queue->AddOnCommandRemovedCallback(
- base::Bind(&FakeDispatcher::OnCommandRemoved,
- weak_ptr_factory_.GetWeakPtr()));
- }
-
- void OnCommandAdded(CommandInstance* command_instance) {
- CHECK(ids_.insert(command_instance->GetID()).second)
- << "Command ID already exists: " << command_instance->GetID();
- CHECK(commands_.insert(command_instance).second)
- << "Command instance already exists";
- }
-
- void OnCommandRemoved(CommandInstance* command_instance) {
- CHECK_EQ(1u, ids_.erase(command_instance->GetID()))
- << "Command ID not found: " << command_instance->GetID();
- CHECK_EQ(1u, commands_.erase(command_instance))
- << "Command instance not found";
- }
-
- // Get the comma-separated list of command IDs currently accumulated in the
- // command queue_.
- std::string GetIDs() const {
- using chromeos::string_utils::Join;
- return Join(",", std::vector<std::string>(ids_.begin(), ids_.end()));
- }
-
- private:
- std::set<std::string> ids_;
- std::set<CommandInstance*> commands_;
- base::WeakPtrFactory<FakeDispatcher> weak_ptr_factory_{this};
-};
-
-TEST_F(CommandQueueTest, Empty) {
- EXPECT_TRUE(queue_.IsEmpty());
- EXPECT_EQ(0, queue_.GetCount());
-}
-
-TEST_F(CommandQueueTest, Add) {
- queue_.Add(CreateDummyCommandInstance("base.reboot", "id1"));
- queue_.Add(CreateDummyCommandInstance("base.reboot", "id2"));
- queue_.Add(CreateDummyCommandInstance("base.reboot", "id3"));
- EXPECT_EQ(3, queue_.GetCount());
- EXPECT_FALSE(queue_.IsEmpty());
-}
-
-TEST_F(CommandQueueTest, Remove) {
- const std::string id1 = "id1";
- const std::string id2 = "id2";
- queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
- queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
- EXPECT_FALSE(queue_.IsEmpty());
- EXPECT_FALSE(Remove("dummy"));
- EXPECT_EQ(2, queue_.GetCount());
- EXPECT_TRUE(Remove(id1));
- EXPECT_EQ(1, queue_.GetCount());
- EXPECT_FALSE(Remove(id1));
- EXPECT_EQ(1, queue_.GetCount());
- EXPECT_TRUE(Remove(id2));
- EXPECT_EQ(0, queue_.GetCount());
- EXPECT_FALSE(Remove(id2));
- EXPECT_EQ(0, queue_.GetCount());
- EXPECT_TRUE(queue_.IsEmpty());
-}
-
-TEST_F(CommandQueueTest, DelayedRemove) {
- const std::string id1 = "id1";
- queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
- EXPECT_EQ(1, queue_.GetCount());
-
- queue_.DelayedRemove(id1);
- EXPECT_EQ(1, queue_.GetCount());
-
- Cleanup(base::TimeDelta::FromMinutes(1));
- EXPECT_EQ(1, queue_.GetCount());
-
- Cleanup(base::TimeDelta::FromMinutes(15));
- EXPECT_EQ(0, queue_.GetCount());
-}
-
-TEST_F(CommandQueueTest, Dispatch) {
- FakeDispatcher dispatch(&queue_);
- const std::string id1 = "id1";
- const std::string id2 = "id2";
- queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
- queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
- std::set<std::string> ids{id1, id2}; // Make sure they are sorted properly.
- std::string expected_set = chromeos::string_utils::Join(
- ",", std::vector<std::string>(ids.begin(), ids.end()));
- EXPECT_EQ(expected_set, dispatch.GetIDs());
- Remove(id1);
- EXPECT_EQ(id2, dispatch.GetIDs());
- Remove(id2);
- EXPECT_EQ("", dispatch.GetIDs());
-}
-
-TEST_F(CommandQueueTest, Find) {
- const std::string id1 = "id1";
- const std::string id2 = "id2";
- queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
- queue_.Add(CreateDummyCommandInstance("base.shutdown", id2));
- EXPECT_EQ(nullptr, queue_.Find("dummy"));
- auto cmd1 = queue_.Find(id1);
- EXPECT_NE(nullptr, cmd1);
- EXPECT_EQ("base.reboot", cmd1->GetName());
- EXPECT_EQ(id1, cmd1->GetID());
- auto cmd2 = queue_.Find(id2);
- EXPECT_NE(nullptr, cmd2);
- EXPECT_EQ("base.shutdown", cmd2->GetName());
- EXPECT_EQ(id2, cmd2->GetID());
-}
-
-} // namespace buffet
diff --git a/buffet/commands/dbus_command_dispatcher.cc b/buffet/commands/dbus_command_dispatcher.cc
deleted file mode 100644
index 2f5333c..0000000
--- a/buffet/commands/dbus_command_dispatcher.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/dbus_command_dispatcher.h"
-
-#include <chromeos/dbus/exported_object_manager.h>
-
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/dbus_command_proxy.h"
-#include "buffet/dbus_constants.h"
-
-using chromeos::dbus_utils::AsyncEventSequencer;
-using chromeos::dbus_utils::ExportedObjectManager;
-
-namespace buffet {
-
-DBusCommandDispacher::DBusCommandDispacher(
- const base::WeakPtr<ExportedObjectManager>& object_manager)
- : object_manager_{object_manager} {
-}
-
-void DBusCommandDispacher::OnCommandAdded(CommandInstance* command_instance) {
- if (!object_manager_)
- return;
- std::unique_ptr<DBusCommandProxy> proxy{new DBusCommandProxy(
- object_manager_.get(), object_manager_->GetBus(), command_instance,
- dbus_constants::kCommandServicePathPrefix + std::to_string(++next_id_))};
- proxy->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
- command_instance->AddProxy(std::move(proxy));
-}
-
-} // namespace buffet
diff --git a/buffet/commands/dbus_command_dispatcher.h b/buffet/commands/dbus_command_dispatcher.h
deleted file mode 100644
index e9f5003..0000000
--- a/buffet/commands/dbus_command_dispatcher.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_DBUS_COMMAND_DISPATCHER_H_
-#define BUFFET_COMMANDS_DBUS_COMMAND_DISPATCHER_H_
-
-#include <map>
-#include <string>
-
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-
-namespace chromeos {
-namespace dbus_utils {
-class ExportedObjectManager;
-} // namespace dbus_utils
-} // namespace chromeos
-
-namespace buffet {
-
-class CommandInstance;
-
-// Implements D-Bus dispatch of commands. When OnCommandAdded is called,
-// DBusCommandDispacher creates an instance of DBusCommandProxy object and
-// advertises it through ExportedObjectManager on D-Bus. Command handling
-// processes can watch the new D-Bus object appear and communicate with it to
-// update the command handling progress. Once command is handled,
-// DBusCommandProxy::Done() is called and the command is removed from the
-// command queue and D-Bus ExportedObjectManager.
-class DBusCommandDispacher final {
- public:
- explicit DBusCommandDispacher(const base::WeakPtr<
- chromeos::dbus_utils::ExportedObjectManager>& object_manager);
-
- void OnCommandAdded(CommandInstance* command_instance);
-
- private:
- base::WeakPtr<chromeos::dbus_utils::ExportedObjectManager> object_manager_;
- int next_id_{0};
-
- // Default constructor is used in special circumstances such as for testing.
- DBusCommandDispacher() = default;
-
- friend class CommandManager;
- DISALLOW_COPY_AND_ASSIGN(DBusCommandDispacher);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_DBUS_COMMAND_DISPATCHER_H_
diff --git a/buffet/commands/dbus_command_dispatcher_unittest.cc b/buffet/commands/dbus_command_dispatcher_unittest.cc
deleted file mode 100644
index d9d91bc..0000000
--- a/buffet/commands/dbus_command_dispatcher_unittest.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/dbus_command_dispatcher.h"
-
-#include <memory>
-#include <string>
-
-#include <chromeos/dbus/exported_object_manager.h>
-#include <dbus/mock_bus.h>
-#include <dbus/mock_exported_object.h>
-#include <dbus/object_manager.h>
-#include <dbus/object_path.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/command_dictionary.h"
-#include "buffet/commands/command_queue.h"
-#include "buffet/commands/dbus_command_proxy.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/dbus_constants.h"
-
-namespace buffet {
-
-using chromeos::dbus_utils::AsyncEventSequencer;
-using testing::_;
-using testing::AnyNumber;
-using testing::InSequence;
-using testing::Invoke;
-using testing::Return;
-using unittests::CreateDictionaryValue;
-
-namespace {
-const char kCommandCategory[] = "test_category";
-
-} // anonymous namespace
-
-class DBusCommandDispacherTest : public testing::Test {
- public:
- void SetUp() override {
- command_queue_.SetNowForTest(base::Time::Max());
-
- const dbus::ObjectPath kExportedObjectManagerPath("/test/om_path");
- std::string cmd_path = dbus_constants::kCommandServicePathPrefix;
- cmd_path += "1";
- const dbus::ObjectPath kCmdObjPath(cmd_path);
-
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SYSTEM;
- bus_ = new dbus::MockBus(options);
- // By default, don't worry about threading assertions.
- EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
- EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
- // Use a mock exported object manager.
- mock_exported_object_manager_ = new dbus::MockExportedObject(
- bus_.get(), kExportedObjectManagerPath);
- EXPECT_CALL(*bus_, GetExportedObject(kExportedObjectManagerPath))
- .WillRepeatedly(Return(mock_exported_object_manager_.get()));
- EXPECT_CALL(*mock_exported_object_manager_,
- ExportMethod(_, _, _, _)).Times(AnyNumber());
- om_.reset(new chromeos::dbus_utils::ExportedObjectManager(
- bus_.get(), kExportedObjectManagerPath));
- om_->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction());
- command_dispatcher_.reset(new DBusCommandDispacher(om_->AsWeakPtr()));
- command_queue_.AddOnCommandAddedCallback(
- base::Bind(&DBusCommandDispacher::OnCommandAdded,
- base::Unretained(command_dispatcher_.get())));
- // Use a mock exported object for command proxy.
- mock_exported_command_proxy_ = new dbus::MockExportedObject(
- bus_.get(), kCmdObjPath);
- EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath))
- .WillRepeatedly(Return(mock_exported_command_proxy_.get()));
- EXPECT_CALL(*mock_exported_command_proxy_, ExportMethod(_, _, _, _))
- .WillRepeatedly(Invoke(MockExportMethod));
-
- auto json = CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'results': {}
- },
- 'shutdown': {
- 'parameters': {},
- 'results': {},
- 'progress': {'progress': 'integer'}
- }
- }
- })");
- CHECK(dictionary_.LoadCommands(*json, kCommandCategory, nullptr, nullptr))
- << "Failed to load command dictionary";
- }
-
- void TearDown() override {
- EXPECT_CALL(*mock_exported_object_manager_, Unregister()).Times(1);
- om_.reset();
- bus_ = nullptr;
- }
-
- static void MockExportMethod(
- const std::string& interface_name,
- const std::string& method_name,
- dbus::ExportedObject::MethodCallCallback method_call_callback,
- dbus::ExportedObject::OnExportedCallback on_exported_callback) {
- on_exported_callback.Run(interface_name, method_name, true);
- }
-
-
- void AddNewCommand(const std::string& json, const std::string& id) {
- auto command_instance = CommandInstance::FromJson(
- CreateDictionaryValue(json.c_str()).get(), "cloud", dictionary_,
- nullptr, nullptr);
- command_instance->SetID(id);
- // Two interfaces are added - Command and Properties.
- EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
- command_queue_.Add(std::move(command_instance));
- }
-
- DBusCommandProxy* FindProxy(CommandInstance* command_instance) {
- CHECK_EQ(command_instance->proxies_.size(), 1U);
- return static_cast<DBusCommandProxy*>(command_instance->proxies_[0].get());
- }
-
- void FinishCommand(DBusCommandProxy* proxy) {
- proxy->Done();
- }
-
- void SetProgress(DBusCommandProxy* proxy,
- const native_types::Object& progress) {
- EXPECT_TRUE(proxy->SetProgress(nullptr, ObjectToDBusVariant(progress)));
- }
-
-
- scoped_refptr<dbus::MockBus> bus_;
- scoped_refptr<dbus::MockExportedObject> mock_exported_object_manager_;
- scoped_refptr<dbus::MockExportedObject> mock_exported_command_proxy_;
- std::unique_ptr<chromeos::dbus_utils::ExportedObjectManager> om_;
- CommandDictionary dictionary_;
- std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
- CommandQueue command_queue_;
-};
-
-TEST_F(DBusCommandDispacherTest, Test_Command_Base_Shutdown) {
- const std::string id = "id0000";
- AddNewCommand("{'name':'base.shutdown'}", id);
- CommandInstance* command_instance = command_queue_.Find(id);
- ASSERT_NE(nullptr, command_instance);
- DBusCommandProxy* command_proxy = FindProxy(command_instance);
- ASSERT_NE(nullptr, command_proxy);
- EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
-
- // Two properties are set, Progress = 50%, Status = "inProgress"
- EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(2);
- native_types::Object progress{
- {"progress", unittests::make_int_prop_value(50)}};
- SetProgress(command_proxy, progress);
- EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
- EXPECT_EQ(progress, command_instance->GetProgress());
-
- // Command must be removed from the queue and proxy destroyed after calling
- // FinishCommand().
- // One property is set, Status = "done"
- EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(1);
- // D-Bus command proxy is going away.
- EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
- // Two interfaces are being removed on the D-Bus command object.
- EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
- FinishCommand(command_proxy);
-
- EXPECT_EQ(nullptr, command_queue_.Find(id));
-}
-
-TEST_F(DBusCommandDispacherTest, Test_Command_Base_Reboot) {
- const std::string id = "id0001";
- AddNewCommand(R"({
- 'name': 'base.reboot',
- 'parameters': {
- 'delay': 20
- }
- })", id);
- CommandInstance* command_instance = command_queue_.Find(id);
- ASSERT_NE(nullptr, command_instance);
- DBusCommandProxy* command_proxy = FindProxy(command_instance);
- ASSERT_NE(nullptr, command_proxy);
- EXPECT_EQ(CommandInstance::kStatusQueued, command_instance->GetStatus());
-
- // One property is set, Status = "inProgress"
- EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(1);
- native_types::Object progress{};
- SetProgress(command_proxy, progress);
- EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
- EXPECT_EQ(progress, command_instance->GetProgress());
-
- // Command must be removed from the queue and proxy destroyed after calling
- // FinishCommand().
- // One property is set, Status = "done"
- EXPECT_CALL(*mock_exported_command_proxy_, SendSignal(_)).Times(1);
- // D-Bus command proxy is going away.
- EXPECT_CALL(*mock_exported_command_proxy_, Unregister()).Times(1);
- // Two interfaces are being removed on the D-Bus command object.
- EXPECT_CALL(*mock_exported_object_manager_, SendSignal(_)).Times(2);
- FinishCommand(command_proxy);
-
- EXPECT_EQ(nullptr, command_queue_.Find(id));
-}
-
-
-} // namespace buffet
diff --git a/buffet/commands/dbus_command_proxy.cc b/buffet/commands/dbus_command_proxy.cc
deleted file mode 100644
index 74278fe..0000000
--- a/buffet/commands/dbus_command_proxy.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/dbus_command_proxy.h"
-
-#include <chromeos/dbus/async_event_sequencer.h>
-#include <chromeos/dbus/exported_object_manager.h>
-
-#include "buffet/commands/command_definition.h"
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/object_schema.h"
-#include "buffet/commands/prop_constraints.h"
-#include "buffet/commands/prop_types.h"
-
-using chromeos::dbus_utils::AsyncEventSequencer;
-using chromeos::dbus_utils::ExportedObjectManager;
-
-namespace buffet {
-
-DBusCommandProxy::DBusCommandProxy(ExportedObjectManager* object_manager,
- const scoped_refptr<dbus::Bus>& bus,
- CommandInstance* command_instance,
- std::string object_path)
- : command_instance_{command_instance},
- dbus_object_{object_manager, bus, dbus::ObjectPath{object_path}} {
-}
-
-void DBusCommandProxy::RegisterAsync(
- const AsyncEventSequencer::CompletionAction& completion_callback) {
- dbus_adaptor_.RegisterWithDBusObject(&dbus_object_);
-
- // Set the initial property values before registering the DBus object.
- dbus_adaptor_.SetName(command_instance_->GetName());
- dbus_adaptor_.SetCategory(command_instance_->GetCategory());
- dbus_adaptor_.SetId(command_instance_->GetID());
- dbus_adaptor_.SetStatus(command_instance_->GetStatus());
- dbus_adaptor_.SetProgress(
- ObjectToDBusVariant(command_instance_->GetProgress()));
- dbus_adaptor_.SetOrigin(command_instance_->GetOrigin());
-
- dbus_adaptor_.SetParameters(ObjectToDBusVariant(
- command_instance_->GetParameters()));
- dbus_adaptor_.SetResults(ObjectToDBusVariant(
- command_instance_->GetResults()));
-
- // Register the command DBus object and expose its methods and properties.
- dbus_object_.RegisterAsync(completion_callback);
-}
-
-void DBusCommandProxy::OnResultsChanged() {
- dbus_adaptor_.SetResults(
- ObjectToDBusVariant(command_instance_->GetResults()));
-}
-
-void DBusCommandProxy::OnStatusChanged() {
- dbus_adaptor_.SetStatus(command_instance_->GetStatus());
-}
-
-void DBusCommandProxy::OnProgressChanged() {
- dbus_adaptor_.SetProgress(
- ObjectToDBusVariant(command_instance_->GetProgress()));
-}
-
-bool DBusCommandProxy::SetProgress(
- chromeos::ErrorPtr* error,
- const chromeos::VariantDictionary& progress) {
- LOG(INFO) << "Received call to Command<" << command_instance_->GetName()
- << ">::SetProgress()";
-
- auto progress_schema =
- command_instance_->GetCommandDefinition()->GetProgress();
- native_types::Object obj;
- if (!ObjectFromDBusVariant(progress_schema, progress, &obj, error))
- return false;
-
- command_instance_->SetProgress(obj);
- return true;
-}
-
-bool DBusCommandProxy::SetResults(chromeos::ErrorPtr* error,
- const chromeos::VariantDictionary& results) {
- LOG(INFO) << "Received call to Command<"
- << command_instance_->GetName() << ">::SetResults()";
-
- auto results_schema = command_instance_->GetCommandDefinition()->GetResults();
- native_types::Object obj;
- if (!ObjectFromDBusVariant(results_schema, results, &obj, error))
- return false;
-
- command_instance_->SetResults(obj);
- return true;
-}
-
-void DBusCommandProxy::Abort() {
- LOG(INFO) << "Received call to Command<"
- << command_instance_->GetName() << ">::Abort()";
- command_instance_->Abort();
-}
-
-void DBusCommandProxy::Cancel() {
- LOG(INFO) << "Received call to Command<"
- << command_instance_->GetName() << ">::Cancel()";
- command_instance_->Cancel();
-}
-
-void DBusCommandProxy::Done() {
- LOG(INFO) << "Received call to Command<"
- << command_instance_->GetName() << ">::Done()";
- command_instance_->Done();
-}
-
-
-} // namespace buffet
diff --git a/buffet/commands/dbus_command_proxy.h b/buffet/commands/dbus_command_proxy.h
deleted file mode 100644
index aac671c..0000000
--- a/buffet/commands/dbus_command_proxy.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_DBUS_COMMAND_PROXY_H_
-#define BUFFET_COMMANDS_DBUS_COMMAND_PROXY_H_
-
-#include <string>
-
-#include <base/macros.h>
-#include <chromeos/dbus/data_serialization.h>
-#include <chromeos/dbus/dbus_object.h>
-
-#include "buffet/commands/command_proxy_interface.h"
-#include "buffet/org.chromium.Buffet.Command.h"
-
-namespace chromeos {
-namespace dbus_utils {
-class ExportedObjectManager;
-} // namespace dbus_utils
-} // namespace chromeos
-
-namespace buffet {
-
-class CommandInstance;
-
-class DBusCommandProxy : public CommandProxyInterface,
- public org::chromium::Buffet::CommandInterface {
- public:
- DBusCommandProxy(chromeos::dbus_utils::ExportedObjectManager* object_manager,
- const scoped_refptr<dbus::Bus>& bus,
- CommandInstance* command_instance,
- std::string object_path);
- ~DBusCommandProxy() override = default;
-
- void RegisterAsync(
- const chromeos::dbus_utils::AsyncEventSequencer::CompletionAction&
- completion_callback);
-
- // CommandProxyInterface implementation/overloads.
- void OnResultsChanged() override;
- void OnStatusChanged() override;
- void OnProgressChanged() override;
-
- private:
- // Handles calls to org.chromium.Buffet.Command.SetProgress(progress).
- bool SetProgress(chromeos::ErrorPtr* error,
- const chromeos::VariantDictionary& progress) override;
- // Handles calls to org.chromium.Buffet.Command.SetResults(results).
- bool SetResults(chromeos::ErrorPtr* error,
- const chromeos::VariantDictionary& results) override;
- // Handles calls to org.chromium.Buffet.Command.Abort().
- void Abort() override;
- // Handles calls to org.chromium.Buffet.Command.Cancel().
- void Cancel() override;
- // Handles calls to org.chromium.Buffet.Command.Done().
- void Done() override;
-
- CommandInstance* command_instance_;
- org::chromium::Buffet::CommandAdaptor dbus_adaptor_{this};
- chromeos::dbus_utils::DBusObject dbus_object_;
-
- friend class DBusCommandProxyTest;
- friend class DBusCommandDispacherTest;
- DISALLOW_COPY_AND_ASSIGN(DBusCommandProxy);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_DBUS_COMMAND_PROXY_H_
diff --git a/buffet/commands/dbus_command_proxy_unittest.cc b/buffet/commands/dbus_command_proxy_unittest.cc
deleted file mode 100644
index 1f94ca7..0000000
--- a/buffet/commands/dbus_command_proxy_unittest.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/dbus_command_proxy.h"
-
-#include <functional>
-#include <memory>
-
-#include <dbus/mock_bus.h>
-#include <dbus/mock_exported_object.h>
-#include <dbus/property.h>
-#include <chromeos/dbus/dbus_object.h>
-#include <chromeos/dbus/dbus_object_test_helpers.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/command_dictionary.h"
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/dbus_constants.h"
-
-namespace buffet {
-
-using ::testing::AnyNumber;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::_;
-
-using chromeos::VariantDictionary;
-using chromeos::dbus_utils::AsyncEventSequencer;
-using unittests::CreateDictionaryValue;
-
-namespace {
-
-const char kTestCommandCategoty[] = "test_command_category";
-const char kTestCommandId[] = "cmd_1";
-
-} // namespace
-
-class DBusCommandProxyTest : public ::testing::Test {
- public:
- void SetUp() override {
- // Set up a mock DBus bus object.
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SYSTEM;
- bus_ = new dbus::MockBus(options);
- // By default, don't worry about threading assertions.
- EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
- EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
-
- // Command instance.
- // TODO(antonm): Test results.
- auto json = CreateDictionaryValue(R"({
- 'robot': {
- 'jump': {
- 'parameters': {
- 'height': {
- 'type': 'integer',
- 'minimum': 0,
- 'maximum': 100
- },
- '_jumpType': {
- 'type': 'string',
- 'enum': ['_withAirFlip', '_withSpin', '_withKick']
- }
- },
- 'results': {
- 'foo': {
- 'type': 'integer'
- },
- 'bar': {
- 'type': 'string'
- }
- },
- 'progress': {
- 'progress': {
- 'type': 'integer',
- 'minimum': 0,
- 'maximum': 100
- }
- }
- }
- }
- })");
- CHECK(dict_.LoadCommands(*json, kTestCommandCategoty, nullptr, nullptr))
- << "Failed to parse test command dictionary";
-
- json = CreateDictionaryValue(R"({
- 'name': 'robot.jump',
- 'parameters': {
- 'height': 53,
- '_jumpType': '_withKick'
- }
- })");
- command_instance_ =
- CommandInstance::FromJson(json.get(), "local", dict_, nullptr, nullptr);
- command_instance_->SetID(kTestCommandId);
-
- // Set up a mock ExportedObject to be used with the DBus command proxy.
- std::string cmd_path = dbus_constants::kCommandServicePathPrefix;
- cmd_path += kTestCommandId;
- const dbus::ObjectPath kCmdObjPath(cmd_path);
- // Use a mock exported object for the exported object manager.
- mock_exported_object_command_ =
- new dbus::MockExportedObject(bus_.get(), kCmdObjPath);
- EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath)).Times(AnyNumber())
- .WillRepeatedly(Return(mock_exported_object_command_.get()));
- EXPECT_CALL(*mock_exported_object_command_,
- ExportMethod(_, _, _, _)).Times(AnyNumber());
-
- std::unique_ptr<CommandProxyInterface> command_proxy(
- new DBusCommandProxy(nullptr, bus_, command_instance_.get(), cmd_path));
- command_instance_->AddProxy(std::move(command_proxy));
- GetCommandProxy()->RegisterAsync(
- AsyncEventSequencer::GetDefaultCompletionAction());
- }
-
- void TearDown() override {
- EXPECT_CALL(*mock_exported_object_command_, Unregister()).Times(1);
- command_instance_.reset();
- dict_.Clear();
- bus_ = nullptr;
- }
-
- DBusCommandProxy* GetCommandProxy() const {
- CHECK_EQ(command_instance_->proxies_.size(), 1U);
- return static_cast<DBusCommandProxy*>(command_instance_->proxies_[0].get());
- }
-
- org::chromium::Buffet::CommandAdaptor* GetCommandAdaptor() const {
- return &GetCommandProxy()->dbus_adaptor_;
- }
-
- org::chromium::Buffet::CommandInterface* GetCommandInterface() const {
- // DBusCommandProxy also implements CommandInterface.
- return GetCommandProxy();
- }
-
- std::unique_ptr<CommandInstance> command_instance_;
- CommandDictionary dict_;
-
- scoped_refptr<dbus::MockExportedObject> mock_exported_object_command_;
- scoped_refptr<dbus::MockBus> bus_;
-};
-
-TEST_F(DBusCommandProxyTest, Init) {
- VariantDictionary params = {
- {"height", int32_t{53}},
- {"_jumpType", std::string{"_withKick"}},
- };
- EXPECT_EQ(CommandInstance::kStatusQueued, GetCommandAdaptor()->GetStatus());
- EXPECT_EQ(params, GetCommandAdaptor()->GetParameters());
- EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetProgress());
- EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetResults());
- EXPECT_EQ("robot.jump", GetCommandAdaptor()->GetName());
- EXPECT_EQ(kTestCommandCategoty, GetCommandAdaptor()->GetCategory());
- EXPECT_EQ(kTestCommandId, GetCommandAdaptor()->GetId());
-}
-
-TEST_F(DBusCommandProxyTest, SetProgress) {
- EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(2);
- EXPECT_TRUE(
- GetCommandInterface()->SetProgress(nullptr, {{"progress", int32_t{10}}}));
- EXPECT_EQ(CommandInstance::kStatusInProgress,
- GetCommandAdaptor()->GetStatus());
-
- VariantDictionary progress{{"progress", int32_t{10}}};
- EXPECT_EQ(progress, GetCommandAdaptor()->GetProgress());
-}
-
-TEST_F(DBusCommandProxyTest, SetProgress_OutOfRange) {
- EXPECT_FALSE(GetCommandInterface()->SetProgress(
- nullptr, {{"progress", int32_t{110}}}));
- EXPECT_EQ(CommandInstance::kStatusQueued, GetCommandAdaptor()->GetStatus());
- EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetProgress());
-}
-
-TEST_F(DBusCommandProxyTest, SetResults) {
- EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
- const VariantDictionary results = {
- {"foo", int32_t{42}},
- {"bar", std::string{"foobar"}},
- };
- EXPECT_TRUE(GetCommandInterface()->SetResults(nullptr, results));
- EXPECT_EQ(results, GetCommandAdaptor()->GetResults());
-}
-
-TEST_F(DBusCommandProxyTest, SetResults_UnknownProperty) {
- EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(0);
- const VariantDictionary results = {
- {"quux", int32_t{42}},
- };
- EXPECT_FALSE(GetCommandInterface()->SetResults(nullptr, results));
-}
-
-TEST_F(DBusCommandProxyTest, Abort) {
- EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
- GetCommandInterface()->Abort();
- EXPECT_EQ(CommandInstance::kStatusAborted,
- GetCommandAdaptor()->GetStatus());
-}
-
-TEST_F(DBusCommandProxyTest, Cancel) {
- EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
- GetCommandInterface()->Cancel();
- EXPECT_EQ(CommandInstance::kStatusCancelled,
- GetCommandAdaptor()->GetStatus());
-}
-
-TEST_F(DBusCommandProxyTest, Done) {
- // 1 property update:
- // status: queued -> done
- EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
- GetCommandInterface()->Done();
- EXPECT_EQ(CommandInstance::kStatusDone, GetCommandAdaptor()->GetStatus());
-}
-
-} // namespace buffet
diff --git a/buffet/commands/enum_to_string.h b/buffet/commands/enum_to_string.h
deleted file mode 100644
index 031c164..0000000
--- a/buffet/commands/enum_to_string.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_ENUM_TO_STRING_H_
-#define BUFFET_COMMANDS_ENUM_TO_STRING_H_
-
-#include <string>
-
-namespace buffet {
-
-// Helps to map enumeration to stings and back.
-//
-// Usage example:
-// .h file:
-// enum class MyEnum { kV1, kV2 };
-// std::string ToString(MyEnum id);
-// bool FromString(const std::string& str, MyEnum* id);
-//
-// .cc file:
-// template <>
-// const EnumToString<MyEnum>::Map EnumToString<MyEnum>::kMap[] = {
-// {MyEnum::kV1, "v1"},
-// {MyEnum::kV2, "v2"},
-// };
-//
-// std::string ToString(MyEnum id) {
-// return EnumToString<MyEnum>::FindNameById(id);
-// }
-//
-// bool FromString(const std::string& str, MyEnum* id) {
-// return EnumToString<MyEnum>::FindIdByName(str, id));
-// }
-template <typename T>
-class EnumToString final {
- public:
- static std::string FindNameById(T id) {
- for (const Map& m : kMap) {
- if (m.id == id) {
- CHECK(m.name);
- return m.name;
- }
- }
- NOTREACHED();
- return std::string();
- }
-
- static bool FindIdByName(const std::string& name, T* id) {
- for (const Map& m : kMap) {
- if (m.name && m.name == name) {
- *id = m.id;
- return true;
- }
- }
- return false;
- }
-
- private:
- struct Map {
- const T id;
- const char* const name;
- };
-
- static const Map kMap[];
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_ENUM_TO_STRING_H_
diff --git a/buffet/commands/object_schema.cc b/buffet/commands/object_schema.cc
deleted file mode 100644
index 6838794..0000000
--- a/buffet/commands/object_schema.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/object_schema.h"
-
-#include <algorithm>
-#include <limits>
-
-#include <base/logging.h>
-#include <base/values.h>
-#include <chromeos/map_utils.h>
-
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-namespace {
-
-// Helper function for to create a PropType based on type string.
-// Generates an error if the string identifies an unknown type.
-std::unique_ptr<PropType> CreatePropType(const std::string& type_name,
- chromeos::ErrorPtr* error) {
- std::string primary_type;
- std::string array_type;
- chromeos::string_utils::SplitAtFirst(type_name, ".", &primary_type,
- &array_type, false);
- std::unique_ptr<PropType> prop;
- ValueType type;
- if (PropType::GetTypeFromTypeString(primary_type, &type)) {
- prop = PropType::Create(type);
- if (prop && type == ValueType::Array && !array_type.empty()) {
- auto items_type = CreatePropType(array_type, error);
- if (items_type) {
- prop->GetArray()->SetItemType(std::move(items_type));
- } else {
- prop.reset();
- return prop;
- }
- }
- }
- if (!prop) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownType,
- "Unknown type %s", type_name.c_str());
- }
- return prop;
-}
-
-// Generates "no_type_info" error.
-void ErrorInvalidTypeInfo(chromeos::ErrorPtr* error) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kNoTypeInfo,
- "Unable to determine parameter type");
-}
-
-// Helper function for PropFromJson to handle the case of parameter being
-// defined as a JSON string like this:
-// "prop":"..."
-std::unique_ptr<PropType> PropFromJsonString(
- const base::Value& value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error) {
- std::string type_name;
- CHECK(value.GetAsString(&type_name)) << "Unable to get string value";
- std::unique_ptr<PropType> prop = CreatePropType(type_name, error);
- base::DictionaryValue empty;
- if (prop && !prop->FromJson(&empty, base_schema, error))
- prop.reset();
-
- return prop;
-}
-
-// Detects a type based on JSON array. Inspects the first element of the array
-// to deduce the PropType from. Returns the string name of the type detected
-// or empty string is type detection failed.
-std::string DetectArrayType(const base::ListValue* list,
- const PropType* base_schema,
- bool allow_arrays) {
- std::string type_name;
- if (base_schema) {
- type_name = base_schema->GetTypeAsString();
- } else if (list->GetSize() > 0) {
- const base::Value* first_element = nullptr;
- if (list->Get(0, &first_element)) {
- switch (first_element->GetType()) {
- case base::Value::TYPE_BOOLEAN:
- type_name = PropType::GetTypeStringFromType(ValueType::Boolean);
- break;
- case base::Value::TYPE_INTEGER:
- type_name = PropType::GetTypeStringFromType(ValueType::Int);
- break;
- case base::Value::TYPE_DOUBLE:
- type_name = PropType::GetTypeStringFromType(ValueType::Double);
- break;
- case base::Value::TYPE_STRING:
- type_name = PropType::GetTypeStringFromType(ValueType::String);
- break;
- case base::Value::TYPE_DICTIONARY:
- type_name = PropType::GetTypeStringFromType(ValueType::Object);
- break;
- case base::Value::TYPE_LIST: {
- if (allow_arrays) {
- type_name = PropType::GetTypeStringFromType(ValueType::Array);
- const base::ListValue* first_element_list = nullptr;
- if (first_element->GetAsList(&first_element_list)) {
- // We do not allow arrays of arrays.
- auto child_type = DetectArrayType(first_element_list, nullptr,
- false);
- if (child_type.empty()) {
- type_name.clear();
- } else {
- type_name += '.' + child_type;
- }
- }
- }
- break;
- }
- default:
- // The rest are unsupported.
- break;
- }
- }
- }
- return type_name;
-}
-
-// Helper function for PropFromJson to handle the case of parameter being
-// defined as a JSON array like this:
-// "prop":[...]
-std::unique_ptr<PropType> PropFromJsonArray(
- const base::Value& value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<PropType> prop;
- const base::ListValue* list = nullptr;
- CHECK(value.GetAsList(&list)) << "Unable to get array value";
- std::string type_name = DetectArrayType(list, base_schema, true);
- if (type_name.empty()) {
- ErrorInvalidTypeInfo(error);
- return prop;
- }
- base::DictionaryValue array_object;
- array_object.SetWithoutPathExpansion(commands::attributes::kOneOf_Enum,
- list->DeepCopy());
- prop = CreatePropType(type_name, error);
- if (prop && !prop->FromJson(&array_object, base_schema, error))
- prop.reset();
-
- return prop;
-}
-
-// Detects a type based on JSON object definition of type. Looks at various
-// members such as minimum/maximum constraints, default and enum values to
-// try to deduce the underlying type of the element. Returns the string name of
-// the type detected or empty string is type detection failed.
-std::string DetectObjectType(const base::DictionaryValue* dict,
- const PropType* base_schema) {
- bool has_min_max = dict->HasKey(commands::attributes::kNumeric_Min) ||
- dict->HasKey(commands::attributes::kNumeric_Max);
-
- // Here we are trying to "detect the type and read in the object based on
- // the deduced type". Later, we'll verify that this detected type matches
- // the expectation of the base schema, if applicable, to make sure we are not
- // changing the expected type. This makes the vendor-side (re)definition of
- // standard and custom commands behave exactly the same.
- // The only problem with this approach was the double-vs-int types.
- // If the type is meant to be a double we want to allow its definition as
- // "min:0, max:0" instead of just forcing it to be only "min:0.0, max:0.0".
- // If we have "minimum" or "maximum", and we have a Double schema object,
- // treat this object as a Double (even if both min and max are integers).
- if (has_min_max && base_schema && base_schema->GetType() == ValueType::Double)
- return PropType::GetTypeStringFromType(ValueType::Double);
-
- // If we have at least one "minimum" or "maximum" that is Double,
- // it's a Double.
- const base::Value* value = nullptr;
- if (dict->Get(commands::attributes::kNumeric_Min, &value) &&
- value->IsType(base::Value::TYPE_DOUBLE))
- return PropType::GetTypeStringFromType(ValueType::Double);
- if (dict->Get(commands::attributes::kNumeric_Max, &value) &&
- value->IsType(base::Value::TYPE_DOUBLE))
- return PropType::GetTypeStringFromType(ValueType::Double);
-
- // If we have "minimum" or "maximum", it's an Integer.
- if (has_min_max)
- return PropType::GetTypeStringFromType(ValueType::Int);
-
- // If we have "minLength" or "maxLength", it's a String.
- if (dict->HasKey(commands::attributes::kString_MinLength) ||
- dict->HasKey(commands::attributes::kString_MaxLength))
- return PropType::GetTypeStringFromType(ValueType::String);
-
- // If we have "properties", it's an object.
- if (dict->HasKey(commands::attributes::kObject_Properties))
- return PropType::GetTypeStringFromType(ValueType::Object);
-
- // If we have "items", it's an array.
- if (dict->HasKey(commands::attributes::kItems))
- return PropType::GetTypeStringFromType(ValueType::Array);
-
- // If we have "enum", it's an array. Detect type from array elements.
- const base::ListValue* list = nullptr;
- if (dict->GetListWithoutPathExpansion(
- commands::attributes::kOneOf_Enum, &list))
- return DetectArrayType(list, base_schema, true);
-
- // If we have "default", try to use it for type detection.
- if (dict->Get(commands::attributes::kDefault, &value)) {
- if (value->IsType(base::Value::TYPE_DOUBLE))
- return PropType::GetTypeStringFromType(ValueType::Double);
- if (value->IsType(base::Value::TYPE_INTEGER))
- return PropType::GetTypeStringFromType(ValueType::Int);
- if (value->IsType(base::Value::TYPE_BOOLEAN))
- return PropType::GetTypeStringFromType(ValueType::Boolean);
- if (value->IsType(base::Value::TYPE_STRING))
- return PropType::GetTypeStringFromType(ValueType::String);
- if (value->IsType(base::Value::TYPE_LIST)) {
- CHECK(value->GetAsList(&list)) << "List value expected";
- std::string child_type = DetectArrayType(list, base_schema, false);
- if (!child_type.empty()) {
- return PropType::GetTypeStringFromType(ValueType::Array) + '.' +
- child_type;
- }
- }
- }
-
- return std::string{};
-}
-
-// Helper function for PropFromJson to handle the case of parameter being
-// defined as a JSON object like this:
-// "prop":{...}
-std::unique_ptr<PropType> PropFromJsonObject(
- const base::Value& value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<PropType> prop;
- const base::DictionaryValue* dict = nullptr;
- CHECK(value.GetAsDictionary(&dict)) << "Unable to get dictionary value";
- std::string type_name;
- if (dict->HasKey(commands::attributes::kType)) {
- if (!dict->GetString(commands::attributes::kType, &type_name)) {
- ErrorInvalidTypeInfo(error);
- return prop;
- }
- } else {
- type_name = DetectObjectType(dict, base_schema);
- }
- if (type_name.empty()) {
- if (!base_schema) {
- ErrorInvalidTypeInfo(error);
- return prop;
- }
- type_name = base_schema->GetTypeAsString();
- }
- prop = CreatePropType(type_name, error);
- if (prop && !prop->FromJson(dict, base_schema, error))
- prop.reset();
-
- return prop;
-}
-
-} // anonymous namespace
-
-ObjectSchema::ObjectSchema() {}
-ObjectSchema::~ObjectSchema() {}
-
-std::unique_ptr<ObjectSchema> ObjectSchema::Clone() const {
- std::unique_ptr<ObjectSchema> cloned{new ObjectSchema};
- for (const auto& pair : properties_) {
- cloned->properties_.emplace(pair.first, pair.second->Clone());
- }
- cloned->extra_properties_allowed_ = extra_properties_allowed_;
- return cloned;
-}
-
-void ObjectSchema::AddProp(const std::string& name,
- std::unique_ptr<PropType> prop) {
- // Not using emplace() here to make sure we override existing properties.
- properties_[name] = std::move(prop);
-}
-
-const PropType* ObjectSchema::GetProp(const std::string& name) const {
- auto p = properties_.find(name);
- return p != properties_.end() ? p->second.get() : nullptr;
-}
-
-std::unique_ptr<base::DictionaryValue> ObjectSchema::ToJson(
- bool full_schema, chromeos::ErrorPtr* error) const {
- std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue);
- for (const auto& pair : properties_) {
- auto PropDef = pair.second->ToJson(full_schema, error);
- if (!PropDef)
- return {};
- value->SetWithoutPathExpansion(pair.first, PropDef.release());
- }
- return value;
-}
-
-bool ObjectSchema::FromJson(const base::DictionaryValue* value,
- const ObjectSchema* object_schema,
- chromeos::ErrorPtr* error) {
- Properties properties;
- base::DictionaryValue::Iterator iter(*value);
- while (!iter.IsAtEnd()) {
- std::string name = iter.key();
- const PropType* base_schema =
- object_schema ? object_schema->GetProp(iter.key()) : nullptr;
- auto prop_type = PropFromJson(iter.value(), base_schema, error);
- if (prop_type) {
- properties.emplace(iter.key(), std::move(prop_type));
- } else {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropDef,
- "Error in definition of property '%s'",
- iter.key().c_str());
- return false;
- }
- iter.Advance();
- }
- properties_ = std::move(properties);
- return true;
-}
-
-std::unique_ptr<PropType> ObjectSchema::PropFromJson(
- const base::Value& value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error) {
- if (value.IsType(base::Value::TYPE_STRING)) {
- // A string value is a short-hand object specification and provides
- // the parameter type.
- return PropFromJsonString(value, base_schema, error);
- } else if (value.IsType(base::Value::TYPE_LIST)) {
- // One of the enumerated types.
- return PropFromJsonArray(value, base_schema, error);
- } else if (value.IsType(base::Value::TYPE_DICTIONARY)) {
- // Full parameter definition.
- return PropFromJsonObject(value, base_schema, error);
- }
- static const std::map<base::Value::Type, const char*> type_names = {
- {base::Value::TYPE_NULL, "Null"},
- {base::Value::TYPE_BOOLEAN, "Boolean"},
- {base::Value::TYPE_INTEGER, "Integer"},
- {base::Value::TYPE_DOUBLE, "Double"},
- {base::Value::TYPE_STRING, "String"},
- {base::Value::TYPE_BINARY, "Binary"},
- {base::Value::TYPE_DICTIONARY, "Object"},
- {base::Value::TYPE_LIST, "Array"},
- };
- const char* type_name = chromeos::GetOrDefault(type_names, value.GetType(),
- "<unknown>");
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownType,
- "Unexpected JSON value type: %s", type_name);
- return {};
-}
-
-std::unique_ptr<ObjectSchema> ObjectSchema::Create() {
- return std::unique_ptr<ObjectSchema>{new ObjectSchema};
-}
-
-} // namespace buffet
diff --git a/buffet/commands/object_schema.h b/buffet/commands/object_schema.h
deleted file mode 100644
index 1f272e6..0000000
--- a/buffet/commands/object_schema.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_OBJECT_SCHEMA_H_
-#define BUFFET_COMMANDS_OBJECT_SCHEMA_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <chromeos/errors/error.h>
-
-namespace base {
-class Value;
-class DictionaryValue;
-} // namespace base
-
-namespace buffet {
-
-class PropType;
-
-// ObjectSchema is a class representing an object definition in GCD command
-// schema. This could represent a GCD command definition, but also it can be
-// used when defining custom object types for command properties such as
-// output media type (paper) for print command. The schema definition for
-// these type of object description is the same.
-class ObjectSchema final {
- public:
- // Do not inline the constructor/destructor to allow forward-declared type
- // PropType to be part of |properties_| member.
- ObjectSchema();
- ~ObjectSchema();
-
- // Properties is a string-to-PropType map representing a list of
- // properties defined for a command/object. The key is the parameter
- // name and the value is the parameter type definition object.
- using Properties = std::map<std::string, std::unique_ptr<PropType>>;
-
- // Makes a full copy of this object.
- virtual std::unique_ptr<ObjectSchema> Clone() const;
-
- // Add a new parameter definition.
- void AddProp(const std::string& name, std::unique_ptr<PropType> prop);
-
- // Finds parameter type definition by name. Returns nullptr if not found.
- const PropType* GetProp(const std::string& name) const;
-
- // Gets the list of all the properties defined.
- const Properties& GetProps() const { return properties_; }
-
- // Specify whether extra properties are allowed on objects described by
- // this schema. When validating a value of an object type, we can
- // make sure that the value has only the properties explicitly defined by
- // the schema and no other (custom) properties are allowed.
- // This is to support JSON Schema's "additionalProperties" specification.
- bool GetExtraPropertiesAllowed() const { return extra_properties_allowed_; }
- void SetExtraPropertiesAllowed(bool allowed) {
- extra_properties_allowed_ = allowed;
- }
-
- // Saves the object schema to JSON. When |full_schema| is set to true,
- // then all properties and constraints are saved, otherwise, only
- // the overridden (not inherited) ones are saved.
- std::unique_ptr<base::DictionaryValue> ToJson(
- bool full_schema, chromeos::ErrorPtr* error) const;
-
- // Loads the object schema from JSON. If |object_schema| is not nullptr, it is
- // used as a base schema to inherit omitted properties and constraints from.
- bool FromJson(const base::DictionaryValue* value,
- const ObjectSchema* object_schema,
- chromeos::ErrorPtr* error);
-
- // Helper factory method to create a new instance of ObjectSchema object.
- static std::unique_ptr<ObjectSchema> Create();
-
- // Helper method to load property type definitions from JSON.
- static std::unique_ptr<PropType> PropFromJson(const base::Value& value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error);
-
- private:
- // Internal parameter type definition map.
- Properties properties_;
- bool extra_properties_allowed_{false};
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_OBJECT_SCHEMA_H_
diff --git a/buffet/commands/object_schema_unittest.cc b/buffet/commands/object_schema_unittest.cc
deleted file mode 100644
index 1330099..0000000
--- a/buffet/commands/object_schema_unittest.cc
+++ /dev/null
@@ -1,1441 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/object_schema.h"
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <vector>
-
-#include <base/json/json_reader.h>
-#include <base/json/json_writer.h>
-#include <base/values.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/prop_constraints.h"
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/schema_constants.h"
-#include "buffet/commands/unittest_utils.h"
-
-namespace buffet {
-
-using unittests::CreateValue;
-using unittests::CreateDictionaryValue;
-
-namespace {
-
-template <typename T>
-std::vector<T> GetArrayValues(const native_types::Array& arr) {
- std::vector<T> values;
- values.reserve(arr.size());
- for (const auto& prop_value : arr) {
- values.push_back(prop_value->GetValueAsAny().Get<T>());
- }
- return values;
-}
-
-template <typename T>
-std::vector<T> GetOneOfValues(const PropType* prop_type) {
- auto one_of = static_cast<const ConstraintOneOf*>(
- prop_type->GetConstraint(ConstraintType::OneOf));
- if (!one_of)
- return {};
-
- return GetArrayValues<T>(one_of->set_.value);
-}
-
-} // anonymous namespace
-
-TEST(CommandSchema, IntPropType_Empty) {
- IntPropType prop;
- EXPECT_TRUE(prop.GetConstraints().empty());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
-}
-
-TEST(CommandSchema, IntPropType_Types) {
- IntPropType prop;
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(&prop, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, IntPropType_ToJson) {
- IntPropType prop;
- EXPECT_JSON_EQ("'integer'", *prop.ToJson(false, nullptr));
- EXPECT_JSON_EQ("{'type':'integer'}", *prop.ToJson(true, nullptr));
- IntPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'minimum':3}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maximum':-7}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maximum':5,'minimum':0}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'enum':[1,2,3]}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("[1,2,3]", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'default':123}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'default':123}", *param2.ToJson(false, nullptr));
-}
-
-TEST(CommandSchema, IntPropType_FromJson) {
- IntPropType prop;
- prop.AddMinMaxConstraint(2, 8);
- IntPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(2, prop.GetMinValue());
- EXPECT_EQ(8, prop.GetMaxValue());
- prop.AddMinMaxConstraint(-2, 30);
- param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(),
- &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(7, param2.GetMinValue());
- EXPECT_EQ(30, param2.GetMaxValue());
- param2.FromJson(CreateDictionaryValue("{'maximum':17}").get(),
- &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(-2, param2.GetMinValue());
- EXPECT_EQ(17, param2.GetMaxValue());
-
- ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':3}").get(),
- &prop, nullptr));
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param2.GetDefaultValue());
- EXPECT_EQ(3, param2.GetDefaultValue()->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, IntPropType_Validate) {
- IntPropType prop;
- prop.AddMinMaxConstraint(2, 4);
- chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("-1").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("0").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("1").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("2").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("3").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("4").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(prop.ValidateValue(CreateValue("5").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("true").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("3.0").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'3'").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
-}
-
-TEST(CommandSchema, IntPropType_CreateValue) {
- IntPropType prop;
- chromeos::ErrorPtr error;
- auto val = prop.CreateValue(2, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(2, val->GetValueAsAny().Get<int>());
-
- val = prop.CreateValue("blah", &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, BoolPropType_Empty) {
- BooleanPropType prop;
- EXPECT_TRUE(prop.GetConstraints().empty());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
-}
-
-TEST(CommandSchema, BoolPropType_Types) {
- BooleanPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(&prop, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, BoolPropType_ToJson) {
- BooleanPropType prop;
- EXPECT_JSON_EQ("'boolean'", *prop.ToJson(false, nullptr));
- EXPECT_JSON_EQ("{'type':'boolean'}", *prop.ToJson(true, nullptr));
- BooleanPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'enum':[true,false]}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("[true,false]", *param2.ToJson(false, nullptr));
- EXPECT_JSON_EQ("{'enum':[true,false],'type':'boolean'}",
- *param2.ToJson(true, nullptr));
- param2.FromJson(CreateDictionaryValue("{'default':true}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'default':true}", *param2.ToJson(false, nullptr));
-}
-
-TEST(CommandSchema, BoolPropType_FromJson) {
- BooleanPropType prop;
- prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop,
- nullptr);
- BooleanPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(std::vector<bool>{true}, GetOneOfValues<bool>(&prop));
-
- BooleanPropType prop_base;
- BooleanPropType param3;
- ASSERT_TRUE(param3.FromJson(CreateDictionaryValue("{'default':false}").get(),
- &prop_base, nullptr));
- EXPECT_TRUE(param3.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param3.GetDefaultValue());
- EXPECT_FALSE(param3.GetDefaultValue()->GetBoolean()->GetValue());
-}
-
-TEST(CommandSchema, BoolPropType_Validate) {
- BooleanPropType prop;
- prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop,
- nullptr);
- chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("false").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("true").get(), &error));
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("1").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("3.0").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'3'").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
-}
-
-TEST(CommandSchema, BoolPropType_CreateValue) {
- BooleanPropType prop;
- chromeos::ErrorPtr error;
- auto val = prop.CreateValue(true, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(val->GetValueAsAny().Get<bool>());
-
- val = prop.CreateValue("blah", &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, DoublePropType_Empty) {
- DoublePropType prop;
- EXPECT_DOUBLE_EQ(std::numeric_limits<double>::lowest(), prop.GetMinValue());
- EXPECT_DOUBLE_EQ((std::numeric_limits<double>::max)(), prop.GetMaxValue());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
-}
-
-TEST(CommandSchema, DoublePropType_Types) {
- DoublePropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(&prop, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, DoublePropType_ToJson) {
- DoublePropType prop;
- EXPECT_JSON_EQ("'number'", *prop.ToJson(false, nullptr));
- EXPECT_JSON_EQ("{'type':'number'}", *prop.ToJson(true, nullptr));
- DoublePropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'minimum':3}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'minimum':3.0}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'maximum':-7}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'maximum':-7.0}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':5}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maximum':5.0,'minimum':0.0}",
- *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'default':12.3}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'default':12.3}", *param2.ToJson(false, nullptr));
-}
-
-TEST(CommandSchema, DoublePropType_FromJson) {
- DoublePropType prop;
- prop.AddMinMaxConstraint(2.5, 8.7);
- DoublePropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(2.5, prop.GetMinValue());
- EXPECT_DOUBLE_EQ(8.7, prop.GetMaxValue());
- prop.AddMinMaxConstraint(-2.2, 30.4);
- param2.FromJson(CreateDictionaryValue("{'minimum':7}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(7.0, param2.GetMinValue());
- EXPECT_DOUBLE_EQ(30.4, param2.GetMaxValue());
- param2.FromJson(CreateDictionaryValue("{'maximum':17.2}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(-2.2, param2.GetMinValue());
- EXPECT_DOUBLE_EQ(17.2, param2.GetMaxValue());
- param2.FromJson(CreateDictionaryValue("{'minimum':0,'maximum':6.1}").get(),
- &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_DOUBLE_EQ(0.0, param2.GetMinValue());
- EXPECT_DOUBLE_EQ(6.1, param2.GetMaxValue());
-
- ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':-1.234}").get(),
- &prop, nullptr));
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param2.GetDefaultValue());
- EXPECT_DOUBLE_EQ(-1.234, param2.GetDefaultValue()->GetDouble()->GetValue());
-}
-
-TEST(CommandSchema, DoublePropType_Validate) {
- DoublePropType prop;
- prop.AddMinMaxConstraint(-1.2, 1.3);
- chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("-2").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("-1.3").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("-1.2").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("0.0").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("1.3").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(prop.ValidateValue(CreateValue("1.31").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("true").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'0.0'").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
-}
-
-TEST(CommandSchema, DoublePropType_CreateValue) {
- DoublePropType prop;
- chromeos::ErrorPtr error;
- auto val = prop.CreateValue(2.0, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_DOUBLE_EQ(2.0, val->GetValueAsAny().Get<double>());
-
- val = prop.CreateValue("blah", &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, StringPropType_Empty) {
- StringPropType prop;
- EXPECT_EQ(0, prop.GetMinLength());
- EXPECT_EQ((std::numeric_limits<int>::max)(), prop.GetMaxLength());
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
-}
-
-TEST(CommandSchema, StringPropType_Types) {
- StringPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(&prop, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, StringPropType_ToJson) {
- StringPropType prop;
- EXPECT_JSON_EQ("'string'", *prop.ToJson(false, nullptr));
- EXPECT_JSON_EQ("{'type':'string'}", *prop.ToJson(true, nullptr));
- StringPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'minLength':3}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'minLength':3}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'maxLength':7}").get(), &prop,
- nullptr);
- EXPECT_JSON_EQ("{'maxLength':7}", *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'minLength':0,'maxLength':5}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'maxLength':5,'minLength':0}",
- *param2.ToJson(false, nullptr));
- param2.FromJson(CreateDictionaryValue("{'default':'abcd'}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'default':'abcd'}", *param2.ToJson(false, nullptr));
-}
-
-TEST(CommandSchema, StringPropType_FromJson) {
- StringPropType prop;
- prop.AddLengthConstraint(2, 8);
- StringPropType param2;
- param2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_FALSE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(2, prop.GetMinLength());
- EXPECT_EQ(8, prop.GetMaxLength());
- prop.AddLengthConstraint(3, 5);
- param2.FromJson(CreateDictionaryValue("{'minLength':4}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(4, param2.GetMinLength());
- EXPECT_EQ(5, param2.GetMaxLength());
- param2.FromJson(CreateDictionaryValue("{'maxLength':8}").get(), &prop,
- nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(3, param2.GetMinLength());
- EXPECT_EQ(8, param2.GetMaxLength());
- param2.FromJson(CreateDictionaryValue(
- "{'minLength':1,'maxLength':7}").get(), &prop, nullptr);
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- EXPECT_TRUE(param2.IsBasedOnSchema());
- EXPECT_EQ(1, param2.GetMinLength());
- EXPECT_EQ(7, param2.GetMaxLength());
-
- ASSERT_TRUE(param2.FromJson(CreateDictionaryValue("{'default':'foo'}").get(),
- &prop, nullptr));
- EXPECT_TRUE(param2.HasOverriddenAttributes());
- ASSERT_NE(nullptr, param2.GetDefaultValue());
- EXPECT_EQ("foo", param2.GetDefaultValue()->GetString()->GetValue());
-}
-
-TEST(CommandSchema, StringPropType_Validate) {
- StringPropType prop;
- prop.AddLengthConstraint(1, 3);
- chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("''").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- prop.AddLengthConstraint(2, 3);
- EXPECT_FALSE(prop.ValidateValue(CreateValue("''").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'a'").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'ab'").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'abc'").get(), &error));
- EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'abcd'").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-
- prop.FromJson(CreateDictionaryValue("{'enum':['abc','def','xyz!!']}").get(),
- nullptr, &error);
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'abc'").get(), &error));
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'def'").get(), &error));
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'xyz!!'").get(), &error));
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'xyz'").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, StringPropType_CreateValue) {
- StringPropType prop;
- chromeos::ErrorPtr error;
- auto val = prop.CreateValue(std::string{"blah"}, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ("blah", val->GetValueAsAny().Get<std::string>());
-
- val = prop.CreateValue(4, &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, ObjectPropType_Empty) {
- ObjectPropType prop;
- EXPECT_TRUE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
-}
-
-TEST(CommandSchema, ObjectPropType_Types) {
- ObjectPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(&prop, prop.GetObject());
- EXPECT_EQ(nullptr, prop.GetArray());
-}
-
-TEST(CommandSchema, ObjectPropType_ToJson) {
- ObjectPropType prop;
- EXPECT_JSON_EQ("{'additionalProperties':false,'properties':{}}",
- *prop.ToJson(false, nullptr));
- EXPECT_JSON_EQ(
- "{'additionalProperties':false,'properties':{},'type':'object'}",
- *prop.ToJson(true, nullptr));
- EXPECT_FALSE(prop.IsBasedOnSchema());
- ObjectPropType prop2;
- prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *prop2.ToJson(false, nullptr));
- EXPECT_TRUE(prop2.IsBasedOnSchema());
-
- auto schema = ObjectSchema::Create();
- schema->AddProp("expires", PropType::Create(ValueType::Int));
- auto pw = PropType::Create(ValueType::String);
- pw->GetString()->AddLengthConstraint(6, 100);
- schema->AddProp("password", std::move(pw));
- prop2.SetObjectSchema(std::move(schema));
- auto expected = R"({
- 'additionalProperties': false,
- 'properties': {
- 'expires': 'integer',
- 'password': {
- 'maxLength': 100,
- 'minLength': 6
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *prop2.ToJson(false, nullptr));
-
- expected = R"({
- 'additionalProperties': false,
- 'properties': {
- 'expires': {
- 'type': 'integer'
- },
- 'password': {
- 'maxLength': 100,
- 'minLength': 6,
- 'type': 'string'
- }
- },
- 'type': 'object'
- })";
- EXPECT_JSON_EQ(expected, *prop2.ToJson(true, nullptr));
-
- ObjectPropType prop3;
- ASSERT_TRUE(prop3.FromJson(CreateDictionaryValue(
- "{'default':{'expires':3,'password':'abracadabra'}}").get(), &prop2,
- nullptr));
- expected = R"({
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- }
- })";
- EXPECT_JSON_EQ(expected, *prop3.ToJson(false, nullptr));
-
- expected = R"({
- 'additionalProperties': false,
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- },
- 'properties': {
- 'expires': {
- 'type': 'integer'
- },
- 'password': {
- 'maxLength': 100,
- 'minLength': 6,
- 'type': 'string'
- }
- },
- 'type': 'object'
- })";
- EXPECT_JSON_EQ(expected, *prop3.ToJson(true, nullptr));
-
- ObjectPropType prop4;
- ASSERT_TRUE(prop4.FromJson(CreateDictionaryValue(
- "{'additionalProperties':true,"
- "'default':{'expires':3,'password':'abracadabra'}}").get(), &prop2,
- nullptr));
- expected = R"({
- 'additionalProperties': true,
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- },
- 'properties': {
- 'expires': 'integer',
- 'password': {
- 'maxLength': 100,
- 'minLength': 6
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *prop4.ToJson(false, nullptr));
-
- expected = R"({
- 'additionalProperties': true,
- 'default': {
- 'expires': 3,
- 'password': 'abracadabra'
- },
- 'properties': {
- 'expires': {
- 'type': 'integer'
- },
- 'password': {
- 'maxLength': 100,
- 'minLength': 6,
- 'type': 'string'
- }
- },
- 'type': 'object'
- })";
- EXPECT_JSON_EQ(expected, *prop4.ToJson(true, nullptr));
-}
-
-TEST(CommandSchema, ObjectPropType_FromJson) {
- ObjectPropType base_prop;
- EXPECT_TRUE(base_prop.FromJson(CreateDictionaryValue(
- "{'properties':{'name':'string','age':'integer'}}").get(), nullptr,
- nullptr));
- auto schema = base_prop.GetObject()->GetObjectSchemaPtr();
- const PropType* prop = schema->GetProp("name");
- EXPECT_EQ(ValueType::String, prop->GetType());
- prop = schema->GetProp("age");
- EXPECT_EQ(ValueType::Int, prop->GetType());
-
- ObjectPropType prop2;
- ASSERT_TRUE(prop2.FromJson(CreateDictionaryValue(
- "{'properties':{'name':'string','age':'integer'},"
- "'default':{'name':'Bob','age':33}}").get(), nullptr, nullptr));
- ASSERT_NE(nullptr, prop2.GetDefaultValue());
- const ObjectValue* defval = prop2.GetDefaultValue()->GetObject();
- ASSERT_NE(nullptr, defval);
- native_types::Object objval = defval->GetValue();
- EXPECT_EQ("Bob", objval["name"]->GetString()->GetValue());
- EXPECT_EQ(33, objval["age"]->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, ObjectPropType_Validate) {
- ObjectPropType prop;
- prop.FromJson(CreateDictionaryValue(
- "{'properties':{'expires':'integer',"
- "'password':{'maxLength':100,'minLength':6}}}").get(), nullptr,
- nullptr);
- chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue(
- "{'expires':10,'password':'abcdef'}").get(), &error));
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue(
- "{'expires':10}").get(), &error));
- EXPECT_EQ("parameter_missing", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue(
- "{'password':'abcdef'}").get(), &error));
- EXPECT_EQ("parameter_missing", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue(
- "{'expires':10,'password':'abcde'}").get(), &error));
- EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue("2").get(), &error));
- EXPECT_EQ("type_mismatch", error->GetCode());
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue(
- "{'expires':10,'password':'abcdef','retry':true}").get(), &error));
- EXPECT_EQ("unexpected_parameter", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ObjectPropType_Validate_Enum) {
- ObjectPropType prop;
- EXPECT_TRUE(prop.FromJson(CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'},"
- "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
- nullptr, nullptr));
- chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue(
- "{'height':20,'width':10}").get(), &error));
- error.reset();
-
- EXPECT_TRUE(prop.ValidateValue(CreateValue(
- "{'height':200,'width':100}").get(), &error));
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue(
- "{'height':12,'width':10}").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ObjectPropType_CreateValue) {
- ObjectPropType prop;
- IntPropType int_type;
- ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'},"
- "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
- nullptr, nullptr));
- native_types::Object obj{
- {"width", int_type.CreateValue(10, nullptr)},
- {"height", int_type.CreateValue(20, nullptr)},
- };
-
- chromeos::ErrorPtr error;
- auto val = prop.CreateValue(obj, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(obj, val->GetValueAsAny().Get<native_types::Object>());
-
- val = prop.CreateValue("blah", &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, ArrayPropType_Empty) {
- ArrayPropType prop;
- EXPECT_FALSE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_EQ(nullptr, prop.GetDefaultValue());
- EXPECT_EQ(nullptr, prop.GetItemTypePtr());
- prop.SetItemType(PropType::Create(ValueType::Int));
- EXPECT_TRUE(prop.HasOverriddenAttributes());
- EXPECT_FALSE(prop.IsBasedOnSchema());
- EXPECT_NE(nullptr, prop.GetItemTypePtr());
-}
-
-TEST(CommandSchema, ArrayPropType_Types) {
- ArrayPropType prop;
- EXPECT_EQ(nullptr, prop.GetInt());
- EXPECT_EQ(nullptr, prop.GetBoolean());
- EXPECT_EQ(nullptr, prop.GetDouble());
- EXPECT_EQ(nullptr, prop.GetString());
- EXPECT_EQ(nullptr, prop.GetObject());
- EXPECT_EQ(&prop, prop.GetArray());
-}
-
-TEST(CommandSchema, ArrayPropType_ToJson) {
- ArrayPropType prop;
- prop.SetItemType(PropType::Create(ValueType::Int));
- EXPECT_JSON_EQ("{'items':'integer'}", *prop.ToJson(false, nullptr));
- EXPECT_JSON_EQ("{'items':{'type':'integer'},'type':'array'}",
- *prop.ToJson(true, nullptr));
- EXPECT_FALSE(prop.IsBasedOnSchema());
- ArrayPropType prop2;
- prop2.FromJson(CreateDictionaryValue("{}").get(), &prop, nullptr);
- EXPECT_JSON_EQ("{}", *prop2.ToJson(false, nullptr));
- EXPECT_TRUE(prop2.IsBasedOnSchema());
- prop2.FromJson(CreateDictionaryValue("{'default':[1,2,3]}").get(),
- &prop, nullptr);
- EXPECT_JSON_EQ("{'default':[1,2,3]}", *prop2.ToJson(false, nullptr));
- EXPECT_JSON_EQ(
- "{'default':[1,2,3],'items':{'type':'integer'},'type':'array'}",
- *prop2.ToJson(true, nullptr));
-}
-
-TEST(CommandSchema, ArrayPropType_FromJson) {
- ArrayPropType prop;
- EXPECT_TRUE(prop.FromJson(
- CreateDictionaryValue("{'items':'integer'}").get(), nullptr, nullptr));
- EXPECT_EQ(ValueType::Int, prop.GetItemTypePtr()->GetType());
-
- ArrayPropType prop2;
- ASSERT_TRUE(prop2.FromJson(CreateDictionaryValue(
- "{'items':'string','default':['foo', 'bar', 'baz']}").get(), nullptr,
- nullptr));
- ASSERT_NE(nullptr, prop2.GetDefaultValue());
- const ArrayValue* defval = prop2.GetDefaultValue()->GetArray();
- ASSERT_NE(nullptr, defval);
- EXPECT_EQ((std::vector<std::string>{"foo", "bar", "baz"}),
- GetArrayValues<std::string>(defval->GetValue()));
-}
-
-TEST(CommandSchema, ArrayPropType_Validate) {
- ArrayPropType prop;
- prop.FromJson(CreateDictionaryValue(
- "{'items':{'minimum':2.3, 'maximum':10.5}}").get(), nullptr,
- nullptr);
-
- chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue("[3,4,10.5]").get(), &error));
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[2]").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- EXPECT_EQ("Value 2 is out of range. It must not be less than 2.3",
- error->GetMessage());
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[4, 5, 20]").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- EXPECT_EQ("Value 20 is out of range. It must not be greater than 10.5",
- error->GetMessage());
- error.reset();
-}
-
-TEST(CommandSchema, ArrayPropType_Validate_Enum) {
- ArrayPropType prop;
- prop.FromJson(CreateDictionaryValue(
- "{'items':'integer', 'enum':[[1], [2,3], [4,5,6]]}").get(), nullptr,
- nullptr);
-
- chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue("[2,3]").get(), &error));
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[2]").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- EXPECT_EQ("Value [2] is invalid. Expected one of [[1],[2,3],[4,5,6]]",
- error->GetMessage());
- error.reset();
-
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[2,3,4]").get(), &error));
- EXPECT_EQ("out_of_range", error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchema, ArrayPropType_CreateValue) {
- ArrayPropType prop;
- ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(
- "{'items':{'properties':{'width':'integer','height':'integer'}}}").get(),
- nullptr, nullptr));
-
- chromeos::ErrorPtr error;
- native_types::Array arr;
-
- auto val = prop.CreateValue(arr, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(arr, val->GetValueAsAny().Get<native_types::Array>());
- EXPECT_JSON_EQ("[]", *val->ToJson(nullptr));
-
- IntPropType int_type;
- ObjectPropType obj_type;
- ASSERT_TRUE(obj_type.FromJson(CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'}}").get(),
- nullptr, nullptr));
- arr.push_back(obj_type.CreateValue(
- native_types::Object{
- {"width", int_type.CreateValue(10, nullptr)},
- {"height", int_type.CreateValue(20, nullptr)},
- },
- nullptr));
- arr.push_back(obj_type.CreateValue(
- native_types::Object{
- {"width", int_type.CreateValue(17, nullptr)},
- {"height", int_type.CreateValue(18, nullptr)},
- },
- nullptr));
-
- val = prop.CreateValue(arr, &error);
- ASSERT_NE(nullptr, val.get());
- EXPECT_EQ(nullptr, error.get());
- EXPECT_EQ(arr, val->GetValueAsAny().Get<native_types::Array>());
- EXPECT_JSON_EQ("[{'height':20,'width':10},{'height':18,'width':17}]",
- *val->ToJson(nullptr));
-
- val = prop.CreateValue("blah", &error);
- EXPECT_EQ(nullptr, val.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
-}
-
-TEST(CommandSchema, ArrayPropType_NestedArrays_NotSupported) {
- ArrayPropType prop;
- chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.FromJson(CreateDictionaryValue(
- "{'items':{'items':'integer'}}").get(), nullptr, &error));
- EXPECT_EQ(errors::commands::kInvalidObjectSchema, error->GetCode());
- error.reset();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeName) {
- ObjectSchema schema;
- const char* schema_str = "{"
- "'param1':'integer',"
- "'param2':'number',"
- "'param3':'string'"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ(ValueType::Int, schema.GetProp("param1")->GetType());
- EXPECT_EQ(ValueType::Double, schema.GetProp("param2")->GetType());
- EXPECT_EQ(ValueType::String, schema.GetProp("param3")->GetType());
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ(nullptr, schema.GetProp("param4"));
-
- int min_int = (std::numeric_limits<int>::min)();
- int max_int = (std::numeric_limits<int>::max)();
- double min_dbl = (std::numeric_limits<double>::lowest)();
- double max_dbl = (std::numeric_limits<double>::max)();
- EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
- EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
- EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
- EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Full_TypeName) {
- ObjectSchema schema;
- const char* schema_str = "{"
- "'param1':{'type':'integer'},"
- "'param2':{'type':'number'},"
- "'param3':{'type':'string'},"
- "'param4':{'type':'array', 'items':'integer'},"
- "'param5':{'type':'object', 'properties':{'p1':'integer'}}"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ(ValueType::Int, schema.GetProp("param1")->GetType());
- EXPECT_EQ(ValueType::Double, schema.GetProp("param2")->GetType());
- EXPECT_EQ(ValueType::String, schema.GetProp("param3")->GetType());
- EXPECT_EQ(ValueType::Array, schema.GetProp("param4")->GetType());
- EXPECT_EQ(ValueType::Object, schema.GetProp("param5")->GetType());
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ("array", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ("object", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ(nullptr, schema.GetProp("param77"));
-
- int min_int = (std::numeric_limits<int>::min)();
- int max_int = (std::numeric_limits<int>::max)();
- double min_dbl = (std::numeric_limits<double>::lowest)();
- double max_dbl = (std::numeric_limits<double>::max)();
- EXPECT_EQ(min_int, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ(min_dbl, schema.GetProp("param2")->GetDouble()->GetMinValue());
- EXPECT_EQ(max_dbl, schema.GetProp("param2")->GetDouble()->GetMaxValue());
- EXPECT_EQ(0, schema.GetProp("param3")->GetString()->GetMinLength());
- EXPECT_EQ(max_int, schema.GetProp("param3")->GetString()->GetMaxLength());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Scalar) {
- ObjectSchema schema;
- const char* schema_str = "{"
- "'param1' :{'minimum':2},"
- "'param2' :{'maximum':10},"
- "'param3' :{'maximum':8, 'minimum':2},"
- "'param4' :{'minimum':2.1},"
- "'param5' :{'maximum':10.1},"
- "'param6' :{'maximum':8.1, 'minimum':3.1},"
- "'param7' :{'maximum':8, 'minimum':3.1},"
- "'param8' :{'maximum':8.1, 'minimum':3},"
- "'param9' :{'minLength':2},"
- "'param10':{'maxLength':10},"
- "'param11':{'maxLength':8, 'minLength':3},"
- "'param12':{'default':12},"
- "'param13':{'default':13.5},"
- "'param14':{'default':true},"
- "'param15':{'default':false},"
- "'param16':{'default':'foobar'},"
- "'param17':{'default':[1,2,3]},"
- "'param18':{'items':'number', 'default':[]}"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param12")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param13")->GetTypeAsString());
- EXPECT_EQ("boolean", schema.GetProp("param14")->GetTypeAsString());
- EXPECT_EQ("boolean", schema.GetProp("param15")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param16")->GetTypeAsString());
- EXPECT_EQ("array", schema.GetProp("param17")->GetTypeAsString());
- auto prop17 = schema.GetProp("param17");
- EXPECT_EQ("integer",
- prop17->GetArray()->GetItemTypePtr()->GetTypeAsString());
- EXPECT_EQ("array", schema.GetProp("param18")->GetTypeAsString());
- auto prop18 = schema.GetProp("param18");
- EXPECT_EQ("number",
- prop18->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- int min_int = (std::numeric_limits<int>::min)();
- int max_int = (std::numeric_limits<int>::max)();
- double min_dbl = (std::numeric_limits<double>::lowest)();
- double max_dbl = (std::numeric_limits<double>::max)();
- EXPECT_EQ(2, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(max_int, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ(min_int, schema.GetProp("param2")->GetInt()->GetMinValue());
- EXPECT_EQ(10, schema.GetProp("param2")->GetInt()->GetMaxValue());
- EXPECT_EQ(2, schema.GetProp("param3")->GetInt()->GetMinValue());
- EXPECT_EQ(8, schema.GetProp("param3")->GetInt()->GetMaxValue());
- EXPECT_DOUBLE_EQ(2.1, schema.GetProp("param4")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(max_dbl,
- schema.GetProp("param4")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(min_dbl,
- schema.GetProp("param5")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(10.1, schema.GetProp("param5")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param6")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param6")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(3.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(8.0, schema.GetProp("param7")->GetDouble()->GetMaxValue());
- EXPECT_DOUBLE_EQ(3.0, schema.GetProp("param8")->GetDouble()->GetMinValue());
- EXPECT_DOUBLE_EQ(8.1, schema.GetProp("param8")->GetDouble()->GetMaxValue());
- EXPECT_EQ(2, schema.GetProp("param9")->GetString()->GetMinLength());
- EXPECT_EQ(max_int, schema.GetProp("param9")->GetString()->GetMaxLength());
- EXPECT_EQ(0, schema.GetProp("param10")->GetString()->GetMinLength());
- EXPECT_EQ(10, schema.GetProp("param10")->GetString()->GetMaxLength());
- EXPECT_EQ(3, schema.GetProp("param11")->GetString()->GetMinLength());
- EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
- const PropValue* val = schema.GetProp("param12")->GetDefaultValue();
- EXPECT_EQ(12, val->GetInt()->GetValue());
- val = schema.GetProp("param13")->GetDefaultValue();
- EXPECT_DOUBLE_EQ(13.5, val->GetDouble()->GetValue());
- val = schema.GetProp("param14")->GetDefaultValue();
- EXPECT_TRUE(val->GetBoolean()->GetValue());
- val = schema.GetProp("param15")->GetDefaultValue();
- EXPECT_FALSE(val->GetBoolean()->GetValue());
- val = schema.GetProp("param16")->GetDefaultValue();
- EXPECT_EQ("foobar", val->GetString()->GetValue());
- val = schema.GetProp("param17")->GetDefaultValue();
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetArrayValues<int>(val->GetArray()->GetValue()));
- val = schema.GetProp("param18")->GetDefaultValue();
- EXPECT_TRUE(val->GetArray()->GetValue().empty());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Shorthand_TypeDeduction_Array) {
- ObjectSchema schema;
- const char* schema_str = "{"
- "'param1' :[0,1,2,3],"
- "'param2' :[0.0,1.1,2.2],"
- "'param3' :['id1', 'id2'],"
- "'param4' :{'enum':[1,2,3]},"
- "'param5' :{'enum':[-1.1,2.2,3]},"
- "'param6' :{'enum':['id0', 'id1']},"
- "'param7' :{'type':'integer', 'enum':[1,2,3]},"
- "'param8' :{'type':'number', 'enum':[1,2,3]},"
- "'param9' :{'type':'number', 'enum':[]},"
- "'param10':{'type':'integer', 'enum':[]},"
- "'param11':[[0,1],[2,3]],"
- "'param12':[['foo','bar']],"
- "'param13':{'enum':[['id0', 'id1']]}"
- "}";
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ("string", schema.GetProp("param6")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param7")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
- EXPECT_EQ("number", schema.GetProp("param9")->GetTypeAsString());
- EXPECT_EQ("integer", schema.GetProp("param10")->GetTypeAsString());
-
- auto prop_type11 = schema.GetProp("param11");
- EXPECT_EQ("array", prop_type11->GetTypeAsString());
- EXPECT_EQ("integer",
- prop_type11->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- auto prop_type12 = schema.GetProp("param12");
- EXPECT_EQ("array", prop_type12->GetTypeAsString());
- EXPECT_EQ("string",
- prop_type12->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- auto prop_type13 = schema.GetProp("param13");
- EXPECT_EQ("array", prop_type12->GetTypeAsString());
- EXPECT_EQ("string",
- prop_type13->GetArray()->GetItemTypePtr()->GetTypeAsString());
-
- EXPECT_EQ((std::vector<int>{0, 1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param1")));
- EXPECT_EQ((std::vector<double>{0.0, 1.1, 2.2}),
- GetOneOfValues<double>(schema.GetProp("param2")));
- EXPECT_EQ((std::vector<std::string>{"id1", "id2"}),
- GetOneOfValues<std::string>(schema.GetProp("param3")));
-
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param4")));
- EXPECT_EQ((std::vector<double>{-1.1, 2.2, 3.0}),
- GetOneOfValues<double>(schema.GetProp("param5")));
- EXPECT_EQ((std::vector<std::string>{"id0", "id1"}),
- GetOneOfValues<std::string>(schema.GetProp("param6")));
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param7")));
- EXPECT_EQ((std::vector<double>{1.0, 2.0, 3.0}),
- GetOneOfValues<double>(schema.GetProp("param8")));
- EXPECT_TRUE(GetOneOfValues<double>(schema.GetProp("param9")).empty());
- EXPECT_TRUE(GetOneOfValues<int>(schema.GetProp("param10")).empty());
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_Inheritance) {
- const char* base_schema_str = "{"
- "'param0' :{'minimum':1, 'maximum':5},"
- "'param1' :{'minimum':1, 'maximum':5},"
- "'param2' :{'minimum':1, 'maximum':5},"
- "'param3' :{'minimum':1, 'maximum':5},"
- "'param4' :{'minimum':1, 'maximum':5},"
- "'param5' :{'minimum':1.1, 'maximum':5.5},"
- "'param6' :{'minimum':1.1, 'maximum':5.5},"
- "'param7' :{'minimum':1.1, 'maximum':5.5},"
- "'param8' :{'minimum':1.1, 'maximum':5.5},"
- "'param9' :{'minLength':1, 'maxLength':5},"
- "'param10':{'minLength':1, 'maxLength':5},"
- "'param11':{'minLength':1, 'maxLength':5},"
- "'param12':{'minLength':1, 'maxLength':5},"
- "'param13':[1,2,3],"
- "'param14':[1,2,3],"
- "'param15':[1.1,2.2,3.3],"
- "'param16':[1.1,2.2,3.3],"
- "'param17':['id1', 'id2'],"
- "'param18':['id1', 'id2'],"
- "'param19':{'minimum':1, 'maximum':5},"
- "'param20':{'default':49},"
- "'param21':{'default':49},"
- "'param22':'integer'"
- "}";
- ObjectSchema base_schema;
- EXPECT_TRUE(base_schema.FromJson(CreateDictionaryValue(base_schema_str).get(),
- nullptr, nullptr));
- const char* schema_str = "{"
- "'param1' :{},"
- "'param2' :{'minimum':2},"
- "'param3' :{'maximum':9},"
- "'param4' :{'minimum':2, 'maximum':9},"
- "'param5' :{},"
- "'param6' :{'minimum':2.2},"
- "'param7' :{'maximum':9.9},"
- "'param8' :{'minimum':2.2, 'maximum':9.9},"
- "'param9' :{},"
- "'param10':{'minLength':3},"
- "'param11':{'maxLength':8},"
- "'param12':{'minLength':3, 'maxLength':8},"
- "'param13':{},"
- "'param14':[1,2,3,4],"
- "'param15':{},"
- "'param16':[1.1,2.2,3.3,4.4],"
- "'param17':{},"
- "'param18':['id1', 'id3'],"
- "'param19':{},"
- "'param20':{},"
- "'param21':{'default':8},"
- "'param22':{'default':123}"
- "}";
- ObjectSchema schema;
- EXPECT_TRUE(schema.FromJson(CreateDictionaryValue(schema_str).get(),
- &base_schema, nullptr));
- EXPECT_EQ(nullptr, schema.GetProp("param0"));
- EXPECT_NE(nullptr, schema.GetProp("param1"));
- EXPECT_EQ("integer", schema.GetProp("param1")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param1")->GetInt()->GetMinValue());
- EXPECT_EQ(5, schema.GetProp("param1")->GetInt()->GetMaxValue());
- EXPECT_EQ("integer", schema.GetProp("param2")->GetTypeAsString());
- EXPECT_EQ(2, schema.GetProp("param2")->GetInt()->GetMinValue());
- EXPECT_EQ(5, schema.GetProp("param2")->GetInt()->GetMaxValue());
- EXPECT_EQ("integer", schema.GetProp("param3")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param3")->GetInt()->GetMinValue());
- EXPECT_EQ(9, schema.GetProp("param3")->GetInt()->GetMaxValue());
- EXPECT_EQ("integer", schema.GetProp("param4")->GetTypeAsString());
- EXPECT_EQ(2, schema.GetProp("param4")->GetInt()->GetMinValue());
- EXPECT_EQ(9, schema.GetProp("param4")->GetInt()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param5")->GetTypeAsString());
- EXPECT_EQ(1.1, schema.GetProp("param5")->GetDouble()->GetMinValue());
- EXPECT_EQ(5.5, schema.GetProp("param5")->GetDouble()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param6")->GetTypeAsString());
- EXPECT_EQ(2.2, schema.GetProp("param6")->GetDouble()->GetMinValue());
- EXPECT_EQ(5.5, schema.GetProp("param6")->GetDouble()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param7")->GetTypeAsString());
- EXPECT_EQ(1.1, schema.GetProp("param7")->GetDouble()->GetMinValue());
- EXPECT_EQ(9.9, schema.GetProp("param7")->GetDouble()->GetMaxValue());
- EXPECT_EQ("number", schema.GetProp("param8")->GetTypeAsString());
- EXPECT_EQ(2.2, schema.GetProp("param8")->GetDouble()->GetMinValue());
- EXPECT_EQ(9.9, schema.GetProp("param8")->GetDouble()->GetMaxValue());
- EXPECT_EQ("string", schema.GetProp("param9")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param9")->GetString()->GetMinLength());
- EXPECT_EQ(5, schema.GetProp("param9")->GetString()->GetMaxLength());
- EXPECT_EQ("string", schema.GetProp("param10")->GetTypeAsString());
- EXPECT_EQ(3, schema.GetProp("param10")->GetString()->GetMinLength());
- EXPECT_EQ(5, schema.GetProp("param10")->GetString()->GetMaxLength());
- EXPECT_EQ("string", schema.GetProp("param11")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param11")->GetString()->GetMinLength());
- EXPECT_EQ(8, schema.GetProp("param11")->GetString()->GetMaxLength());
- EXPECT_EQ("string", schema.GetProp("param12")->GetTypeAsString());
- EXPECT_EQ(3, schema.GetProp("param12")->GetString()->GetMinLength());
- EXPECT_EQ(8, schema.GetProp("param12")->GetString()->GetMaxLength());
- EXPECT_EQ("integer", schema.GetProp("param13")->GetTypeAsString());
- EXPECT_EQ((std::vector<int>{1, 2, 3}),
- GetOneOfValues<int>(schema.GetProp("param13")));
- EXPECT_EQ("integer", schema.GetProp("param14")->GetTypeAsString());
- EXPECT_EQ((std::vector<int>{1, 2, 3, 4}),
- GetOneOfValues<int>(schema.GetProp("param14")));
- EXPECT_EQ("number", schema.GetProp("param15")->GetTypeAsString());
- EXPECT_EQ((std::vector<double>{1.1, 2.2, 3.3}),
- GetOneOfValues<double>(schema.GetProp("param15")));
- EXPECT_EQ("number", schema.GetProp("param16")->GetTypeAsString());
- EXPECT_EQ((std::vector<double>{1.1, 2.2, 3.3, 4.4}),
- GetOneOfValues<double>(schema.GetProp("param16")));
- EXPECT_EQ("string", schema.GetProp("param17")->GetTypeAsString());
- EXPECT_EQ((std::vector<std::string>{"id1", "id2"}),
- GetOneOfValues<std::string>(schema.GetProp("param17")));
- EXPECT_EQ("string", schema.GetProp("param18")->GetTypeAsString());
- EXPECT_EQ((std::vector<std::string>{"id1", "id3"}),
- GetOneOfValues<std::string>(schema.GetProp("param18")));
- EXPECT_EQ("integer", schema.GetProp("param19")->GetTypeAsString());
- EXPECT_EQ(1, schema.GetProp("param19")->GetInt()->GetMinValue());
- EXPECT_EQ(5, schema.GetProp("param19")->GetInt()->GetMaxValue());
- EXPECT_EQ(49,
- schema.GetProp("param20")->GetDefaultValue()->GetInt()->GetValue());
- EXPECT_EQ(8,
- schema.GetProp("param21")->GetDefaultValue()->GetInt()->GetValue());
- EXPECT_EQ(123,
- schema.GetProp("param22")->GetDefaultValue()->GetInt()->GetValue());
-}
-
-TEST(CommandSchema, ObjectSchema_UseDefaults) {
- ObjectPropType prop;
- const char* schema_str = "{'properties':{"
- "'param1':{'default':true},"
- "'param2':{'default':2},"
- "'param3':{'default':3.3},"
- "'param4':{'default':'four'},"
- "'param5':{'default':{'x':5,'y':6},"
- "'properties':{'x':'integer','y':'integer'}},"
- "'param6':{'default':[1,2,3]}"
- "}}";
- ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- nullptr));
-
- // Omit all.
- auto value = prop.CreateValue();
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue("{}").get(), nullptr));
- native_types::Object obj = value->GetObject()->GetValue();
- EXPECT_TRUE(obj["param1"]->GetBoolean()->GetValue());
- EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
- EXPECT_DOUBLE_EQ(3.3, obj["param3"]->GetDouble()->GetValue());
- EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
- native_types::Object param5 = obj["param5"]->GetObject()->GetValue();
- EXPECT_EQ(5, param5["x"]->GetInt()->GetValue());
- EXPECT_EQ(6, param5["y"]->GetInt()->GetValue());
- native_types::Array param6 = obj["param6"]->GetArray()->GetValue();
- EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
-
- // Specify some.
- value = prop.CreateValue();
- const char* val_json = "{"
- "'param1':false,"
- "'param3':33.3,"
- "'param5':{'x':-5,'y':-6}"
- "}";
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
- obj = value->GetObject()->GetValue();
- EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
- EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
- EXPECT_DOUBLE_EQ(33.3, obj["param3"]->GetDouble()->GetValue());
- EXPECT_EQ("four", obj["param4"]->GetString()->GetValue());
- param5 = obj["param5"]->GetObject()->GetValue();
- EXPECT_EQ(-5, param5["x"]->GetInt()->GetValue());
- EXPECT_EQ(-6, param5["y"]->GetInt()->GetValue());
- param6 = obj["param6"]->GetArray()->GetValue();
- EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
-
- // Specify all.
- value = prop.CreateValue();
- val_json = "{"
- "'param1':false,"
- "'param2':22,"
- "'param3':333.3,"
- "'param4':'FOUR',"
- "'param5':{'x':-55,'y':66},"
- "'param6':[-1, 0]"
- "}";
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
- obj = value->GetObject()->GetValue();
- EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
- EXPECT_EQ(22, obj["param2"]->GetInt()->GetValue());
- EXPECT_DOUBLE_EQ(333.3, obj["param3"]->GetDouble()->GetValue());
- EXPECT_EQ("FOUR", obj["param4"]->GetString()->GetValue());
- param5 = obj["param5"]->GetObject()->GetValue();
- EXPECT_EQ(-55, param5["x"]->GetInt()->GetValue());
- EXPECT_EQ(66, param5["y"]->GetInt()->GetValue());
- param6 = obj["param6"]->GetArray()->GetValue();
- EXPECT_EQ((std::vector<int>{-1, 0}), GetArrayValues<int>(param6));
-}
-
-TEST(CommandSchema, ObjectSchema_FromJson_BaseSchema_Failures) {
- ObjectSchema schema;
- chromeos::ErrorPtr error;
- const char* schema_str = "{"
- "'param1':{}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'type':'foo'}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("unknown_type", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':[]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'minimum':'foo'}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':[1,2.2]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'minimum':1, 'enum':[1,2,3]}" // can't have min/max & enum.
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'maximum':1, 'blah':2}" // 'blah' is unexpected.
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'enum':[1,2,3],'default':5}" // 'default' must be 1, 2, or 3.
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':[[1,2.3]]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':[[1,2],[3,4],['blah']]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'default':[]}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':[[[1]],[[2]]]"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'enum':[[['foo']]]}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-
- schema_str = "{"
- "'param1':{'default':[[1],[2]]}"
- "}";
- EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
- &error));
- EXPECT_EQ("no_type_info", error->GetFirstError()->GetCode());
- error.reset();
-}
-
-} // namespace buffet
diff --git a/buffet/commands/prop_constraints.cc b/buffet/commands/prop_constraints.cc
deleted file mode 100644
index 1fd43e6..0000000
--- a/buffet/commands/prop_constraints.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/prop_constraints.h"
-
-#include <base/json/json_writer.h>
-
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-namespace {
-
-// Helper function to convert a property value to string, which is used for
-// error reporting.
-std::string PropValueToString(const PropValue& value) {
- std::string result;
- auto json = value.ToJson(nullptr);
- if (json)
- base::JSONWriter::Write(*json, &result);
- return result;
-}
-
-} // anonymous namespace
-
-// Constraint ----------------------------------------------------------------
-Constraint::~Constraint() {}
-
-bool Constraint::ReportErrorLessThan(chromeos::ErrorPtr* error,
- const std::string& val,
- const std::string& limit) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "Value %s is out of range. It must not be less than %s",
- val.c_str(), limit.c_str());
- return false;
-}
-
-bool Constraint::ReportErrorGreaterThan(chromeos::ErrorPtr* error,
- const std::string& val,
- const std::string& limit) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "Value %s is out of range. It must not be greater than %s",
- val.c_str(), limit.c_str());
- return false;
-}
-
-bool Constraint::ReportErrorNotOneOf(chromeos::ErrorPtr* error,
- const std::string& val,
- const std::vector<std::string>& values) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "Value %s is invalid. Expected one of [%s]", val.c_str(),
- chromeos::string_utils::Join(",", values).c_str());
- return false;
-}
-
-bool Constraint::AddToJsonDict(base::DictionaryValue* dict,
- bool overridden_only,
- chromeos::ErrorPtr* error) const {
- if (!overridden_only || HasOverriddenAttributes()) {
- auto value = ToJson(error);
- if (!value)
- return false;
- dict->SetWithoutPathExpansion(GetDictKey(), value.release());
- }
- return true;
-}
-
-// ConstraintStringLength -----------------------------------------------------
-ConstraintStringLength::ConstraintStringLength(
- const InheritableAttribute<int>& limit) : limit_(limit) {}
-ConstraintStringLength::ConstraintStringLength(int limit) : limit_(limit) {}
-
-bool ConstraintStringLength::HasOverriddenAttributes() const {
- return !limit_.is_inherited;
-}
-
-std::unique_ptr<base::Value> ConstraintStringLength::ToJson(
- chromeos::ErrorPtr* error) const {
- return TypedValueToJson(limit_.value, error);
-}
-
-// ConstraintStringLengthMin --------------------------------------------------
-ConstraintStringLengthMin::ConstraintStringLengthMin(
- const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {}
-ConstraintStringLengthMin::ConstraintStringLengthMin(int limit)
- : ConstraintStringLength(limit) {}
-
-bool ConstraintStringLengthMin::Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const {
- CHECK(value.GetString()) << "Expecting a string value for this constraint";
- const std::string& str = value.GetString()->GetValue();
- int length = static_cast<int>(str.size());
- if (length < limit_.value) {
- if (limit_.value == 1) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "String must not be empty");
- } else {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "String must be at least %d characters long,"
- " actual length of string '%s' is %d",
- limit_.value, str.c_str(), length);
- }
- return false;
- }
- return true;
-}
-
-std::unique_ptr<Constraint>
-ConstraintStringLengthMin::Clone() const {
- return std::unique_ptr<Constraint>{new ConstraintStringLengthMin{limit_}};
-}
-
-std::unique_ptr<Constraint>
-ConstraintStringLengthMin::CloneAsInherited() const {
- return std::unique_ptr<Constraint>{
- new ConstraintStringLengthMin{limit_.value}};
-}
-
-// ConstraintStringLengthMax --------------------------------------------------
-ConstraintStringLengthMax::ConstraintStringLengthMax(
- const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {}
-ConstraintStringLengthMax::ConstraintStringLengthMax(int limit)
- : ConstraintStringLength(limit) {}
-
-bool ConstraintStringLengthMax::Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const {
- CHECK(value.GetString()) << "Expecting a string value for this constraint";
- const std::string& str = value.GetString()->GetValue();
- int length = static_cast<int>(str.size());
- if (length > limit_.value) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kOutOfRange,
- "String must be no more than %d character(s) "
- "long, actual length of string '%s' is %d",
- limit_.value, str.c_str(), length);
- return false;
- }
- return true;
-}
-
-std::unique_ptr<Constraint>
-ConstraintStringLengthMax::Clone() const {
- return std::unique_ptr<Constraint>{new ConstraintStringLengthMax{limit_}};
-}
-
-std::unique_ptr<Constraint>
-ConstraintStringLengthMax::CloneAsInherited() const {
- return std::unique_ptr<Constraint>{
- new ConstraintStringLengthMax{limit_.value}};
-}
-
-// ConstraintOneOf --------------------------------------------------
-ConstraintOneOf::ConstraintOneOf(InheritableAttribute<native_types::Array> set)
- : set_(std::move(set)) {}
-ConstraintOneOf::ConstraintOneOf(native_types::Array set)
- : set_(std::move(set)) {}
-
-bool ConstraintOneOf::Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const {
- for (const auto& item : set_.value) {
- if (value.IsEqual(item.get()))
- return true;
- }
- std::vector<std::string> choice_list;
- choice_list.reserve(set_.value.size());
- for (const auto& item : set_.value) {
- choice_list.push_back(PropValueToString(*item));
- }
- return ReportErrorNotOneOf(error, PropValueToString(value), choice_list);
-}
-
-std::unique_ptr<Constraint> ConstraintOneOf::Clone() const {
- InheritableAttribute<native_types::Array> attr;
- attr.is_inherited = set_.is_inherited;
- attr.value.reserve(set_.value.size());
- for (const auto& prop_value : set_.value) {
- attr.value.push_back(prop_value->Clone());
- }
- return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(attr)}};
-}
-
-std::unique_ptr<Constraint> ConstraintOneOf::CloneAsInherited() const {
- native_types::Array cloned;
- cloned.reserve(set_.value.size());
- for (const auto& prop_value : set_.value) {
- cloned.push_back(prop_value->Clone());
- }
- return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(cloned)}};
-}
-
-std::unique_ptr<base::Value> ConstraintOneOf::ToJson(
- chromeos::ErrorPtr* error) const {
- return TypedValueToJson(set_.value, error);
-}
-
-const char* ConstraintOneOf::GetDictKey() const {
- return commands::attributes::kOneOf_Enum;
-}
-
-} // namespace buffet
diff --git a/buffet/commands/prop_constraints.h b/buffet/commands/prop_constraints.h
deleted file mode 100644
index c6b7e9b..0000000
--- a/buffet/commands/prop_constraints.h
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_PROP_CONSTRAINTS_H_
-#define BUFFET_COMMANDS_PROP_CONSTRAINTS_H_
-
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <base/macros.h>
-#include <base/values.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_constants.h"
-#include "buffet/commands/schema_utils.h"
-
-namespace buffet {
-
-enum class ConstraintType {
- Min,
- Max,
- StringLengthMin,
- StringLengthMax,
- OneOf
-};
-
-// Abstract base class for all parameter constraints. Many constraints are
-// type-dependent. Thus, a numeric parameter could have "minimum" and/or
-// "maximum" constraints specified. Some constraints, such as "OneOf" apply to
-// any data type.
-class Constraint {
- public:
- Constraint() = default;
- virtual ~Constraint();
-
- // Gets the constraint type.
- virtual ConstraintType GetType() const = 0;
-
- // Checks if any of the constraint properties/attributes are overridden
- // from their base schema definition. If the constraint is inherited, then
- // it will not be written to JSON when saving partial schema.
- virtual bool HasOverriddenAttributes() const = 0;
-
- // Validates a parameter against the constraint. Returns true if parameter
- // value satisfies the constraint, otherwise fills the optional |error| with
- // the details for the failure.
- virtual bool Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const = 0;
-
- // Makes a full copy of this Constraint instance.
- virtual std::unique_ptr<Constraint> Clone() const = 0;
-
- // Makes a copy of the constraint object, marking all the attributes
- // as inherited from the original definition.
- virtual std::unique_ptr<Constraint> CloneAsInherited() const = 0;
-
- // Saves the constraint into the specified JSON |dict| object, representing
- // the object schema. If |overridden_only| is set to true, then the
- // inherited constraints will not be added to the schema object.
- virtual bool AddToJsonDict(base::DictionaryValue* dict,
- bool overridden_only,
- chromeos::ErrorPtr* error) const;
-
- // Saves the value of constraint to JSON value. E.g., if the numeric
- // constraint was defined as {"minimum":20} this will create a JSON value
- // of 20. The current design implies that each constraint has one value
- // only. If this assumption changes, this interface needs to be updated
- // accordingly.
- virtual std::unique_ptr<base::Value> ToJson(
- chromeos::ErrorPtr* error) const = 0;
-
- // Overloaded by the concrete class implementation, it should return the
- // JSON object property name to store the constraint's value as.
- // E.g., if the numeric constraint was defined as {"minimum":20} this
- // method should return "minimum".
- virtual const char* GetDictKey() const = 0;
-
- protected:
- // Static helper methods to format common constraint validation errors.
- // They fill the |error| object with specific error message.
- // Since these functions could be used by constraint objects for various
- // data types, the values used in validation are expected to be
- // send as strings already.
- static bool ReportErrorLessThan(chromeos::ErrorPtr* error,
- const std::string& val,
- const std::string& limit);
- static bool ReportErrorGreaterThan(chromeos::ErrorPtr* error,
- const std::string& val,
- const std::string& limit);
-
- static bool ReportErrorNotOneOf(chromeos::ErrorPtr* error,
- const std::string& val,
- const std::vector<std::string>& values);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Constraint);
-};
-
-// ConstraintMinMaxBase is a base class for numeric Minimum and Maximum
-// constraints.
-template<typename T>
-class ConstraintMinMaxBase : public Constraint {
- public:
- explicit ConstraintMinMaxBase(const InheritableAttribute<T>& limit)
- : limit_(limit) {}
- explicit ConstraintMinMaxBase(const T& limit)
- : limit_(limit) {}
-
- // Implementation of Constraint::HasOverriddenAttributes().
- bool HasOverriddenAttributes() const override {
- return !limit_.is_inherited;
- }
-
- // Implementation of Constraint::ToJson().
- std::unique_ptr<base::Value> ToJson(
- chromeos::ErrorPtr* error) const override {
- return TypedValueToJson(limit_.value, error);
- }
-
- // Stores the upper/lower value limit for maximum/minimum constraint.
- // |limit_.is_inherited| indicates whether the constraint is inherited
- // from base schema or overridden.
- InheritableAttribute<T> limit_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintMinMaxBase);
-};
-
-// Implementation of Minimum value constraint for Integer/Double types.
-template<typename T>
-class ConstraintMin : public ConstraintMinMaxBase<T> {
- public:
- explicit ConstraintMin(const InheritableAttribute<T>& limit)
- : ConstraintMinMaxBase<T>(limit) {}
- explicit ConstraintMin(const T& limit)
- : ConstraintMinMaxBase<T>(limit) {}
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override { return ConstraintType::Min; }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const override {
- T v = value.GetValueAsAny().Get<T>();
- if (v < this->limit_.value)
- return this->ReportErrorLessThan(
- error, chromeos::string_utils::ToString(v),
- chromeos::string_utils::ToString(this->limit_.value));
- return true;
- }
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override {
- return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_}};
- }
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override {
- return std::unique_ptr<Constraint>{new ConstraintMin{this->limit_.value}};
- }
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kNumeric_Min;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintMin);
-};
-
-// Implementation of Maximum value constraint for Integer/Double types.
-template<typename T>
-class ConstraintMax : public ConstraintMinMaxBase<T> {
- public:
- explicit ConstraintMax(const InheritableAttribute<T>& limit)
- : ConstraintMinMaxBase<T>(limit) {}
- explicit ConstraintMax(const T& limit)
- : ConstraintMinMaxBase<T>(limit) {}
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override { return ConstraintType::Max; }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const override {
- T v = value.GetValueAsAny().Get<T>();
- if (v > this->limit_.value)
- return this->ReportErrorGreaterThan(
- error, chromeos::string_utils::ToString(v),
- chromeos::string_utils::ToString(this->limit_.value));
- return true;
- }
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override {
- return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_}};
- }
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override {
- return std::unique_ptr<Constraint>{new ConstraintMax{this->limit_.value}};
- }
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kNumeric_Max;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintMax);
-};
-
-// ConstraintStringLength is a base class for Minimum/Maximum string length
-// constraints, similar to ConstraintMinMaxBase of numeric types.
-class ConstraintStringLength : public Constraint {
- public:
- explicit ConstraintStringLength(const InheritableAttribute<int>& limit);
- explicit ConstraintStringLength(int limit);
-
- // Implementation of Constraint::HasOverriddenAttributes().
- bool HasOverriddenAttributes() const override;
- // Implementation of Constraint::ToJson().
- std::unique_ptr<base::Value> ToJson(chromeos::ErrorPtr* error) const override;
-
- // Stores the upper/lower value limit for string length constraint.
- // |limit_.is_inherited| indicates whether the constraint is inherited
- // from base schema or overridden.
- InheritableAttribute<int> limit_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintStringLength);
-};
-
-// Implementation of Minimum string length constraint.
-class ConstraintStringLengthMin : public ConstraintStringLength {
- public:
- explicit ConstraintStringLengthMin(const InheritableAttribute<int>& limit);
- explicit ConstraintStringLengthMin(int limit);
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override {
- return ConstraintType::StringLengthMin;
- }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const override;
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override;
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override;
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kString_MinLength;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMin);
-};
-
-// Implementation of Maximum string length constraint.
-class ConstraintStringLengthMax : public ConstraintStringLength {
- public:
- explicit ConstraintStringLengthMax(const InheritableAttribute<int>& limit);
- explicit ConstraintStringLengthMax(int limit);
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override {
- return ConstraintType::StringLengthMax;
- }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const override;
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override;
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override;
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override {
- return commands::attributes::kString_MaxLength;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintStringLengthMax);
-};
-
-// Implementation of OneOf constraint for different data types.
-class ConstraintOneOf : public Constraint {
- public:
- explicit ConstraintOneOf(InheritableAttribute<native_types::Array> set);
- explicit ConstraintOneOf(native_types::Array set);
-
- // Implementation of Constraint::GetType().
- ConstraintType GetType() const override {
- return ConstraintType::OneOf;
- }
-
- // Implementation of Constraint::HasOverriddenAttributes().
- bool HasOverriddenAttributes() const override {
- return !set_.is_inherited;
- }
-
- // Implementation of Constraint::Validate().
- bool Validate(const PropValue& value,
- chromeos::ErrorPtr* error) const override;
-
- // Implementation of Constraint::Clone().
- std::unique_ptr<Constraint> Clone() const override;
-
- // Implementation of Constraint::CloneAsInherited().
- std::unique_ptr<Constraint> CloneAsInherited() const override;
-
- // Implementation of Constraint::ToJson().
- std::unique_ptr<base::Value> ToJson(chromeos::ErrorPtr* error) const override;
-
- // Implementation of Constraint::GetDictKey().
- const char* GetDictKey() const override;
-
- // Stores the list of acceptable values for the parameter.
- // |set_.is_inherited| indicates whether the constraint is inherited
- // from base schema or overridden.
- InheritableAttribute<native_types::Array> set_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstraintOneOf);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_PROP_CONSTRAINTS_H_
diff --git a/buffet/commands/prop_types.cc b/buffet/commands/prop_types.cc
deleted file mode 100644
index f60f256..0000000
--- a/buffet/commands/prop_types.cc
+++ /dev/null
@@ -1,661 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/prop_types.h"
-
-#include <algorithm>
-#include <limits>
-#include <set>
-
-#include <base/json/json_writer.h>
-#include <base/logging.h>
-#include <base/values.h>
-#include <chromeos/any.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/commands/object_schema.h"
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-// PropType -------------------------------------------------------------------
-PropType::PropType() {
-}
-
-PropType::~PropType() {
-}
-
-std::string PropType::GetTypeAsString() const {
- return GetTypeStringFromType(GetType());
-}
-
-bool PropType::HasOverriddenAttributes() const {
- if (default_.value && !default_.is_inherited)
- return true;
-
- for (const auto& pair : constraints_) {
- if (pair.second->HasOverriddenAttributes())
- return true;
- }
- return false;
-}
-
-std::unique_ptr<base::Value> PropType::ToJson(bool full_schema,
- chromeos::ErrorPtr* error) const {
- if (!full_schema && !HasOverriddenAttributes()) {
- if (based_on_schema_)
- return std::unique_ptr<base::Value>(new base::DictionaryValue);
- return TypedValueToJson(GetTypeAsString(), error);
- }
-
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- if (full_schema) {
- // If we are asked for full_schema definition, then we need to output every
- // parameter property, including the "type", and any constraints.
- // So, we write the "type" only if asked for full schema.
- // Otherwise we will be able to infer the parameter type based on
- // the constraints and their types.
- // That is, the following JSONs could possibly define a parameter:
- // {'type':'integer'} -> explicit "integer" with no constraints
- // {'minimum':10} -> no type specified, but since we have "minimum"
- // and 10 is integer, than this is an integer
- // parameter with min constraint.
- // {'enum':[1,2,3]} -> integer with OneOf constraint.
- // And so is this: [1,2,3] -> an array of ints assume it's an "int" enum.
- dict->SetString(commands::attributes::kType, GetTypeAsString());
- }
-
- if (!full_schema && constraints_.size() == 1) {
- // If we are not asked for full schema, and we have only one constraint
- // which is OneOf, we short-circuit the whole thing and return just
- // the array [1,2,3] instead of an object with "enum" property like:
- // {'enum':[1,2,3]}
- auto p = constraints_.find(ConstraintType::OneOf);
- if (p != constraints_.end()) {
- return p->second->ToJson(error);
- }
- }
-
- for (const auto& pair : constraints_) {
- if (!pair.second->AddToJsonDict(dict.get(), !full_schema, error))
- return std::unique_ptr<base::Value>();
- }
-
- if (default_.value && (full_schema || !default_.is_inherited)) {
- auto defval = default_.value->ToJson(error);
- if (!defval)
- return std::unique_ptr<base::Value>();
- dict->Set(commands::attributes::kDefault, defval.release());
- }
-
- return std::unique_ptr<base::Value>(dict.release());
-}
-
-std::unique_ptr<PropType> PropType::Clone() const {
- auto cloned = PropType::Create(GetType());
- cloned->based_on_schema_ = based_on_schema_;
- for (const auto& pair : constraints_) {
- cloned->constraints_.emplace(pair.first, pair.second->Clone());
- }
- cloned->default_.is_inherited = default_.is_inherited;
- if (default_.value)
- cloned->default_.value = default_.value->Clone();
- return cloned;
-}
-
-bool PropType::FromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error) {
- if (base_schema && base_schema->GetType() != GetType()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kPropTypeChanged,
- "Redefining a property of type %s as %s",
- base_schema->GetTypeAsString().c_str(),
- GetTypeAsString().c_str());
- return false;
- }
- based_on_schema_ = (base_schema != nullptr);
- constraints_.clear();
- // Add the well-known object properties first (like "type", "displayName",
- // "default") to the list of "processed" keys so we do not complain about them
- // when we check for unknown/unexpected keys below.
- std::set<std::string> processed_keys{
- commands::attributes::kType,
- commands::attributes::kDisplayName,
- commands::attributes::kDefault,
- };
- if (!ObjectSchemaFromJson(value, base_schema, &processed_keys, error))
- return false;
- if (base_schema) {
- for (const auto& pair : base_schema->GetConstraints()) {
- constraints_.emplace(pair.first, pair.second->CloneAsInherited());
- }
- }
- if (!ConstraintsFromJson(value, &processed_keys, error))
- return false;
-
- // Now make sure there are no unexpected/unknown keys in the property schema
- // definition object.
- base::DictionaryValue::Iterator iter(*value);
- while (!iter.IsAtEnd()) {
- std::string key = iter.key();
- if (processed_keys.find(key) == processed_keys.end()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownProperty,
- "Unexpected property '%s'", key.c_str());
- return false;
- }
- iter.Advance();
- }
-
- // Read the default value, if specified.
- // We need to do this last since the current type definition must be complete,
- // so we can parse and validate the value of the default.
- const base::Value* defval = nullptr; // Owned by value
- if (value->GetWithoutPathExpansion(commands::attributes::kDefault, &defval)) {
- std::unique_ptr<PropValue> prop_value = CreateValue();
- if (!prop_value->FromJson(defval, error) ||
- !ValidateValue(prop_value->GetValueAsAny(), error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'",
- commands::attributes::kDefault);
- return false;
- }
- default_.value = std::move(prop_value);
- default_.is_inherited = false;
- } else if (base_schema) {
- // If we have the base schema, inherit the type's default value from it.
- // It doesn't matter if the base schema actually has a default value
- // specified or not. If it doesn't, then the current type definition will
- // have no default value set either (|default_.value| is a unique_ptr to
- // PropValue, which can be set to nullptr).
- if (base_schema->default_.value)
- default_.value = base_schema->default_.value->Clone();
- default_.is_inherited = true;
- }
- return true;
-}
-
-void PropType::AddConstraint(std::unique_ptr<Constraint> constraint) {
- constraints_[constraint->GetType()] = std::move(constraint);
-}
-
-void PropType::RemoveConstraint(ConstraintType constraint_type) {
- constraints_.erase(constraint_type);
-}
-
-void PropType::RemoveAllConstraints() {
- constraints_.clear();
-}
-
-const Constraint* PropType::GetConstraint(
- ConstraintType constraint_type) const {
- auto p = constraints_.find(constraint_type);
- return p != constraints_.end() ? p->second.get() : nullptr;
-}
-
-Constraint* PropType::GetConstraint(ConstraintType constraint_type) {
- auto p = constraints_.find(constraint_type);
- return p != constraints_.end() ? p->second.get() : nullptr;
-}
-
-bool PropType::ValidateValue(const base::Value* value,
- chromeos::ErrorPtr* error) const {
- std::unique_ptr<PropValue> val = CreateValue();
- CHECK(val) << "Failed to create value object";
- return val->FromJson(value, error) && ValidateConstraints(*val, error);
-}
-
-bool PropType::ValidateValue(const chromeos::Any& value,
- chromeos::ErrorPtr* error) const {
- return !!CreateValue(value, error);
-}
-
-bool PropType::ValidateConstraints(const PropValue& value,
- chromeos::ErrorPtr* error) const {
- for (const auto& pair : constraints_) {
- if (!pair.second->Validate(value, error))
- return false;
- }
- return true;
-}
-
-const PropType::TypeMap& PropType::GetTypeMap() {
- static TypeMap map = {
- {ValueType::Int, "integer"},
- {ValueType::Double, "number"},
- {ValueType::String, "string"},
- {ValueType::Boolean, "boolean"},
- {ValueType::Object, "object"},
- {ValueType::Array, "array"},
- };
- return map;
-}
-
-std::string PropType::GetTypeStringFromType(ValueType type) {
- for (const auto& pair : GetTypeMap()) {
- if (pair.first == type)
- return pair.second;
- }
- LOG(FATAL) << "Type map is missing a type";
- return std::string();
-}
-
-bool PropType::GetTypeFromTypeString(const std::string& name, ValueType* type) {
- for (const auto& pair : GetTypeMap()) {
- if (pair.second == name) {
- *type = pair.first;
- return true;
- }
- }
- return false;
-}
-
-std::unique_ptr<PropType> PropType::Create(ValueType type) {
- PropType* prop = nullptr;
- switch (type) {
- case buffet::ValueType::Int:
- prop = new IntPropType;
- break;
- case buffet::ValueType::Double:
- prop = new DoublePropType;
- break;
- case buffet::ValueType::String:
- prop = new StringPropType;
- break;
- case buffet::ValueType::Boolean:
- prop = new BooleanPropType;
- break;
- case buffet::ValueType::Object:
- prop = new ObjectPropType;
- break;
- case buffet::ValueType::Array:
- prop = new ArrayPropType;
- break;
- }
- return std::unique_ptr<PropType>(prop);
-}
-
-bool PropType::GenerateErrorValueTypeMismatch(chromeos::ErrorPtr* error) const {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kTypeMismatch,
- "Unable to convert value to type '%s'",
- GetTypeAsString().c_str());
- return false;
-}
-
-template<typename T>
-static std::unique_ptr<Constraint> LoadOneOfConstraint(
- const base::DictionaryValue* value,
- const PropType* prop_type,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<Constraint> constraint;
- const base::Value* list = nullptr; // Owned by |value|
- CHECK(value->Get(commands::attributes::kOneOf_Enum, &list))
- << "'enum' property missing in JSON dictionary";
- native_types::Array choice_list;
- ArrayPropType array_type;
- array_type.SetItemType(prop_type->Clone());
- if (!TypedValueFromJson(list, &array_type, &choice_list, error))
- return constraint;
- InheritableAttribute<native_types::Array> val(std::move(choice_list), false);
- constraint.reset(new ConstraintOneOf{std::move(val)});
- return constraint;
-}
-
-template<class ConstraintClass, typename T>
-static std::unique_ptr<Constraint> LoadMinMaxConstraint(
- const char* dict_key,
- const base::DictionaryValue* value,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<Constraint> constraint;
- InheritableAttribute<T> limit;
-
- const base::Value* src_val = nullptr;
- CHECK(value->Get(dict_key, &src_val)) << "Unable to get min/max constraints";
- if (!TypedValueFromJson(src_val, nullptr, &limit.value, error))
- return constraint;
- limit.is_inherited = false;
-
- constraint.reset(new ConstraintClass{limit});
- return constraint;
-}
-
-// PropTypeBase ----------------------------------------------------------------
-
-template<class Derived, class Value, typename T>
-bool PropTypeBase<Derived, Value, T>::ConstraintsFromJson(
- const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- if (!PropType::ConstraintsFromJson(value, processed_keys, error))
- return false;
-
- if (value->HasKey(commands::attributes::kOneOf_Enum)) {
- auto type = Clone();
- type->RemoveAllConstraints();
- auto constraint = LoadOneOfConstraint<T>(value, type.get(), error);
- if (!constraint)
- return false;
- this->AddConstraint(std::move(constraint));
- this->RemoveConstraint(ConstraintType::Min);
- this->RemoveConstraint(ConstraintType::Max);
- processed_keys->insert(commands::attributes::kOneOf_Enum);
- }
-
- return true;
-}
-
-// NumericPropTypeBase ---------------------------------------------------------
-
-template<class Derived, class Value, typename T>
-bool NumericPropTypeBase<Derived, Value, T>::ConstraintsFromJson(
- const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- if (!Base::ConstraintsFromJson(value, processed_keys, error))
- return false;
-
- if (processed_keys->find(commands::attributes::kOneOf_Enum) ==
- processed_keys->end()) {
- // Process min/max constraints only if "enum" constraint wasn't already
- // specified.
- if (value->HasKey(commands::attributes::kNumeric_Min)) {
- auto constraint = LoadMinMaxConstraint<ConstraintMin<T>, T>(
- commands::attributes::kNumeric_Min, value, error);
- if (!constraint)
- return false;
- this->AddConstraint(std::move(constraint));
- this->RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kNumeric_Min);
- }
- if (value->HasKey(commands::attributes::kNumeric_Max)) {
- auto constraint = LoadMinMaxConstraint<ConstraintMax<T>, T>(
- commands::attributes::kNumeric_Max, value, error);
- if (!constraint)
- return false;
- this->AddConstraint(std::move(constraint));
- this->RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kNumeric_Max);
- }
- }
-
- return true;
-}
-
-// StringPropType -------------------------------------------------------------
-
-bool StringPropType::ConstraintsFromJson(
- const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- if (!Base::ConstraintsFromJson(value, processed_keys, error))
- return false;
-
- if (processed_keys->find(commands::attributes::kOneOf_Enum) ==
- processed_keys->end()) {
- // Process min/max constraints only if "enum" constraint wasn't already
- // specified.
- if (value->HasKey(commands::attributes::kString_MinLength)) {
- auto constraint = LoadMinMaxConstraint<ConstraintStringLengthMin, int>(
- commands::attributes::kString_MinLength, value, error);
- if (!constraint)
- return false;
- AddConstraint(std::move(constraint));
- RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kString_MinLength);
- }
- if (value->HasKey(commands::attributes::kString_MaxLength)) {
- auto constraint = LoadMinMaxConstraint<ConstraintStringLengthMax, int>(
- commands::attributes::kString_MaxLength, value, error);
- if (!constraint)
- return false;
- AddConstraint(std::move(constraint));
- RemoveConstraint(ConstraintType::OneOf);
- processed_keys->insert(commands::attributes::kString_MaxLength);
- }
- }
- return true;
-}
-
-void StringPropType::AddLengthConstraint(int min_len, int max_len) {
- InheritableAttribute<int> min_attr(min_len, false);
- InheritableAttribute<int> max_attr(max_len, false);
- AddConstraint(std::unique_ptr<ConstraintStringLengthMin>{
- new ConstraintStringLengthMin{min_attr}});
- AddConstraint(std::unique_ptr<ConstraintStringLengthMax>{
- new ConstraintStringLengthMax{max_attr}});
-}
-
-int StringPropType::GetMinLength() const {
- auto slc = static_cast<const ConstraintStringLength*>(
- GetConstraint(ConstraintType::StringLengthMin));
- return slc ? slc->limit_.value : 0;
-}
-
-int StringPropType::GetMaxLength() const {
- auto slc = static_cast<const ConstraintStringLength*>(
- GetConstraint(ConstraintType::StringLengthMax));
- return slc ? slc->limit_.value : std::numeric_limits<int>::max();
-}
-
-// ObjectPropType -------------------------------------------------------------
-
-ObjectPropType::ObjectPropType()
- : object_schema_{ObjectSchema::Create(), false} {}
-
-bool ObjectPropType::HasOverriddenAttributes() const {
- return PropType::HasOverriddenAttributes() ||
- !object_schema_.is_inherited;
-}
-
-std::unique_ptr<PropType> ObjectPropType::Clone() const {
- auto cloned = Base::Clone();
-
- cloned->GetObject()->object_schema_.is_inherited =
- object_schema_.is_inherited;
- cloned->GetObject()->object_schema_.value = object_schema_.value->Clone();
- return cloned;
-}
-
-std::unique_ptr<base::Value> ObjectPropType::ToJson(
- bool full_schema, chromeos::ErrorPtr* error) const {
- std::unique_ptr<base::Value> value = PropType::ToJson(full_schema, error);
- if (value) {
- base::DictionaryValue* dict = nullptr;
- CHECK(value->GetAsDictionary(&dict)) << "Expecting a JSON object";
- if (!object_schema_.is_inherited || full_schema) {
- auto object_schema = object_schema_.value->ToJson(full_schema, error);
- if (!object_schema) {
- value.reset();
- return value;
- }
- dict->SetWithoutPathExpansion(commands::attributes::kObject_Properties,
- object_schema.release());
- dict->SetBooleanWithoutPathExpansion(
- commands::attributes::kObject_AdditionalProperties,
- object_schema_.value->GetExtraPropertiesAllowed());
- }
- }
- return value;
-}
-
-bool ObjectPropType::ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- if (!Base::ObjectSchemaFromJson(value, base_schema, processed_keys, error))
- return false;
-
- using commands::attributes::kObject_Properties;
- using commands::attributes::kObject_AdditionalProperties;
-
- const ObjectSchema* base_object_schema = nullptr;
- if (base_schema)
- base_object_schema = base_schema->GetObject()->GetObjectSchemaPtr();
-
- const base::DictionaryValue* props = nullptr;
- if (value->GetDictionaryWithoutPathExpansion(kObject_Properties, &props)) {
- processed_keys->insert(kObject_Properties);
- std::unique_ptr<ObjectSchema> object_schema{new ObjectSchema};
- if (!object_schema->FromJson(props, base_object_schema, error)) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Error parsing object property schema");
- return false;
- }
- bool extra_properties_allowed = false;
- if (value->GetBooleanWithoutPathExpansion(kObject_AdditionalProperties,
- &extra_properties_allowed)) {
- processed_keys->insert(kObject_AdditionalProperties);
- object_schema->SetExtraPropertiesAllowed(extra_properties_allowed);
- }
- object_schema_.value = std::move(object_schema);
- object_schema_.is_inherited = false;
- } else if (base_object_schema) {
- auto cloned_object_schema = base_object_schema->Clone();
- bool extra_properties_allowed = false;
- if (value->GetBooleanWithoutPathExpansion(kObject_AdditionalProperties,
- &extra_properties_allowed)) {
- processed_keys->insert(kObject_AdditionalProperties);
- cloned_object_schema->SetExtraPropertiesAllowed(extra_properties_allowed);
- object_schema_.is_inherited = false;
- } else {
- object_schema_.is_inherited = true;
- }
- object_schema_.value = std::move(cloned_object_schema);
- } else {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Object type definition must include the "
- "object schema ('%s' field not found)",
- kObject_Properties);
- return false;
- }
-
- return true;
-}
-
-chromeos::Any ObjectPropType::ConvertArrayToDBusVariant(
- const native_types::Array& source) const {
- std::vector<chromeos::VariantDictionary> result;
- result.reserve(source.size());
- for (const auto& prop_value : source) {
- chromeos::Any dict = PropValueToDBusVariant(prop_value.get());
- result.push_back(std::move(*dict.GetPtr<chromeos::VariantDictionary>()));
- }
- return result;
-}
-
-bool ObjectPropType::ConvertDBusVariantToArray(
- const chromeos::Any& source,
- native_types::Array* result,
- chromeos::ErrorPtr* error) const {
- if (!source.IsTypeCompatible<std::vector<chromeos::VariantDictionary>>())
- return GenerateErrorValueTypeMismatch(error);
-
- const auto& source_array =
- source.Get<std::vector<chromeos::VariantDictionary>>();
- result->reserve(source_array.size());
- for (const auto& value : source_array) {
- auto prop_value = PropValueFromDBusVariant(this, value, error);
- if (!prop_value)
- return false;
- result->push_back(std::move(prop_value));
- }
- return true;
-}
-
-void ObjectPropType::SetObjectSchema(
- std::unique_ptr<const ObjectSchema> schema) {
- object_schema_.value = std::move(schema);
- object_schema_.is_inherited = false;
-}
-
-// ArrayPropType -------------------------------------------------------------
-
-ArrayPropType::ArrayPropType() {}
-
-bool ArrayPropType::HasOverriddenAttributes() const {
- return PropType::HasOverriddenAttributes() ||
- !item_type_.is_inherited;
-}
-
-std::unique_ptr<PropType> ArrayPropType::Clone() const {
- auto cloned = Base::Clone();
-
- cloned->GetArray()->item_type_.is_inherited = item_type_.is_inherited;
- cloned->GetArray()->item_type_.value = item_type_.value->Clone();
- return cloned;
-}
-
-std::unique_ptr<base::Value> ArrayPropType::ToJson(
- bool full_schema, chromeos::ErrorPtr* error) const {
- std::unique_ptr<base::Value> value = PropType::ToJson(full_schema, error);
- if (value) {
- base::DictionaryValue* dict = nullptr;
- CHECK(value->GetAsDictionary(&dict)) << "Expecting a JSON object";
- if (!item_type_.is_inherited || full_schema) {
- auto type = item_type_.value->ToJson(full_schema, error);
- if (!type) {
- value.reset();
- return value;
- }
- dict->SetWithoutPathExpansion(commands::attributes::kItems,
- type.release());
- }
- }
- return value;
-}
-
-bool ArrayPropType::ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- if (!Base::ObjectSchemaFromJson(value, base_schema, processed_keys, error))
- return false;
-
- using commands::attributes::kItems;
-
- const PropType* base_type = nullptr;
- if (base_schema)
- base_type = base_schema->GetArray()->GetItemTypePtr();
-
- const base::Value* type_value = nullptr;
- if (value->GetWithoutPathExpansion(kItems, &type_value)) {
- processed_keys->insert(kItems);
- auto item_type = ObjectSchema::PropFromJson(*type_value, base_type, error);
- if (!item_type)
- return false;
- if (item_type->GetType() == ValueType::Array) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Arrays of arrays are not supported");
- return false;
- }
- SetItemType(std::move(item_type));
- } else if (!item_type_.value) {
- if (base_type) {
- item_type_.value = base_type->Clone();
- item_type_.is_inherited = true;
- } else {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidObjectSchema,
- "Array type definition must include the "
- "array item type ('%s' field not found)",
- kItems);
- return false;
- }
- }
- return true;
-}
-
-void ArrayPropType::SetItemType(std::unique_ptr<const PropType> item_type) {
- item_type_.value = std::move(item_type);
- item_type_.is_inherited = false;
-}
-
-} // namespace buffet
diff --git a/buffet/commands/prop_types.h b/buffet/commands/prop_types.h
deleted file mode 100644
index 4841db6..0000000
--- a/buffet/commands/prop_types.h
+++ /dev/null
@@ -1,408 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_PROP_TYPES_H_
-#define BUFFET_COMMANDS_PROP_TYPES_H_
-
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <chromeos/any.h>
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/prop_constraints.h"
-#include "buffet/commands/prop_values.h"
-
-namespace buffet {
-
-class IntPropType;
-class DoublePropType;
-class StringPropType;
-class BooleanPropType;
-class ObjectPropType;
-class ArrayPropType;
-
-// PropType is a base class for all parameter type definition objects.
-// Property definitions of a particular type will derive from this class and
-// provide type-specific implementations.
-class PropType {
- public:
- // ConstraintMap is a type alias for a map containing parameter
- // constraints. It is implemented as a map for fast look-ups of constraints
- // of particular type. Also it is expected to have at most one constraint
- // of each type (e.g. it makes no sense to impose two "minimum" constraints
- // onto a numeric parameter).
- using ConstraintMap = std::map<ConstraintType,
- std::unique_ptr<Constraint>>;
-
- PropType();
- virtual ~PropType();
-
- // Gets the parameter type as an enumeration.
- virtual ValueType GetType() const = 0;
- // Gets the parameter type as a string.
- std::string GetTypeAsString() const;
- // Returns true if this parameter definition inherits a type
- // definition from a base object schema.
- bool IsBasedOnSchema() const { return based_on_schema_; }
- // Returns a default value specified for the type, or nullptr if no default
- // is available.
- const PropValue* GetDefaultValue() const { return default_.value.get(); }
- // Gets the constraints specified for the parameter, if any.
- const ConstraintMap& GetConstraints() const {
- return constraints_;
- }
- // Checks if any of the type attributes were overridden from the base
- // schema definition. If this type does not inherit from a base schema,
- // this method returns true.
- // An attribute could be the value of any of the constraints, default
- // value of a parameter or any other data that may be specified in
- // parameter type definition in and can be inherited from the base schema.
- virtual bool HasOverriddenAttributes() const;
-
- // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>.
- virtual IntPropType* GetInt() { return nullptr; }
- virtual IntPropType const* GetInt() const { return nullptr; }
- virtual DoublePropType* GetDouble() { return nullptr; }
- virtual DoublePropType const* GetDouble() const { return nullptr; }
- virtual StringPropType* GetString() { return nullptr; }
- virtual StringPropType const* GetString() const { return nullptr; }
- virtual BooleanPropType* GetBoolean() { return nullptr; }
- virtual BooleanPropType const* GetBoolean() const { return nullptr; }
- virtual ObjectPropType* GetObject() { return nullptr; }
- virtual ObjectPropType const* GetObject() const { return nullptr; }
- virtual ArrayPropType* GetArray() { return nullptr; }
- virtual ArrayPropType const* GetArray() const { return nullptr; }
-
- // Makes a full copy of this type definition.
- virtual std::unique_ptr<PropType> Clone() const;
-
- // Creates an instance of associated value object, using the parameter
- // type as a factory class.
- virtual std::unique_ptr<PropValue> CreateValue() const = 0;
- virtual std::unique_ptr<PropValue> CreateValue(
- const chromeos::Any& val, chromeos::ErrorPtr* error) const = 0;
-
- // Converts an array of PropValue containing the values of the types described
- // by this instance of PropType into an Any containing std::vector<T>, where
- // T corresponds to the native representation of this PropType.
- virtual chromeos::Any ConvertArrayToDBusVariant(
- const native_types::Array& source) const = 0;
-
- // ConvertAnyToArray is the opposite of ConvertArrayToAny().
- // Given an Any containing std::vector<T>, converts each value into the
- // corresponding PropValue of type of this PropType and adds them to
- // |result| array. If type conversion fails, this function returns false
- // and specifies the error details in |error|.
- virtual bool ConvertDBusVariantToArray(const chromeos::Any& source,
- native_types::Array* result,
- chromeos::ErrorPtr* error) const = 0;
-
- // Saves the parameter type definition as a JSON object.
- // If |full_schema| is set to true, the full type definition is saved,
- // otherwise only the overridden properties and attributes from the base
- // schema is saved. That is, inherited properties and attributes are not
- // saved.
- // If it fails, returns "nullptr" and fills in the |error| with additional
- // error information.
- virtual std::unique_ptr<base::Value> ToJson(bool full_schema,
- chromeos::ErrorPtr* error) const;
- // Parses an JSON parameter type definition. Optional |base_schema| may
- // specify the base schema type definition this type should be based upon.
- // If not specified (nullptr), the parameter type is assumed to be a full
- // definition and any omitted required properties are treated as an error.
- // Returns true on success, otherwise fills in the |error| with additional
- // error information.
- virtual bool FromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- chromeos::ErrorPtr* error);
- // Helper function to load object schema from JSON.
- virtual bool ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- return true;
- }
- // Helper function to load type-specific constraints from JSON.
- virtual bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) {
- return true;
- }
-
- // Validates a JSON value for the parameter type to make sure it satisfies
- // the parameter type definition including any specified constraints.
- // Returns false if the |value| does not meet the requirements of the type
- // definition and returns additional information about the failure via
- // the |error| parameter.
- bool ValidateValue(const base::Value* value, chromeos::ErrorPtr* error) const;
-
- // Similar to the above method, but uses Any as the value container.
- bool ValidateValue(const chromeos::Any& value,
- chromeos::ErrorPtr* error) const;
-
- // Additional helper static methods to help with converting a type enum
- // value into a string and back.
- using TypeMap = std::vector<std::pair<ValueType, std::string>>;
- // Returns a list of value types and corresponding type names.
- static const TypeMap& GetTypeMap();
- // Gets the type name string for the given type.
- static std::string GetTypeStringFromType(ValueType type);
- // Finds the type for the given type name. Returns true on success.
- static bool GetTypeFromTypeString(const std::string& name, ValueType* type);
-
- // Creates an instance of PropType-derived class for the specified
- // parameter type.
- static std::unique_ptr<PropType> Create(ValueType type);
-
- // Adds a constraint to the type definition.
- void AddConstraint(std::unique_ptr<Constraint> constraint);
- // Removes a constraint of given type, if it exists.
- void RemoveConstraint(ConstraintType constraint_type);
- // Removes all constraints.
- void RemoveAllConstraints();
-
- // Finds a constraint of given type. Returns nullptr if not found.
- const Constraint* GetConstraint(ConstraintType constraint_type) const;
- Constraint* GetConstraint(ConstraintType constraint_type);
-
- // Validates the given value against all the constraints.
- bool ValidateConstraints(const PropValue& value,
- chromeos::ErrorPtr* error) const;
-
- // Helper method to generate "type mismatch" error when creating a value
- // from this type. Always returns false.
- bool GenerateErrorValueTypeMismatch(chromeos::ErrorPtr* error) const;
-
- protected:
- // Specifies if this parameter definition is derived from a base
- // object schema.
- bool based_on_schema_ = false;
- // A list of constraints specified for the parameter.
- ConstraintMap constraints_;
- // The default value specified for the parameter, if any. If the default
- // value is present, the parameter is treated as optional and the default
- // value is used if the parameter value is omitted when sending a command.
- // Otherwise the parameter is treated as required and, if it is omitted,
- // this is treated as an error.
- InheritableAttribute<std::unique_ptr<PropValue>> default_;
-};
-
-// Base class for all the derived concrete implementations of property
-// type classes. Provides implementations for common methods of PropType base.
-template<class Derived, class Value, typename T>
-class PropTypeBase : public PropType {
- public:
- // Overrides from PropType.
- ValueType GetType() const override { return GetValueType<T>(); }
-
- std::unique_ptr<PropValue> CreateValue() const override {
- if (GetDefaultValue())
- return GetDefaultValue()->Clone();
- return std::unique_ptr<PropValue>{new Value{Clone()}};
- }
-
- std::unique_ptr<PropValue> CreateValue(
- const chromeos::Any& v, chromeos::ErrorPtr* error) const override {
- std::unique_ptr<PropValue> prop_value;
- if (v.IsTypeCompatible<T>()) {
- std::unique_ptr<Value> value{new Value{Clone()}};
- value->SetValue(v.Get<T>());
- if (ValidateConstraints(*value, error))
- prop_value = std::move(value);
- } else {
- GenerateErrorValueTypeMismatch(error);
- }
- return prop_value;
- }
-
- chromeos::Any ConvertArrayToDBusVariant(
- const native_types::Array& source) const override {
- std::vector<T> result;
- result.reserve(source.size());
- for (const auto& prop_value : source) {
- result.push_back(PropValueToDBusVariant(prop_value.get()).Get<T>());
- }
- return result;
- }
-
- bool ConvertDBusVariantToArray(const chromeos::Any& source,
- native_types::Array* result,
- chromeos::ErrorPtr* error) const override {
- if (!source.IsTypeCompatible<std::vector<T>>())
- return GenerateErrorValueTypeMismatch(error);
-
- const auto& source_array = source.Get<std::vector<T>>();
- result->reserve(source_array.size());
- for (const auto& value : source_array) {
- auto prop_value = PropValueFromDBusVariant(this, value, error);
- if (!prop_value)
- return false;
- result->push_back(std::move(prop_value));
- }
- return true;
- }
-
- bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) override;
-};
-
-// Helper base class for Int and Double parameter types.
-template<class Derived, class Value, typename T>
-class NumericPropTypeBase : public PropTypeBase<Derived, Value, T> {
- public:
- using Base = PropTypeBase<Derived, Value, T>;
- bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) override;
-
- // Helper method to set and obtain a min/max constraint values.
- // Used mostly for unit testing.
- void AddMinMaxConstraint(T min_value, T max_value) {
- InheritableAttribute<T> min_attr(min_value, false);
- InheritableAttribute<T> max_attr(max_value, false);
- this->AddConstraint(std::unique_ptr<ConstraintMin<T>>{
- new ConstraintMin<T>{min_attr}});
- this->AddConstraint(std::unique_ptr<ConstraintMax<T>>{
- new ConstraintMax<T>{max_attr}});
- }
- T GetMinValue() const {
- auto mmc = static_cast<const ConstraintMin<T>*>(
- this->GetConstraint(ConstraintType::Min));
- return mmc ? mmc->limit_.value : std::numeric_limits<T>::lowest();
- }
- T GetMaxValue() const {
- auto mmc = static_cast<const ConstraintMax<T>*>(
- this->GetConstraint(ConstraintType::Max));
- return mmc ? mmc->limit_.value : (std::numeric_limits<T>::max)();
- }
-};
-
-// Property definition of Integer type.
-class IntPropType : public NumericPropTypeBase<IntPropType, IntValue, int> {
- public:
- // Overrides from the PropType base class.
- IntPropType* GetInt() override { return this; }
- IntPropType const* GetInt() const override { return this; }
-};
-
-// Property definition of Number type.
-class DoublePropType
- : public NumericPropTypeBase<DoublePropType, DoubleValue, double> {
- public:
- // Overrides from the PropType base class.
- DoublePropType* GetDouble() override { return this; }
- DoublePropType const* GetDouble() const override { return this; }
-};
-
-// Property definition of String type.
-class StringPropType
- : public PropTypeBase<StringPropType, StringValue, std::string> {
- public:
- using Base = PropTypeBase<StringPropType, StringValue, std::string>;
- // Overrides from the PropType base class.
- StringPropType* GetString() override { return this; }
- StringPropType const* GetString() const override { return this; }
-
- bool ConstraintsFromJson(const base::DictionaryValue* value,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) override;
-
- // Helper methods to add and inspect simple constraints.
- // Used mostly for unit testing.
- void AddLengthConstraint(int min_len, int max_len);
- int GetMinLength() const;
- int GetMaxLength() const;
-};
-
-// Property definition of Boolean type.
-class BooleanPropType
- : public PropTypeBase<BooleanPropType, BooleanValue, bool> {
- public:
- // Overrides from the PropType base class.
- BooleanPropType* GetBoolean() override { return this; }
- BooleanPropType const* GetBoolean() const override { return this; }
-};
-
-// Parameter definition of Object type.
-class ObjectPropType
- : public PropTypeBase<ObjectPropType, ObjectValue, native_types::Object> {
- public:
- using Base = PropTypeBase<ObjectPropType, ObjectValue, native_types::Object>;
- ObjectPropType();
-
- // Overrides from the ParamType base class.
- bool HasOverriddenAttributes() const override;
-
- ObjectPropType* GetObject() override { return this; }
- ObjectPropType const* GetObject() const override { return this; }
-
- std::unique_ptr<PropType> Clone() const override;
-
- std::unique_ptr<base::Value> ToJson(bool full_schema,
- chromeos::ErrorPtr* error) const override;
- bool ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) override;
-
- chromeos::Any ConvertArrayToDBusVariant(
- const native_types::Array& source) const override;
-
- bool ConvertDBusVariantToArray(const chromeos::Any& source,
- native_types::Array* result,
- chromeos::ErrorPtr* error) const override;
-
- // Returns a schema for Object-type parameter.
- inline const ObjectSchema* GetObjectSchemaPtr() const {
- return object_schema_.value.get();
- }
- void SetObjectSchema(std::unique_ptr<const ObjectSchema> schema);
-
- private:
- InheritableAttribute<std::unique_ptr<const ObjectSchema>> object_schema_;
-};
-
-// Parameter definition of Array type.
-class ArrayPropType
- : public PropTypeBase<ArrayPropType, ArrayValue, native_types::Array> {
- public:
- using Base = PropTypeBase<ArrayPropType, ArrayValue, native_types::Array>;
- ArrayPropType();
-
- // Overrides from the ParamType base class.
- bool HasOverriddenAttributes() const override;
-
- ArrayPropType* GetArray() override { return this; }
- ArrayPropType const* GetArray() const override { return this; }
-
- std::unique_ptr<PropType> Clone() const override;
-
- std::unique_ptr<base::Value> ToJson(bool full_schema,
- chromeos::ErrorPtr* error) const override;
-
- bool ObjectSchemaFromJson(const base::DictionaryValue* value,
- const PropType* base_schema,
- std::set<std::string>* processed_keys,
- chromeos::ErrorPtr* error) override;
-
- // Returns a type for Array elements.
- inline const PropType* GetItemTypePtr() const {
- return item_type_.value.get();
- }
- void SetItemType(std::unique_ptr<const PropType> item_type);
-
- private:
- InheritableAttribute<std::unique_ptr<const PropType>> item_type_;
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_PROP_TYPES_H_
diff --git a/buffet/commands/prop_values.cc b/buffet/commands/prop_values.cc
deleted file mode 100644
index a4dc391..0000000
--- a/buffet/commands/prop_values.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/prop_values.h"
-
-#include "buffet/commands/prop_types.h"
-
-namespace buffet {
-
-PropValue::PropValue(std::unique_ptr<const PropType> type)
- : type_{std::move(type)} {}
-
-PropValue::PropValue(const PropType* type_ptr)
- : type_{type_ptr->Clone()} {}
-
-PropValue::~PropValue() {}
-
-} // namespace buffet
diff --git a/buffet/commands/prop_values.h b/buffet/commands/prop_values.h
deleted file mode 100644
index 228316f..0000000
--- a/buffet/commands/prop_values.h
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_PROP_VALUES_H_
-#define BUFFET_COMMANDS_PROP_VALUES_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <chromeos/any.h>
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/schema_utils.h"
-
-namespace base {
-class Value;
-class DictionaryValue;
-} // namespace base
-
-namespace buffet {
-
-// Enumeration to indicate supported command parameter types.
-enum class ValueType {
- Int,
- Double,
- String,
- Boolean,
- Object,
- Array,
-};
-
-class PropValue;
-class IntValue;
-class DoubleValue;
-class StringValue;
-class BooleanValue;
-class ObjectValue;
-class ArrayValue;
-
-class PropType;
-
-// Helper methods to get the parameter type enum value for the given
-// native C++ data representation.
-// The generic GetValueType<T>() is undefined, however particular
-// type specializations return the appropriate ValueType.
-template<typename T> ValueType GetValueType(); // Undefined.
-template<>
-inline ValueType GetValueType<int>() { return ValueType::Int; }
-template<>
-inline ValueType GetValueType<double>() { return ValueType::Double; }
-template<>
-inline ValueType GetValueType<std::string>() { return ValueType::String; }
-template<>
-inline ValueType GetValueType<bool>() { return ValueType::Boolean; }
-template<>
-inline ValueType GetValueType<native_types::Object>() {
- return ValueType::Object;
-}
-template<>
-inline ValueType GetValueType<native_types::Array>() {
- return ValueType::Array;
-}
-
-// The base class for property values.
-// Concrete value classes of various types will be derived from this base.
-// A property value is the actual command parameter value (or a concrete value
-// that can be used in constraints and presets). The PropValue is mostly
-// just parsed content of base::Value when a command is dispatched, however
-// it does have some additional functionality:
-// - it has a reference to the type definition (PropType) which is used
-// when validating the value, especially for "object" types.
-// - it can be compared with another instances of values of the same type.
-// This is used to validate the values against "enum"/"one of" constraints.
-class PropValue {
- public:
- explicit PropValue(std::unique_ptr<const PropType> type);
- // Special out-of-line constructor to help implement PropValue::Clone().
- // That method needs to clone the underlying type but can't do this in this
- // header file since PropType is just forward-declared (it needs PropValue
- // fully defined in its own inner workings).
- explicit PropValue(const PropType* type_ptr);
- virtual ~PropValue();
-
- // Gets the type of the value.
- virtual ValueType GetType() const = 0;
-
- // Type conversion methods. Used in lieu of RTTI and dynamic_cast<>.
- virtual IntValue* GetInt() { return nullptr; }
- virtual IntValue const* GetInt() const { return nullptr; }
- virtual DoubleValue* GetDouble() { return nullptr; }
- virtual DoubleValue const* GetDouble() const { return nullptr; }
- virtual StringValue* GetString() { return nullptr; }
- virtual StringValue const* GetString() const { return nullptr; }
- virtual BooleanValue* GetBoolean() { return nullptr; }
- virtual BooleanValue const* GetBoolean() const { return nullptr; }
- virtual ObjectValue* GetObject() { return nullptr; }
- virtual ObjectValue const* GetObject() const { return nullptr; }
- virtual ArrayValue* GetArray() { return nullptr; }
- virtual ArrayValue const* GetArray() const { return nullptr; }
-
- // Makes a full copy of this value class.
- virtual std::unique_ptr<PropValue> Clone() const = 0;
-
- // Saves the value as a JSON object.
- // If it fails, returns nullptr value and fills in the details for the
- // failure in the |error| parameter.
- virtual std::unique_ptr<base::Value> ToJson(
- chromeos::ErrorPtr* error) const = 0;
- // Parses a value from JSON.
- // If it fails, it returns false and provides additional information
- // via the |error| parameter.
- virtual bool FromJson(const base::Value* value,
- chromeos::ErrorPtr* error) = 0;
-
- // Returns the contained C++ value as Any.
- virtual chromeos::Any GetValueAsAny() const = 0;
-
- // Return the type definition of this value.
- const PropType* GetPropType() const { return type_.get(); }
- // Compares two values and returns true if they are equal.
- virtual bool IsEqual(const PropValue* value) const = 0;
-
- protected:
- std::unique_ptr<const PropType> type_;
-};
-
-// A helper template base class for implementing value classes.
-template<typename Derived, typename T>
-class TypedValueBase : public PropValue {
- public:
- // To help refer to this base class from derived classes, define Base to
- // be this class.
- using Base = TypedValueBase<Derived, T>;
- // Expose the non-default constructor of the base class.
- using PropValue::PropValue;
-
- // Overrides from PropValue base class.
- ValueType GetType() const override { return GetValueType<T>(); }
-
- std::unique_ptr<PropValue> Clone() const override {
- std::unique_ptr<Derived> derived{new Derived{type_.get()}};
- derived->value_ = value_;
- return std::move(derived);
- }
-
- std::unique_ptr<base::Value> ToJson(
- chromeos::ErrorPtr* error) const override {
- return TypedValueToJson(value_, error);
- }
-
- bool FromJson(const base::Value* value, chromeos::ErrorPtr* error) override {
- return TypedValueFromJson(value, GetPropType(), &value_, error);
- }
-
- bool IsEqual(const PropValue* value) const override {
- if (GetType() != value->GetType())
- return false;
- const Base* value_base = static_cast<const Base*>(value);
- return CompareValue(GetValue(), value_base->GetValue());
- }
-
- // Helper methods to get and set the C++ representation of the value.
- chromeos::Any GetValueAsAny() const override { return value_; }
- const T& GetValue() const { return value_; }
- void SetValue(T value) { value_ = std::move(value); }
-
- protected:
- T value_{}; // The value of the parameter in C++ data representation.
-};
-
-// Value of type Integer.
-class IntValue final : public TypedValueBase<IntValue, int> {
- public:
- using Base::Base; // Expose the custom constructor of the base class.
- IntValue* GetInt() override { return this; }
- IntValue const* GetInt() const override { return this; }
-};
-
-// Value of type Number.
-class DoubleValue final : public TypedValueBase<DoubleValue, double> {
- public:
- using Base::Base; // Expose the custom constructor of the base class.
- DoubleValue* GetDouble() override { return this; }
- DoubleValue const* GetDouble() const override { return this; }
-};
-
-// Value of type String.
-class StringValue final : public TypedValueBase<StringValue, std::string> {
- public:
- using Base::Base; // Expose the custom constructor of the base class.
- StringValue* GetString() override { return this; }
- StringValue const* GetString() const override { return this; }
-};
-
-// Value of type Boolean.
-class BooleanValue final : public TypedValueBase<BooleanValue, bool> {
- public:
- using Base::Base; // Expose the custom constructor of the base class.
- BooleanValue* GetBoolean() override { return this; }
- BooleanValue const* GetBoolean() const override { return this; }
-};
-
-// Value of type Object.
-class ObjectValue final
- : public TypedValueBase<ObjectValue, native_types::Object> {
- public:
- using Base::Base; // Expose the custom constructor of the base class.
- ObjectValue* GetObject() override { return this; }
- ObjectValue const* GetObject() const override { return this; }
-};
-
-// Value of type Array.
-class ArrayValue final
- : public TypedValueBase<ArrayValue, native_types::Array> {
- public:
- using Base::Base; // Expose the custom constructor of the base class.
- ArrayValue* GetArray() override { return this; }
- ArrayValue const* GetArray() const override { return this; }
-};
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_PROP_VALUES_H_
diff --git a/buffet/commands/schema_constants.cc b/buffet/commands/schema_constants.cc
deleted file mode 100644
index 7af3a89..0000000
--- a/buffet/commands/schema_constants.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-namespace errors {
-namespace commands {
-const char kDomain[] = "command_schema";
-
-const char kOutOfRange[] = "out_of_range";
-const char kTypeMismatch[] = "type_mismatch";
-const char kPropTypeChanged[] = "param_type_changed";
-const char kUnknownType[] = "unknown_type";
-const char kInvalidPropDef[] = "invalid_parameter_definition";
-const char kInvalidPropValue[] = "invalid_parameter_value";
-const char kNoTypeInfo[] = "no_type_info";
-const char kPropertyMissing[] = "parameter_missing";
-const char kUnknownProperty[] = "unexpected_parameter";
-const char kInvalidObjectSchema[] = "invalid_object_schema";
-const char kDuplicateCommandDef[] = "duplicate_command_definition";
-const char kInvalidCommandName[] = "invalid_command_name";
-const char kCommandFailed[] = "command_failed";
-const char kInvalidCommandVisibility[] = "invalid_command_visibility";
-const char kInvalidMinimalRole[] = "invalid_minimal_role";
-} // namespace commands
-} // namespace errors
-
-namespace commands {
-namespace attributes {
-
-const char kType[] = "type";
-const char kDisplayName[] = "displayName";
-const char kDefault[] = "default";
-const char kItems[] = "items";
-
-const char kNumeric_Min[] = "minimum";
-const char kNumeric_Max[] = "maximum";
-
-const char kString_MinLength[] = "minLength";
-const char kString_MaxLength[] = "maxLength";
-
-const char kOneOf_Enum[] = "enum";
-const char kOneOf_Metadata[] = "metadata";
-
-const char kObject_Properties[] = "properties";
-const char kObject_AdditionalProperties[] = "additionalProperties";
-
-const char kCommand_Id[] = "id";
-const char kCommand_Name[] = "name";
-const char kCommand_Parameters[] = "parameters";
-const char kCommand_Progress[] = "progress";
-const char kCommand_Results[] = "results";
-const char kCommand_State[] = "state";
-
-const char kCommand_Role[] = "minimalRole";
-const char kCommand_Role_Manager[] = "manager";
-const char kCommand_Role_Owner[] = "owner";
-const char kCommand_Role_User[] = "user";
-const char kCommand_Role_Viewer[] = "viewer";
-
-const char kCommand_ErrorCode[] = "error.code";
-const char kCommand_ErrorMessage[] = "error.message";
-
-const char kCommand_Visibility[] = "visibility";
-const char kCommand_Visibility_None[] = "none";
-const char kCommand_Visibility_Local[] = "local";
-const char kCommand_Visibility_Cloud[] = "cloud";
-const char kCommand_Visibility_All[] = "all";
-
-} // namespace attributes
-} // namespace commands
-
-} // namespace buffet
diff --git a/buffet/commands/schema_constants.h b/buffet/commands/schema_constants.h
deleted file mode 100644
index f9690fc..0000000
--- a/buffet/commands/schema_constants.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_SCHEMA_CONSTANTS_H_
-#define BUFFET_COMMANDS_SCHEMA_CONSTANTS_H_
-
-namespace buffet {
-
-namespace errors {
-namespace commands {
-// Error domain for command schema description.
-extern const char kDomain[];
-
-// Common command definition error codes.
-extern const char kOutOfRange[];
-extern const char kTypeMismatch[];
-extern const char kPropTypeChanged[];
-extern const char kUnknownType[];
-extern const char kInvalidPropDef[];
-extern const char kInvalidPropValue[];
-extern const char kNoTypeInfo[];
-extern const char kPropertyMissing[];
-extern const char kUnknownProperty[];
-extern const char kInvalidObjectSchema[];
-extern const char kDuplicateCommandDef[];
-extern const char kInvalidCommandName[];
-extern const char kCommandFailed[];
-extern const char kInvalidCommandVisibility[];
-extern const char kInvalidMinimalRole[];
-} // namespace commands
-} // namespace errors
-
-namespace commands {
-namespace attributes {
-// Command description JSON schema attributes.
-extern const char kType[];
-extern const char kDisplayName[];
-extern const char kDefault[];
-extern const char kItems[];
-
-extern const char kNumeric_Min[];
-extern const char kNumeric_Max[];
-
-extern const char kString_MinLength[];
-extern const char kString_MaxLength[];
-
-extern const char kOneOf_Enum[];
-extern const char kOneOf_Metadata[];
-
-extern const char kObject_Properties[];
-extern const char kObject_AdditionalProperties[];
-
-extern const char kCommand_Id[];
-extern const char kCommand_Name[];
-extern const char kCommand_Parameters[];
-extern const char kCommand_Progress[];
-extern const char kCommand_Results[];
-extern const char kCommand_State[];
-
-extern const char kCommand_Role[];
-extern const char kCommand_Role_Manager[];
-extern const char kCommand_Role_Owner[];
-extern const char kCommand_Role_User[];
-extern const char kCommand_Role_Viewer[];
-
-extern const char kCommand_ErrorCode[];
-extern const char kCommand_ErrorMessage[];
-
-extern const char kCommand_Visibility[];
-extern const char kCommand_Visibility_None[];
-extern const char kCommand_Visibility_Local[];
-extern const char kCommand_Visibility_Cloud[];
-extern const char kCommand_Visibility_All[];
-
-} // namespace attributes
-} // namespace commands
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_SCHEMA_CONSTANTS_H_
diff --git a/buffet/commands/schema_utils.cc b/buffet/commands/schema_utils.cc
deleted file mode 100644
index efb758e..0000000
--- a/buffet/commands/schema_utils.cc
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/schema_utils.h"
-
-#include <algorithm>
-#include <set>
-#include <string>
-
-#include <base/json/json_writer.h>
-
-#include "buffet/commands/object_schema.h"
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/prop_values.h"
-
-namespace buffet {
-namespace {
-// Helper function to report "type mismatch" errors when parsing JSON.
-void ReportJsonTypeMismatch(const base::Value* value_in,
- const std::string& expected_type,
- chromeos::ErrorPtr* error) {
- std::string value_as_string;
- base::JSONWriter::Write(*value_in, &value_as_string);
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kTypeMismatch,
- "Unable to convert value %s into %s",
- value_as_string.c_str(), expected_type.c_str());
-}
-
-// Template version of ReportJsonTypeMismatch that deduces the type of expected
-// data from the value_out parameter passed to particular overload of
-// TypedValueFromJson() function. Always returns false.
-template<typename T>
-bool ReportUnexpectedJson(const base::Value* value_in, T*,
- chromeos::ErrorPtr* error) {
- ReportJsonTypeMismatch(value_in,
- PropType::GetTypeStringFromType(GetValueType<T>()),
- error);
- return false;
-}
-
-bool ErrorMissingProperty(chromeos::ErrorPtr* error, const char* param_name) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kPropertyMissing,
- "Required parameter missing: %s", param_name);
- return false;
-}
-} // namespace
-
-// Specializations of TypedValueToJson<T>() for supported C++ types.
-std::unique_ptr<base::Value> TypedValueToJson(bool value,
- chromeos::ErrorPtr* error) {
- return std::unique_ptr<base::Value>(new base::FundamentalValue(value));
-}
-
-std::unique_ptr<base::Value> TypedValueToJson(int value,
- chromeos::ErrorPtr* error) {
- return std::unique_ptr<base::Value>(new base::FundamentalValue(value));
-}
-
-std::unique_ptr<base::Value> TypedValueToJson(double value,
- chromeos::ErrorPtr* error) {
- return std::unique_ptr<base::Value>(new base::FundamentalValue(value));
-}
-
-std::unique_ptr<base::Value> TypedValueToJson(const std::string& value,
- chromeos::ErrorPtr* error) {
- return std::unique_ptr<base::Value>(new base::StringValue(value));
-}
-
-std::unique_ptr<base::Value> TypedValueToJson(const native_types::Object& value,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- for (const auto& pair : value) {
- auto prop_value = pair.second->ToJson(error);
- if (!prop_value)
- return prop_value;
- dict->SetWithoutPathExpansion(pair.first, prop_value.release());
- }
- return std::move(dict);
-}
-
-std::unique_ptr<base::Value> TypedValueToJson(const native_types::Array& value,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<base::ListValue> list(new base::ListValue);
- for (const auto& item : value) {
- auto json = item->ToJson(error);
- if (!json)
- return std::unique_ptr<base::Value>();
- list->Append(json.release());
- }
- return std::move(list);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- bool* value_out,
- chromeos::ErrorPtr* error) {
- return value_in->GetAsBoolean(value_out) ||
- ReportUnexpectedJson(value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- int* value_out,
- chromeos::ErrorPtr* error) {
- return value_in->GetAsInteger(value_out) ||
- ReportUnexpectedJson(value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- double* value_out,
- chromeos::ErrorPtr* error) {
- return value_in->GetAsDouble(value_out) ||
- ReportUnexpectedJson(value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- std::string* value_out,
- chromeos::ErrorPtr* error) {
- return value_in->GetAsString(value_out) ||
- ReportUnexpectedJson(value_in, value_out, error);
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- native_types::Object* value_out,
- chromeos::ErrorPtr* error) {
- const base::DictionaryValue* dict = nullptr;
- if (!value_in->GetAsDictionary(&dict))
- return ReportUnexpectedJson(value_in, value_out, error);
-
- CHECK(type) << "Object definition must be provided";
- CHECK(ValueType::Object == type->GetType()) << "Type must be Object";
-
- const ObjectSchema* object_schema = type->GetObject()->GetObjectSchemaPtr();
- std::set<std::string> keys_processed;
- value_out->clear(); // Clear possible default values already in |value_out|.
- for (const auto& pair : object_schema->GetProps()) {
- const PropValue* def_value = pair.second->GetDefaultValue();
- if (dict->HasKey(pair.first)) {
- auto value = pair.second->CreateValue();
- const base::Value* param_value = nullptr;
- CHECK(dict->GetWithoutPathExpansion(pair.first, ¶m_value))
- << "Unable to get parameter";
- if (!value->FromJson(param_value, error) ||
- !pair.second->ValidateValue(value->GetValueAsAny(), error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'",
- pair.first.c_str());
- return false;
- }
- value_out->emplace_hint(value_out->end(), pair.first, std::move(value));
- } else if (def_value) {
- value_out->emplace_hint(value_out->end(), pair.first, def_value->Clone());
- } else {
- return ErrorMissingProperty(error, pair.first.c_str());
- }
- keys_processed.insert(pair.first);
- }
-
- // Just for sanity, make sure that we processed all the necessary properties
- // and there weren't any extra (unknown) ones specified. If so, ignore
- // them, but log as warnings...
- base::DictionaryValue::Iterator iter(*dict);
- while (!iter.IsAtEnd()) {
- std::string key = iter.key();
- if (keys_processed.find(key) == keys_processed.end() &&
- !object_schema->GetExtraPropertiesAllowed()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownProperty,
- "Unrecognized parameter '%s'", key.c_str());
- return false;
- }
- iter.Advance();
- }
-
- // Now go over all property values and validate them.
- for (const auto& pair : *value_out) {
- const PropType* prop_type = pair.second->GetPropType();
- CHECK(prop_type) << "Value property type must be available";
- if (!prop_type->ValidateConstraints(*pair.second, error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'",
- pair.first.c_str());
- return false;
- }
- }
- return true;
-}
-
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- native_types::Array* value_out,
- chromeos::ErrorPtr* error) {
- const base::ListValue* list = nullptr;
- if (!value_in->GetAsList(&list))
- return ReportUnexpectedJson(value_in, value_out, error);
-
- CHECK(type) << "Array type definition must be provided";
- CHECK(ValueType::Array == type->GetType()) << "Type must be Array";
- const PropType* item_type = type->GetArray()->GetItemTypePtr();
- CHECK(item_type) << "Incomplete array type definition";
-
- // This value might already contain values from the type defaults.
- // Clear them first before proceeding.
- value_out->clear();
- value_out->reserve(list->GetSize());
- for (const base::Value* item : *list) {
- std::unique_ptr<PropValue> prop_value = item_type->CreateValue();
- if (!prop_value->FromJson(item, error) ||
- !item_type->ValidateValue(prop_value->GetValueAsAny(), error)) {
- return false;
- }
- value_out->push_back(std::move(prop_value));
- }
- return true;
-}
-
-// Compares two sets of key-value pairs from two Objects.
-static bool obj_cmp(const native_types::Object::value_type& v1,
- const native_types::Object::value_type& v2) {
- return (v1.first == v2.first) && v1.second->IsEqual(v2.second.get());
-}
-
-bool operator==(const native_types::Object& obj1,
- const native_types::Object& obj2) {
- if (obj1.size() != obj2.size())
- return false;
-
- auto pair = std::mismatch(obj1.begin(), obj1.end(), obj2.begin(), obj_cmp);
- return pair == std::make_pair(obj1.end(), obj2.end());
-}
-
-bool operator==(const native_types::Array& arr1,
- const native_types::Array& arr2) {
- if (arr1.size() != arr2.size())
- return false;
-
- using Type = const native_types::Array::value_type;
- // Compare two array items.
- auto arr_cmp = [](const Type& v1, const Type& v2) {
- return v1->IsEqual(v2.get());
- };
- auto pair = std::mismatch(arr1.begin(), arr1.end(), arr2.begin(), arr_cmp);
- return pair == std::make_pair(arr1.end(), arr2.end());
-}
-
-std::string ToString(const native_types::Object& obj) {
- auto val = TypedValueToJson(obj, nullptr);
- std::string str;
- base::JSONWriter::Write(*val, &str);
- return str;
-}
-
-std::string ToString(const native_types::Array& arr) {
- auto val = TypedValueToJson(arr, nullptr);
- std::string str;
- base::JSONWriter::Write(*val, &str);
- return str;
-}
-
-chromeos::Any PropValueToDBusVariant(const PropValue* value) {
- if (value->GetType() == ValueType::Object)
- return ObjectToDBusVariant(value->GetObject()->GetValue());
-
- if (value->GetType() == ValueType::Array) {
- const PropType* item_type =
- value->GetPropType()->GetArray()->GetItemTypePtr();
- return item_type->ConvertArrayToDBusVariant(value->GetArray()->GetValue());
- }
- return value->GetValueAsAny();
-}
-
-chromeos::VariantDictionary
-ObjectToDBusVariant(const native_types::Object& object) {
- chromeos::VariantDictionary dict;
- for (const auto& pair : object) {
- // Since we are inserting the elements from native_types::Object which is
- // a map, the keys are already sorted. So use the "end()" position as a hint
- // for dict.insert() so the destination map can optimize its insertion
- // time.
- chromeos::Any prop = PropValueToDBusVariant(pair.second.get());
- dict.emplace_hint(dict.end(), pair.first, std::move(prop));
- }
- return dict;
-}
-
-std::unique_ptr<const PropValue> PropValueFromDBusVariant(
- const PropType* type,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const PropValue> result;
- if (type->GetType() == ValueType::Array) {
- // Special case for array types.
- // We expect the |value| to contain std::vector<T>, while PropValue must use
- // native_types::Array instead. Do the conversion.
- native_types::Array arr;
- const PropType* item_type = type->GetArray()->GetItemTypePtr();
- if (item_type->ConvertDBusVariantToArray(value, &arr, error))
- result = type->CreateValue(arr, error);
- } else if (type->GetType() == ValueType::Object) {
- // Special case for object types.
- // We expect the |value| to contain chromeos::VariantDictionary, while
- // PropValue must use native_types::Object instead. Do the conversion.
- if (!value.IsTypeCompatible<chromeos::VariantDictionary>()) {
- type->GenerateErrorValueTypeMismatch(error);
- return result;
- }
- CHECK(nullptr != type->GetObject()->GetObjectSchemaPtr())
- << "An object type must have a schema defined for it";
- native_types::Object obj;
- if (!ObjectFromDBusVariant(type->GetObject()->GetObjectSchemaPtr(),
- value.Get<chromeos::VariantDictionary>(),
- &obj,
- error)) {
- return result;
- }
-
- result = type->CreateValue(std::move(obj), error);
- } else {
- result = type->CreateValue(value, error);
- }
-
- return result;
-}
-
-bool ObjectFromDBusVariant(const ObjectSchema* object_schema,
- const chromeos::VariantDictionary& dict,
- native_types::Object* obj,
- chromeos::ErrorPtr* error) {
- std::set<std::string> keys_processed;
- obj->clear();
- // First go over all object parameters defined by type's object schema and
- // extract the corresponding parameters from the source dictionary.
- for (const auto& pair : object_schema->GetProps()) {
- const PropValue* def_value = pair.second->GetDefaultValue();
- auto it = dict.find(pair.first);
- if (it != dict.end()) {
- const PropType* prop_type = pair.second.get();
- CHECK(prop_type) << "Value property type must be available";
- auto prop_value = PropValueFromDBusVariant(prop_type, it->second, error);
- if (!prop_value) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'",
- pair.first.c_str());
- return false;
- }
- obj->emplace_hint(obj->end(), pair.first, std::move(prop_value));
- } else if (def_value) {
- obj->emplace_hint(obj->end(), pair.first, def_value->Clone());
- } else {
- ErrorMissingProperty(error, pair.first.c_str());
- return false;
- }
- keys_processed.insert(pair.first);
- }
-
- // Make sure that we processed all the necessary properties and there weren't
- // any extra (unknown) ones specified, unless the schema allows them.
- if (!object_schema->GetExtraPropertiesAllowed()) {
- for (const auto& pair : dict) {
- if (keys_processed.find(pair.first) == keys_processed.end()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- errors::commands::kDomain,
- errors::commands::kUnknownProperty,
- "Unrecognized property '%s'",
- pair.first.c_str());
- return false;
- }
- }
- }
-
- return true;
-}
-
-} // namespace buffet
diff --git a/buffet/commands/schema_utils.h b/buffet/commands/schema_utils.h
deleted file mode 100644
index 59e3b39..0000000
--- a/buffet/commands/schema_utils.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_SCHEMA_UTILS_H_
-#define BUFFET_COMMANDS_SCHEMA_UTILS_H_
-
-#include <limits>
-#include <map>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include <base/values.h>
-#include <chromeos/any.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/variant_dictionary.h>
-
-namespace buffet {
-
-class PropType;
-class PropValue;
-class ObjectSchema;
-class ObjectValue;
-
-namespace native_types {
-// C++ representation of object values.
-using Object = std::map<std::string, std::shared_ptr<const PropValue>>;
-// C++ representation of array of values.
-using Array = std::vector<std::shared_ptr<const PropValue>>;
-} // namespace native_types
-
-// Converts an object to string.
-std::string ToString(const native_types::Object& obj);
-
-// Converts an array to string.
-std::string ToString(const native_types::Array& arr);
-
-// InheritableAttribute class is used for specifying various command parameter
-// attributes that can be inherited from a base (parent) schema.
-// The |value| still specifies the actual attribute values, whether it
-// is inherited or overridden, while |is_inherited| can be used to identify
-// if the attribute was inherited (true) or overridden (false).
-template<typename T>
-class InheritableAttribute final {
- public:
- InheritableAttribute() = default;
- explicit InheritableAttribute(T val)
- : value(std::move(val)), is_inherited(true) {}
- InheritableAttribute(T val, bool inherited)
- : value(std::move(val)), is_inherited(inherited) {}
- T value{};
- bool is_inherited{true};
-};
-
-// A bunch of helper function to create base::Value for specific C++ classes,
-// including vectors of types. These are used in template classes below
-// to simplify specialization logic.
-std::unique_ptr<base::Value> TypedValueToJson(bool value,
- chromeos::ErrorPtr* error);
-std::unique_ptr<base::Value> TypedValueToJson(int value,
- chromeos::ErrorPtr* error);
-std::unique_ptr<base::Value> TypedValueToJson(double value,
- chromeos::ErrorPtr* error);
-std::unique_ptr<base::Value> TypedValueToJson(const std::string& value,
- chromeos::ErrorPtr* error);
-std::unique_ptr<base::Value> TypedValueToJson(const native_types::Object& value,
- chromeos::ErrorPtr* error);
-std::unique_ptr<base::Value> TypedValueToJson(const native_types::Array& value,
- chromeos::ErrorPtr* error);
-template<typename T>
-std::unique_ptr<base::Value> TypedValueToJson(const std::vector<T>& values,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<base::ListValue> list(new base::ListValue);
- for (const auto& v : values) {
- auto json = TypedValueToJson(v, error);
- if (!json)
- return std::unique_ptr<base::Value>();
- list->Append(json.release());
- }
- return std::move(list);
-}
-
-// Similarly to TypedValueToJson() function above, the following overloaded
-// helper methods allow to extract specific C++ data types from base::Value.
-// Also used in template classes below to simplify specialization logic.
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- bool* value_out,
- chromeos::ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- int* value_out,
- chromeos::ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- double* value_out,
- chromeos::ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- std::string* value_out,
- chromeos::ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- native_types::Object* value_out,
- chromeos::ErrorPtr* error);
-bool TypedValueFromJson(const base::Value* value_in,
- const PropType* type,
- native_types::Array* value_out,
- chromeos::ErrorPtr* error);
-
-bool operator==(const native_types::Object& obj1,
- const native_types::Object& obj2);
-bool operator==(const native_types::Array& arr1,
- const native_types::Array& arr2);
-
-// CompareValue is a helper function to help with implementing EqualsTo operator
-// for various data types. For most scalar types it is using operator==(),
-// however, for floating point values, rounding errors in binary representation
-// of IEEE floats/doubles can cause straight == comparison to fail for seemingly
-// equivalent values. For these, use approximate comparison with the error
-// margin equal to the epsilon value defined for the corresponding data type.
-// This is used when looking up values for implementation of OneOf constraints
-// which should work reliably for floating points also ("number" type).
-
-// Compare exact types using ==.
-template<typename T>
-inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
-CompareValue(const T& v1, const T& v2) {
- return v1 == v2;
-}
-
-// Compare non-exact types (such as double) using precision margin (epsilon).
-template<typename T>
-inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type
-CompareValue(const T& v1, const T& v2) {
- return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon();
-}
-
-// Converts PropValue to Any in a format understood by D-Bus data serialization.
-// Has special handling for Object types where native_types::Object are
-// converted to chromeos::VariantDictionary.
-chromeos::Any PropValueToDBusVariant(const PropValue* value);
-// Converts native_types::Object to chromeos::VariantDictionary
-// with proper conversion of all nested properties.
-chromeos::VariantDictionary
-ObjectToDBusVariant(const native_types::Object& object);
-// Converts D-Bus variant to PropValue.
-// Has special handling for Object types where chromeos::VariantDictionary
-// is converted to native_types::Object.
-std::unique_ptr<const PropValue> PropValueFromDBusVariant(
- const PropType* type,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error);
-// Converts D-Bus variant to ObjectValue.
-bool ObjectFromDBusVariant(const ObjectSchema* object_schema,
- const chromeos::VariantDictionary& dict,
- native_types::Object* obj,
- chromeos::ErrorPtr* error);
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_SCHEMA_UTILS_H_
diff --git a/buffet/commands/schema_utils_unittest.cc b/buffet/commands/schema_utils_unittest.cc
deleted file mode 100644
index d872995..0000000
--- a/buffet/commands/schema_utils_unittest.cc
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/schema_utils.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/values.h>
-#include <chromeos/variant_dictionary.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/object_schema.h"
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_constants.h"
-#include "buffet/commands/unittest_utils.h"
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-using unittests::CreateValue;
-using chromeos::VariantDictionary;
-
-TEST(CommandSchemaUtils, TypedValueToJson_Scalar) {
- EXPECT_JSON_EQ("true", *TypedValueToJson(true, nullptr));
- EXPECT_JSON_EQ("false", *TypedValueToJson(false, nullptr));
-
- EXPECT_JSON_EQ("0", *TypedValueToJson(0, nullptr));
- EXPECT_JSON_EQ("-10", *TypedValueToJson(-10, nullptr));
- EXPECT_JSON_EQ("20", *TypedValueToJson(20, nullptr));
-
- EXPECT_JSON_EQ("0.0", *TypedValueToJson(0.0, nullptr));
- EXPECT_JSON_EQ("1.2", *TypedValueToJson(1.2, nullptr));
-
- EXPECT_JSON_EQ("'abc'", *TypedValueToJson(std::string("abc"), nullptr));
-
- std::vector<bool> bool_array{true, false};
- EXPECT_JSON_EQ("[true,false]", *TypedValueToJson(bool_array, nullptr));
-
- std::vector<int> int_array{1, 2, 5};
- EXPECT_JSON_EQ("[1,2,5]", *TypedValueToJson(int_array, nullptr));
-
- std::vector<double> dbl_array{1.1, 2.2};
- EXPECT_JSON_EQ("[1.1,2.2]", *TypedValueToJson(dbl_array, nullptr));
-
- std::vector<std::string> str_array{"a", "bc"};
- EXPECT_JSON_EQ("['a','bc']", *TypedValueToJson(str_array, nullptr));
-}
-
-TEST(CommandSchemaUtils, TypedValueToJson_Object) {
- IntPropType int_type;
- native_types::Object object;
-
- object.insert(std::make_pair("width", int_type.CreateValue(640, nullptr)));
- object.insert(std::make_pair("height", int_type.CreateValue(480, nullptr)));
- EXPECT_JSON_EQ("{'height':480,'width':640}",
- *TypedValueToJson(object, nullptr));
-}
-
-TEST(CommandSchemaUtils, TypedValueToJson_Array) {
- IntPropType int_type;
- native_types::Array arr;
-
- arr.push_back(int_type.CreateValue(640, nullptr));
- arr.push_back(int_type.CreateValue(480, nullptr));
- EXPECT_JSON_EQ("[640,480]", *TypedValueToJson(arr, nullptr));
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Bool) {
- bool value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("true").get(), nullptr, &value, nullptr));
- EXPECT_TRUE(value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("false").get(), nullptr, &value, nullptr));
- EXPECT_FALSE(value);
-
- chromeos::ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("0").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Int) {
- int value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("0").get(), nullptr, &value, nullptr));
- EXPECT_EQ(0, value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("23").get(), nullptr, &value, nullptr));
- EXPECT_EQ(23, value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("-1234").get(), nullptr, &value, nullptr));
- EXPECT_EQ(-1234, value);
-
- chromeos::ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Double) {
- double value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("0").get(), nullptr, &value, nullptr));
- EXPECT_DOUBLE_EQ(0.0, value);
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("0.0").get(), nullptr, &value, nullptr));
- EXPECT_DOUBLE_EQ(0.0, value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("23").get(), nullptr, &value, nullptr));
- EXPECT_EQ(23.0, value);
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("23.1").get(), nullptr, &value, nullptr));
- EXPECT_EQ(23.1, value);
-
- EXPECT_TRUE(TypedValueFromJson(CreateValue("-1.23E+02").get(), nullptr,
- &value, nullptr));
- EXPECT_EQ(-123.0, value);
-
- chromeos::ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_String) {
- std::string value;
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("''").get(), nullptr, &value, nullptr));
- EXPECT_EQ("", value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("'23'").get(), nullptr, &value, nullptr));
- EXPECT_EQ("23", value);
-
- EXPECT_TRUE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, nullptr));
- EXPECT_EQ("abc", value);
-
- chromeos::ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("12").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Object) {
- native_types::Object value;
- std::unique_ptr<ObjectSchema> schema{new ObjectSchema};
-
- IntPropType age_prop;
- age_prop.AddMinMaxConstraint(0, 150);
- schema->AddProp("age", age_prop.Clone());
-
- StringPropType name_prop;
- name_prop.AddLengthConstraint(1, 30);
- schema->AddProp("name", name_prop.Clone());
-
- ObjectPropType type;
- type.SetObjectSchema(std::move(schema));
- EXPECT_TRUE(TypedValueFromJson(CreateValue("{'age':20,'name':'Bob'}").get(),
- &type, &value, nullptr));
- native_types::Object value2;
- value2.insert(std::make_pair("age", age_prop.CreateValue(20, nullptr)));
- value2.insert(std::make_pair("name",
- name_prop.CreateValue(std::string("Bob"),
- nullptr)));
- EXPECT_EQ(value2, value);
-
- chromeos::ErrorPtr error;
- EXPECT_FALSE(
- TypedValueFromJson(CreateValue("'abc'").get(), nullptr, &value, &error));
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, TypedValueFromJson_Array) {
- native_types::Array arr;
- StringPropType str_type;
- str_type.AddLengthConstraint(3, 100);
- ArrayPropType type;
- type.SetItemType(str_type.Clone());
-
- EXPECT_TRUE(TypedValueFromJson(CreateValue("['foo', 'bar']").get(), &type,
- &arr, nullptr));
- native_types::Array arr2;
- arr2.push_back(str_type.CreateValue(std::string{"foo"}, nullptr));
- arr2.push_back(str_type.CreateValue(std::string{"bar"}, nullptr));
- EXPECT_EQ(arr2, arr);
-
- chromeos::ErrorPtr error;
- EXPECT_FALSE(TypedValueFromJson(CreateValue("['baz', 'ab']").get(), &type,
- &arr, &error));
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
- error.reset();
-}
-
-TEST(CommandSchemaUtils, PropValueToDBusVariant) {
- IntPropType int_type;
- auto prop_value = int_type.CreateValue(5, nullptr);
- EXPECT_EQ(5, PropValueToDBusVariant(prop_value.get()).Get<int>());
-
- BooleanPropType bool_type;
- prop_value = bool_type.CreateValue(true, nullptr);
- EXPECT_TRUE(PropValueToDBusVariant(prop_value.get()).Get<bool>());
-
- DoublePropType dbl_type;
- prop_value = dbl_type.CreateValue(5.5, nullptr);
- EXPECT_DOUBLE_EQ(5.5, PropValueToDBusVariant(prop_value.get()).Get<double>());
-
- StringPropType str_type;
- prop_value = str_type.CreateValue(std::string{"foo"}, nullptr);
- EXPECT_EQ("foo", PropValueToDBusVariant(prop_value.get()).Get<std::string>());
-
- ObjectPropType obj_type;
- ASSERT_TRUE(obj_type.FromJson(CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'},"
- "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
- nullptr, nullptr));
- native_types::Object obj{
- {"width", int_type.CreateValue(10, nullptr)},
- {"height", int_type.CreateValue(20, nullptr)},
- };
- prop_value = obj_type.CreateValue(obj, nullptr);
- VariantDictionary dict =
- PropValueToDBusVariant(prop_value.get()).Get<VariantDictionary>();
- EXPECT_EQ(20, dict["height"].Get<int>());
- EXPECT_EQ(10, dict["width"].Get<int>());
-
- ArrayPropType arr_type;
- arr_type.SetItemType(str_type.Clone());
- native_types::Array arr;
- arr.push_back(str_type.CreateValue(std::string{"foo"}, nullptr));
- arr.push_back(str_type.CreateValue(std::string{"bar"}, nullptr));
- arr.push_back(str_type.CreateValue(std::string{"baz"}, nullptr));
- prop_value = arr_type.CreateValue(arr, nullptr);
- chromeos::Any any = PropValueToDBusVariant(prop_value.get());
- ASSERT_TRUE(any.IsTypeCompatible<std::vector<std::string>>());
- EXPECT_EQ((std::vector<std::string>{"foo", "bar", "baz"}),
- any.Get<std::vector<std::string>>());
-}
-
-TEST(CommandSchemaUtils, PropValueFromDBusVariant_Int) {
- IntPropType int_type;
- ASSERT_TRUE(int_type.FromJson(CreateDictionaryValue("{'enum':[1,2]}").get(),
- nullptr, nullptr));
-
- auto prop_value = PropValueFromDBusVariant(&int_type, 1, nullptr);
- ASSERT_NE(nullptr, prop_value.get());
- EXPECT_EQ(1, prop_value->GetValueAsAny().Get<int>());
-
- chromeos::ErrorPtr error;
- prop_value = PropValueFromDBusVariant(&int_type, 5, &error);
- EXPECT_EQ(nullptr, prop_value.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
-}
-
-TEST(CommandSchemaUtils, PropValueFromDBusVariant_Bool) {
- BooleanPropType bool_type;
- ASSERT_TRUE(bool_type.FromJson(CreateDictionaryValue("{'enum':[true]}").get(),
- nullptr, nullptr));
-
- auto prop_value = PropValueFromDBusVariant(&bool_type, true, nullptr);
- ASSERT_NE(nullptr, prop_value.get());
- EXPECT_TRUE(prop_value->GetValueAsAny().Get<bool>());
-
- chromeos::ErrorPtr error;
- prop_value = PropValueFromDBusVariant(&bool_type, false, &error);
- EXPECT_EQ(nullptr, prop_value.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
-}
-
-TEST(CommandSchemaUtils, PropValueFromDBusVariant_Double) {
- DoublePropType dbl_type;
- ASSERT_TRUE(dbl_type.FromJson(CreateDictionaryValue("{'maximum':2.0}").get(),
- nullptr, nullptr));
-
- auto prop_value = PropValueFromDBusVariant(&dbl_type, 1.0, nullptr);
- ASSERT_NE(nullptr, prop_value.get());
- EXPECT_DOUBLE_EQ(1.0, prop_value->GetValueAsAny().Get<double>());
-
- chromeos::ErrorPtr error;
- prop_value = PropValueFromDBusVariant(&dbl_type, 10.0, &error);
- EXPECT_EQ(nullptr, prop_value.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
-}
-
-TEST(CommandSchemaUtils, PropValueFromDBusVariant_String) {
- StringPropType str_type;
- ASSERT_TRUE(str_type.FromJson(CreateDictionaryValue("{'minLength': 4}").get(),
- nullptr, nullptr));
-
- auto prop_value = PropValueFromDBusVariant(&str_type, std::string{"blah"},
- nullptr);
- ASSERT_NE(nullptr, prop_value.get());
- EXPECT_EQ("blah", prop_value->GetValueAsAny().Get<std::string>());
-
- chromeos::ErrorPtr error;
- prop_value = PropValueFromDBusVariant(&str_type, std::string{"foo"}, &error);
- EXPECT_EQ(nullptr, prop_value.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
-}
-
-TEST(CommandSchemaUtils, PropValueFromDBusVariant_Object) {
- ObjectPropType obj_type;
- ASSERT_TRUE(obj_type.FromJson(CreateDictionaryValue(
- "{'properties':{'width':'integer','height':'integer'},"
- "'enum':[{'width':10,'height':20},{'width':100,'height':200}]}").get(),
- nullptr, nullptr));
-
- VariantDictionary obj{
- {"width", 100},
- {"height", 200},
- };
- auto prop_value = PropValueFromDBusVariant(&obj_type, obj, nullptr);
- ASSERT_NE(nullptr, prop_value.get());
- auto value = prop_value->GetValueAsAny().Get<native_types::Object>();
- EXPECT_EQ(100, value["width"].get()->GetValueAsAny().Get<int>());
- EXPECT_EQ(200, value["height"].get()->GetValueAsAny().Get<int>());
-
- chromeos::ErrorPtr error;
- obj["height"] = 20;
- prop_value = PropValueFromDBusVariant(&obj_type, obj, &error);
- EXPECT_EQ(nullptr, prop_value.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
-}
-
-TEST(CommandSchemaUtils, PropValueFromDBusVariant_Array) {
- ArrayPropType arr_type;
- IntPropType int_type;
- int_type.AddMinMaxConstraint(0, 100);
- arr_type.SetItemType(int_type.Clone());
- std::vector<int> data{0, 1, 1, 100};
- auto prop_value = PropValueFromDBusVariant(&arr_type, data, nullptr);
- ASSERT_NE(nullptr, prop_value.get());
- auto arr = prop_value->GetValueAsAny().Get<native_types::Array>();
- ASSERT_EQ(4u, arr.size());
- EXPECT_EQ(0, arr[0]->GetInt()->GetValue());
- EXPECT_EQ(1, arr[1]->GetInt()->GetValue());
- EXPECT_EQ(1, arr[2]->GetInt()->GetValue());
- EXPECT_EQ(100, arr[3]->GetInt()->GetValue());
-
- chromeos::ErrorPtr error;
- data.push_back(-1); // This value is out of bounds for |int_type|.
- prop_value = PropValueFromDBusVariant(&arr_type, data, &error);
- EXPECT_EQ(nullptr, prop_value.get());
- ASSERT_NE(nullptr, error.get());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
-}
-
-} // namespace buffet
diff --git a/buffet/commands/unittest_utils.cc b/buffet/commands/unittest_utils.cc
deleted file mode 100644
index df07289..0000000
--- a/buffet/commands/unittest_utils.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/unittest_utils.h"
-
-#include <base/json/json_reader.h>
-#include <base/json/json_writer.h>
-
-namespace buffet {
-namespace unittests {
-
-std::unique_ptr<base::Value> CreateValue(const char* json) {
- std::string json2(json);
- // Convert apostrophes to double-quotes so JSONReader can parse the string.
- std::replace(json2.begin(), json2.end(), '\'', '"');
- int error = 0;
- std::string message;
- std::unique_ptr<base::Value> value{
- base::JSONReader::ReadAndReturnError(json2, base::JSON_PARSE_RFC, &error,
- &message)
- .release()};
- CHECK(value) << "Failed to load JSON: " << message << ", " << json;
- return value;
-}
-
-std::unique_ptr<base::DictionaryValue> CreateDictionaryValue(const char* json) {
- std::unique_ptr<base::Value> value = CreateValue(json);
- base::DictionaryValue* dict = nullptr;
- value->GetAsDictionary(&dict);
- CHECK(dict) << "Value is not dictionary: " << json;
- value.release();
- return std::unique_ptr<base::DictionaryValue>(dict);
-}
-
-} // namespace unittests
-} // namespace buffet
diff --git a/buffet/commands/unittest_utils.h b/buffet/commands/unittest_utils.h
deleted file mode 100644
index 3a9dcc1..0000000
--- a/buffet/commands/unittest_utils.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_UNITTEST_UTILS_H_
-#define BUFFET_COMMANDS_UNITTEST_UTILS_H_
-
-#include <memory>
-#include <string>
-
-#include <base/values.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/prop_values.h"
-
-namespace buffet {
-namespace unittests {
-
-// Helper method to create base::Value from a string as a smart pointer.
-// For ease of definition in C++ code, double-quotes in the source definition
-// are replaced with apostrophes.
-std::unique_ptr<base::Value> CreateValue(const char* json);
-
-// Helper method to create a JSON dictionary object from a string.
-std::unique_ptr<base::DictionaryValue> CreateDictionaryValue(const char* json);
-
-inline bool IsEqualValue(const base::Value& val1, const base::Value& val2) {
- return val1.Equals(&val2);
-}
-
-template <typename PropVal, typename T>
-std::unique_ptr<const PropVal> make_prop_value(const T& value) {
- std::unique_ptr<PropVal> result{
- new PropVal{PropType::Create(GetValueType<T>())}};
- result->SetValue(value);
- return std::move(result);
-}
-
-inline std::unique_ptr<const IntValue> make_int_prop_value(int value) {
- return make_prop_value<IntValue, int>(value);
-}
-
-inline std::unique_ptr<const DoubleValue> make_double_prop_value(double value) {
- return make_prop_value<DoubleValue, double>(value);
-}
-
-inline std::unique_ptr<const BooleanValue> make_bool_prop_value(bool value) {
- return make_prop_value<BooleanValue, bool>(value);
-}
-
-inline std::unique_ptr<const StringValue>
-make_string_prop_value(const std::string& value) {
- return make_prop_value<StringValue, std::string>(value);
-}
-
-} // namespace unittests
-} // namespace buffet
-
-#define EXPECT_JSON_EQ(expected, actual) \
- EXPECT_PRED2(buffet::unittests::IsEqualValue, \
- *buffet::unittests::CreateValue(expected), actual)
-
-#endif // BUFFET_COMMANDS_UNITTEST_UTILS_H_
diff --git a/buffet/commands/user_role.cc b/buffet/commands/user_role.cc
deleted file mode 100644
index a9237ee..0000000
--- a/buffet/commands/user_role.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/commands/user_role.h"
-
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/enum_to_string.h"
-#include "buffet/commands/schema_constants.h"
-
-namespace buffet {
-
-template <>
-const EnumToString<UserRole>::Map EnumToString<UserRole>::kMap[] = {
- {UserRole::kViewer, commands::attributes::kCommand_Role_Viewer},
- {UserRole::kUser, commands::attributes::kCommand_Role_User},
- {UserRole::kOwner, commands::attributes::kCommand_Role_Owner},
- {UserRole::kManager, commands::attributes::kCommand_Role_Manager},
-};
-
-std::string ToString(UserRole role) {
- return EnumToString<UserRole>::FindNameById(role);
-}
-
-bool FromString(const std::string& str,
- UserRole* role,
- chromeos::ErrorPtr* error) {
- if (EnumToString<UserRole>::FindIdByName(str, role))
- return true;
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid role: '%s'", str.c_str());
- return false;
-}
-
-} // namespace buffet
diff --git a/buffet/commands/user_role.h b/buffet/commands/user_role.h
deleted file mode 100644
index 711abdf..0000000
--- a/buffet/commands/user_role.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_COMMANDS_USER_ROLE_H_
-#define BUFFET_COMMANDS_USER_ROLE_H_
-
-#include <string>
-#include <chromeos/errors/error.h>
-
-namespace buffet {
-
-enum class UserRole {
- kViewer,
- kUser,
- kManager,
- kOwner,
-};
-
-std::string ToString(UserRole role);
-
-bool FromString(const std::string& str,
- UserRole* role,
- chromeos::ErrorPtr* error);
-
-} // namespace buffet
-
-#endif // BUFFET_COMMANDS_USER_ROLE_H_
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
deleted file mode 100644
index 66ee054..0000000
--- a/buffet/device_registration_info.cc
+++ /dev/null
@@ -1,1131 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/device_registration_info.h"
-
-#include <algorithm>
-#include <memory>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/json/json_writer.h>
-#include <base/values.h>
-#include <chromeos/bind_lambda.h>
-#include <chromeos/data_encoding.h>
-#include <chromeos/errors/error_codes.h>
-#include <chromeos/http/http_utils.h>
-#include <chromeos/key_value_store.h>
-#include <chromeos/mime_utils.h>
-#include <chromeos/strings/string_utils.h>
-#include <chromeos/url_utils.h>
-
-#include "buffet/commands/cloud_command_proxy.h"
-#include "buffet/commands/command_definition.h"
-#include "buffet/commands/command_manager.h"
-#include "buffet/commands/schema_constants.h"
-#include "buffet/notification/xmpp_channel.h"
-#include "buffet/states/state_manager.h"
-#include "buffet/utils.h"
-
-const char buffet::kErrorDomainOAuth2[] = "oauth2";
-const char buffet::kErrorDomainGCD[] = "gcd";
-const char buffet::kErrorDomainGCDServer[] = "gcd_server";
-
-namespace {
-
-const int kMaxStartDeviceRetryDelayMinutes{1};
-const int64_t kMinStartDeviceRetryDelaySeconds{5};
-const int64_t kAbortCommandRetryDelaySeconds{5};
-
-std::pair<std::string, std::string> BuildAuthHeader(
- const std::string& access_token_type,
- const std::string& access_token) {
- std::string authorization =
- chromeos::string_utils::Join(" ", access_token_type, access_token);
- return {chromeos::http::request_header::kAuthorization, authorization};
-}
-
-inline void SetUnexpectedError(chromeos::ErrorPtr* error) {
- chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainGCD,
- "unexpected_response", "Unexpected GCD error");
-}
-
-void ParseGCDError(const base::DictionaryValue* json,
- chromeos::ErrorPtr* error) {
- const base::Value* list_value = nullptr;
- const base::ListValue* error_list = nullptr;
- if (!json->Get("error.errors", &list_value) ||
- !list_value->GetAsList(&error_list)) {
- SetUnexpectedError(error);
- return;
- }
-
- for (size_t i = 0; i < error_list->GetSize(); i++) {
- const base::Value* error_value = nullptr;
- const base::DictionaryValue* error_object = nullptr;
- if (!error_list->Get(i, &error_value) ||
- !error_value->GetAsDictionary(&error_object)) {
- SetUnexpectedError(error);
- continue;
- }
- std::string error_code, error_message;
- if (error_object->GetString("reason", &error_code) &&
- error_object->GetString("message", &error_message)) {
- chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainGCDServer,
- error_code, error_message);
- } else {
- SetUnexpectedError(error);
- }
- }
-}
-
-std::string BuildURL(const std::string& url,
- const std::vector<std::string>& subpaths,
- const chromeos::data_encoding::WebParamList& params) {
- std::string result = chromeos::url::CombineMultiple(url, subpaths);
- return chromeos::url::AppendQueryParams(result, params);
-}
-
-void IgnoreCloudError(const chromeos::Error*) {
-}
-
-void IgnoreCloudErrorWithCallback(const base::Closure& cb,
- const chromeos::Error*) {
- cb.Run();
-}
-
-void IgnoreCloudResult(const base::DictionaryValue&) {
-}
-
-void IgnoreCloudResultWithCallback(const base::Closure& cb,
- const base::DictionaryValue&) {
- cb.Run();
-}
-
-} // anonymous namespace
-
-namespace buffet {
-
-DeviceRegistrationInfo::DeviceRegistrationInfo(
- const std::shared_ptr<CommandManager>& command_manager,
- const std::shared_ptr<StateManager>& state_manager,
- std::unique_ptr<BuffetConfig> config,
- const std::shared_ptr<chromeos::http::Transport>& transport,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- bool notifications_enabled,
- privetd::ShillClient* shill_client)
- : transport_{transport},
- task_runner_{task_runner},
- command_manager_{command_manager},
- state_manager_{state_manager},
- config_{std::move(config)},
- notifications_enabled_{notifications_enabled},
- shill_client_{shill_client} {
- cloud_backoff_policy_.reset(new chromeos::BackoffEntry::Policy{});
- cloud_backoff_policy_->num_errors_to_ignore = 0;
- cloud_backoff_policy_->initial_delay_ms = 1000;
- cloud_backoff_policy_->multiply_factor = 2.0;
- cloud_backoff_policy_->jitter_factor = 0.1;
- cloud_backoff_policy_->maximum_backoff_ms = 30000;
- cloud_backoff_policy_->entry_lifetime_ms = -1;
- cloud_backoff_policy_->always_use_initial_delay = false;
- cloud_backoff_entry_.reset(
- new chromeos::BackoffEntry{cloud_backoff_policy_.get()});
-
- command_manager_->AddOnCommandDefChanged(
- base::Bind(&DeviceRegistrationInfo::OnCommandDefsChanged,
- weak_factory_.GetWeakPtr()));
- state_manager_->AddOnChangedCallback(
- base::Bind(&DeviceRegistrationInfo::OnStateChanged,
- weak_factory_.GetWeakPtr()));
-}
-
-DeviceRegistrationInfo::~DeviceRegistrationInfo() = default;
-
-std::pair<std::string, std::string>
- DeviceRegistrationInfo::GetAuthorizationHeader() const {
- return BuildAuthHeader("Bearer", access_token_);
-}
-
-std::string DeviceRegistrationInfo::GetServiceURL(
- const std::string& subpath,
- const chromeos::data_encoding::WebParamList& params) const {
- return BuildURL(config_->service_url(), {subpath}, params);
-}
-
-std::string DeviceRegistrationInfo::GetDeviceURL(
- const std::string& subpath,
- const chromeos::data_encoding::WebParamList& params) const {
- CHECK(!config_->device_id().empty()) << "Must have a valid device ID";
- return BuildURL(config_->service_url(),
- {"devices", config_->device_id(), subpath}, params);
-}
-
-std::string DeviceRegistrationInfo::GetOAuthURL(
- const std::string& subpath,
- const chromeos::data_encoding::WebParamList& params) const {
- return BuildURL(config_->oauth_url(), {subpath}, params);
-}
-
-void DeviceRegistrationInfo::Start() {
- if (HaveRegistrationCredentials()) {
- StartNotificationChannel();
- // Wait a significant amount of time for local daemons to publish their
- // state to Buffet before publishing it to the cloud.
- // TODO(wiley) We could do a lot of things here to either expose this
- // timeout as a configurable knob or allow local
- // daemons to signal that their state is up to date so that
- // we need not wait for them.
- ScheduleStartDevice(base::TimeDelta::FromSeconds(5));
- }
-}
-
-void DeviceRegistrationInfo::ScheduleStartDevice(const base::TimeDelta& later) {
- SetRegistrationStatus(RegistrationStatus::kConnecting);
- if (!task_runner_)
- return; // Assume we're in unittests
- base::TimeDelta max_delay =
- base::TimeDelta::FromMinutes(kMaxStartDeviceRetryDelayMinutes);
- base::TimeDelta min_delay =
- base::TimeDelta::FromSeconds(kMinStartDeviceRetryDelaySeconds);
- base::TimeDelta retry_delay = later * 2;
- if (retry_delay > max_delay) { retry_delay = max_delay; }
- if (retry_delay < min_delay) { retry_delay = min_delay; }
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DeviceRegistrationInfo::StartDevice,
- weak_factory_.GetWeakPtr(), nullptr,
- retry_delay),
- later);
-}
-
-bool DeviceRegistrationInfo::HaveRegistrationCredentials() const {
- return !config_->refresh_token().empty() &&
- !config_->device_id().empty() &&
- !config_->robot_account().empty();
-}
-
-bool DeviceRegistrationInfo::VerifyRegistrationCredentials(
- chromeos::ErrorPtr* error) const {
- const bool have_credentials = HaveRegistrationCredentials();
-
- VLOG(1) << "Device registration record "
- << ((have_credentials) ? "found" : "not found.");
- if (!have_credentials)
- chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainGCD,
- "device_not_registered",
- "No valid device registration record found");
- return have_credentials;
-}
-
-std::unique_ptr<base::DictionaryValue>
-DeviceRegistrationInfo::ParseOAuthResponse(chromeos::http::Response* response,
- chromeos::ErrorPtr* error) {
- int code = 0;
- auto resp = chromeos::http::ParseJsonResponse(response, &code, error);
- if (resp && code >= chromeos::http::status_code::BadRequest) {
- std::string error_code, error_message;
- if (!resp->GetString("error", &error_code)) {
- error_code = "unexpected_response";
- }
- if (error_code == "invalid_grant") {
- LOG(INFO) << "The device's registration has been revoked.";
- SetRegistrationStatus(RegistrationStatus::kInvalidCredentials);
- }
- // I have never actually seen an error_description returned.
- if (!resp->GetString("error_description", &error_message)) {
- error_message = "Unexpected OAuth error";
- }
- chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainOAuth2,
- error_code, error_message);
- return std::unique_ptr<base::DictionaryValue>();
- }
- return resp;
-}
-
-void DeviceRegistrationInfo::RefreshAccessToken(
- const base::Closure& success_callback,
- const CloudRequestErrorCallback& error_callback) {
- LOG(INFO) << "Refreshing access token.";
-
- chromeos::ErrorPtr error;
- if (!VerifyRegistrationCredentials(&error)) {
- error_callback.Run(error.get());
- return;
- }
-
- // Make a shared pointer to |error_callback| since we are going to share this
- // callback with both success and error callbacks for PostFormData() and if
- // |error_callback| has any move-only types, one of the copies will be bad.
- auto shared_error_callback =
- std::make_shared<CloudRequestErrorCallback>(error_callback);
-
- auto on_refresh_error = [shared_error_callback](
- chromeos::http::RequestID id,
- const chromeos::Error* error) {
- shared_error_callback->Run(error);
- };
-
- chromeos::http::FormFieldList form_data{
- {"refresh_token", config_->refresh_token()},
- {"client_id", config_->client_id()},
- {"client_secret", config_->client_secret()},
- {"grant_type", "refresh_token"},
- };
-
- chromeos::http::PostFormData(
- GetOAuthURL("token"), form_data, {}, transport_,
- base::Bind(&DeviceRegistrationInfo::OnRefreshAccessTokenSuccess,
- weak_factory_.GetWeakPtr(),
- success_callback, shared_error_callback),
- base::Bind(on_refresh_error));
-}
-
-void DeviceRegistrationInfo::OnRefreshAccessTokenSuccess(
- const base::Closure& success_callback,
- const std::shared_ptr<CloudRequestErrorCallback>& error_callback,
- chromeos::http::RequestID id,
- std::unique_ptr<chromeos::http::Response> response) {
- chromeos::ErrorPtr error;
- auto json = ParseOAuthResponse(response.get(), &error);
- if (!json) {
- error_callback->Run(error.get());
- return;
- }
-
- int expires_in = 0;
- if (!json->GetString("access_token", &access_token_) ||
- !json->GetInteger("expires_in", &expires_in) ||
- access_token_.empty() ||
- expires_in <= 0) {
- LOG(ERROR) << "Access token unavailable.";
- chromeos::Error::AddTo(&error, FROM_HERE, kErrorDomainOAuth2,
- "unexpected_server_response",
- "Access token unavailable");
- error_callback->Run(error.get());
- return;
- }
- access_token_expiration_ = base::Time::Now() +
- base::TimeDelta::FromSeconds(expires_in);
- LOG(INFO) << "Access token is refreshed for additional " << expires_in
- << " seconds.";
-
- if (primary_notification_channel_ &&
- !primary_notification_channel_->IsConnected()) {
- // If we have disconnected channel, it is due to failed credentials.
- // Now that we have a new access token, retry the connection.
- StartNotificationChannel();
- }
- success_callback.Run();
-}
-
-void DeviceRegistrationInfo::StartNotificationChannel() {
- if (notification_channel_starting_)
- return;
-
- LOG(INFO) << "Starting notification channel";
-
- // If no TaskRunner assume we're in unittests.
- if (!task_runner_) {
- LOG(INFO) << "No TaskRunner, not starting notification channel";
- return;
- }
-
- if (primary_notification_channel_) {
- primary_notification_channel_->Stop();
- primary_notification_channel_.reset();
- current_notification_channel_ = nullptr;
- }
-
- // Start with just regular polling at the pre-configured polling interval.
- // Once the primary notification channel is connected successfully, it will
- // call back to OnConnected() and at that time we'll switch to use the
- // primary channel and switch periodic poll into much more infrequent backup
- // poll mode.
- const base::TimeDelta pull_interval = config_->polling_period();
- if (!pull_channel_) {
- pull_channel_.reset(new PullChannel{pull_interval, task_runner_});
- pull_channel_->Start(this);
- } else {
- pull_channel_->UpdatePullInterval(pull_interval);
- }
- current_notification_channel_ = pull_channel_.get();
-
- if (!notifications_enabled_) {
- LOG(WARNING) << "Notification channel disabled by flag.";
- return;
- }
-
- notification_channel_starting_ = true;
- primary_notification_channel_.reset(new XmppChannel{
- config_->robot_account(), access_token_, task_runner_, shill_client_});
- primary_notification_channel_->Start(this);
-}
-
-void DeviceRegistrationInfo::AddOnRegistrationChangedCallback(
- const OnRegistrationChangedCallback& callback) {
- on_registration_changed_.push_back(callback);
- callback.Run(registration_status_);
-}
-
-void DeviceRegistrationInfo::AddOnConfigChangedCallback(
- const BuffetConfig::OnChangedCallback& callback) {
- config_->AddOnChangedCallback(callback);
-}
-
-std::unique_ptr<base::DictionaryValue>
-DeviceRegistrationInfo::BuildDeviceResource(chromeos::ErrorPtr* error) {
- // Limit only to commands that are visible to the cloud.
- auto commands = command_manager_->GetCommandDictionary().GetCommandsAsJson(
- [](const CommandDefinition* def) { return def->GetVisibility().cloud; },
- true, error);
- if (!commands)
- return nullptr;
-
- std::unique_ptr<base::DictionaryValue> state =
- state_manager_->GetStateValuesAsJson(error);
- if (!state)
- return nullptr;
-
- std::unique_ptr<base::DictionaryValue> resource{new base::DictionaryValue};
- if (!config_->device_id().empty())
- resource->SetString("id", config_->device_id());
- resource->SetString("name", config_->name());
- if (!config_->description().empty())
- resource->SetString("description", config_->description());
- if (!config_->location().empty())
- resource->SetString("location", config_->location());
- resource->SetString("modelManifestId", config_->model_id());
- resource->SetString("deviceKind", config_->device_kind());
- std::unique_ptr<base::DictionaryValue> channel{new base::DictionaryValue};
- if (current_notification_channel_) {
- channel->SetString("supportedType",
- current_notification_channel_->GetName());
- current_notification_channel_->AddChannelParameters(channel.get());
- } else {
- channel->SetString("supportedType", "pull");
- }
- resource->Set("channel", channel.release());
- resource->Set("commandDefs", commands.release());
- resource->Set("state", state.release());
-
- return resource;
-}
-
-void DeviceRegistrationInfo::GetDeviceInfo(
- const CloudRequestCallback& success_callback,
- const CloudRequestErrorCallback& error_callback) {
- DoCloudRequest(chromeos::http::request_type::kGet, GetDeviceURL(), nullptr,
- success_callback, error_callback);
-}
-
-std::string DeviceRegistrationInfo::RegisterDevice(const std::string& ticket_id,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<base::DictionaryValue> device_draft =
- BuildDeviceResource(error);
- if (!device_draft)
- return std::string();
-
- base::DictionaryValue req_json;
- req_json.SetString("id", ticket_id);
- req_json.SetString("oauthClientId", config_->client_id());
- req_json.Set("deviceDraft", device_draft.release());
-
- auto url = GetServiceURL("registrationTickets/" + ticket_id,
- {{"key", config_->api_key()}});
- std::unique_ptr<chromeos::http::Response> response =
- chromeos::http::PatchJsonAndBlock(url, &req_json, {}, transport_, error);
- auto json_resp = chromeos::http::ParseJsonResponse(response.get(), nullptr,
- error);
- if (!json_resp)
- return std::string();
- if (!response->IsSuccessful()) {
- ParseGCDError(json_resp.get(), error);
- return std::string();
- }
-
- url = GetServiceURL("registrationTickets/" + ticket_id +
- "/finalize?key=" + config_->api_key());
- response = chromeos::http::SendRequestWithNoDataAndBlock(
- chromeos::http::request_type::kPost, url, {}, transport_, error);
- if (!response)
- return std::string();
- json_resp = chromeos::http::ParseJsonResponse(response.get(), nullptr, error);
- if (!json_resp)
- return std::string();
- if (!response->IsSuccessful()) {
- ParseGCDError(json_resp.get(), error);
- return std::string();
- }
-
- std::string auth_code;
- std::string device_id;
- std::string robot_account;
- if (!json_resp->GetString("robotAccountEmail", &robot_account) ||
- !json_resp->GetString("robotAccountAuthorizationCode", &auth_code) ||
- !json_resp->GetString("deviceDraft.id", &device_id)) {
- chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainGCD,
- "unexpected_response",
- "Device account missing in response");
- return std::string();
- }
-
- // Now get access_token and refresh_token
- response = chromeos::http::PostFormDataAndBlock(GetOAuthURL("token"), {
- {"code", auth_code},
- {"client_id", config_->client_id()},
- {"client_secret", config_->client_secret()},
- {"redirect_uri", "oob"},
- {"scope", "https://www.googleapis.com/auth/clouddevices"},
- {"grant_type", "authorization_code"}
- }, {}, transport_, error);
- if (!response)
- return std::string();
-
- json_resp = ParseOAuthResponse(response.get(), error);
- int expires_in = 0;
- std::string refresh_token;
- if (!json_resp || !json_resp->GetString("access_token", &access_token_) ||
- !json_resp->GetString("refresh_token", &refresh_token) ||
- !json_resp->GetInteger("expires_in", &expires_in) ||
- access_token_.empty() || refresh_token.empty() || expires_in <= 0) {
- chromeos::Error::AddTo(error, FROM_HERE,
- kErrorDomainGCD, "unexpected_response",
- "Device access_token missing in response");
- return std::string();
- }
-
- access_token_expiration_ = base::Time::Now() +
- base::TimeDelta::FromSeconds(expires_in);
-
- BuffetConfig::Transaction change{config_.get()};
- change.set_device_id(device_id);
- change.set_robot_account(robot_account);
- change.set_refresh_token(refresh_token);
- change.Commit();
-
- StartNotificationChannel();
-
- // We're going to respond with our success immediately and we'll StartDevice
- // shortly after.
- ScheduleStartDevice(base::TimeDelta::FromSeconds(0));
- return device_id;
-}
-
-void DeviceRegistrationInfo::DoCloudRequest(
- const std::string& method,
- const std::string& url,
- const base::DictionaryValue* body,
- const CloudRequestCallback& success_callback,
- const CloudRequestErrorCallback& error_callback) {
- // We make CloudRequestData shared here because we want to make sure
- // there is only one instance of success_callback and error_calback since
- // those may have move-only types and making a copy of the callback with
- // move-only types curried-in will invalidate the source callback.
- auto data = std::make_shared<CloudRequestData>();
- data->method = method;
- data->url = url;
- if (body)
- base::JSONWriter::Write(*body, &data->body);
- data->success_callback = success_callback;
- data->error_callback = error_callback;
- SendCloudRequest(data);
-}
-
-void DeviceRegistrationInfo::SendCloudRequest(
- const std::shared_ptr<const CloudRequestData>& data) {
- // TODO(antonm): Add reauthorization on access token expiration (do not
- // forget about 5xx when fetching new access token).
- // TODO(antonm): Add support for device removal.
-
- VLOG(1) << "Sending cloud request '" << data->method << "' to '" << data->url
- << "' with request body '" << data->body << "'";
- chromeos::ErrorPtr error;
- if (!VerifyRegistrationCredentials(&error)) {
- data->error_callback.Run(error.get());
- return;
- }
-
- if (cloud_backoff_entry_->ShouldRejectRequest()) {
- VLOG(1) << "Cloud request delayed for "
- << cloud_backoff_entry_->GetTimeUntilRelease()
- << " due to backoff policy";
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DeviceRegistrationInfo::SendCloudRequest, AsWeakPtr(),
- data),
- cloud_backoff_entry_->GetTimeUntilRelease());
- return;
- }
-
- using chromeos::mime::application::kJson;
- using chromeos::mime::parameters::kCharset;
- const std::string mime_type =
- chromeos::mime::AppendParameter(kJson, kCharset, "utf-8");
-
- chromeos::http::RequestID request_id = chromeos::http::SendRequest(
- data->method, data->url, data->body.c_str(), data->body.size(), mime_type,
- {GetAuthorizationHeader()}, transport_,
- base::Bind(&DeviceRegistrationInfo::OnCloudRequestSuccess, AsWeakPtr(),
- data),
- base::Bind(&DeviceRegistrationInfo::OnCloudRequestError, AsWeakPtr(),
- data));
- VLOG(1) << "Cloud request with ID " << request_id << " successfully sent";
-}
-
-void DeviceRegistrationInfo::OnCloudRequestSuccess(
- const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
- std::unique_ptr<chromeos::http::Response> response) {
- int status_code = response->GetStatusCode();
- VLOG(1) << "Response for cloud request with ID " << request_id
- << " received with status code " << status_code;
- if (status_code == chromeos::http::status_code::Denied) {
- RefreshAccessToken(
- base::Bind(&DeviceRegistrationInfo::OnAccessTokenRefreshed, AsWeakPtr(),
- data),
- base::Bind(&DeviceRegistrationInfo::OnAccessTokenError, AsWeakPtr(),
- data));
- return;
- }
-
- if (status_code >= chromeos::http::status_code::InternalServerError) {
- // Request was valid, but server failed, retry.
- // TODO(antonm): Reconsider status codes, maybe only some require
- // retry.
- // TODO(antonm): Support Retry-After header.
- RetryCloudRequest(data);
- return;
- }
-
- chromeos::ErrorPtr error;
- auto json_resp = chromeos::http::ParseJsonResponse(response.get(), nullptr,
- &error);
- if (!json_resp) {
- data->error_callback.Run(error.get());
- return;
- }
-
- if (!response->IsSuccessful()) {
- ParseGCDError(json_resp.get(), &error);
- if (status_code == chromeos::http::status_code::Forbidden &&
- error->HasError(buffet::kErrorDomainGCDServer, "rateLimitExceeded")) {
- // If we exceeded server quota, retry the request later.
- RetryCloudRequest(data);
- return;
- }
- data->error_callback.Run(error.get());
- return;
- }
-
- cloud_backoff_entry_->InformOfRequest(true);
- SetRegistrationStatus(RegistrationStatus::kConnected);
- data->success_callback.Run(*json_resp);
-}
-
-void DeviceRegistrationInfo::OnCloudRequestError(
- const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
- const chromeos::Error* error) {
- VLOG(1) << "Cloud request with ID " << request_id << " failed";
- RetryCloudRequest(data);
-}
-
-void DeviceRegistrationInfo::RetryCloudRequest(
- const std::shared_ptr<const CloudRequestData>& data) {
- // TODO(avakulenko): Tie connecting/connected status to XMPP channel instead.
- SetRegistrationStatus(RegistrationStatus::kConnecting);
- cloud_backoff_entry_->InformOfRequest(false);
- SendCloudRequest(data);
-}
-
-void DeviceRegistrationInfo::OnAccessTokenRefreshed(
- const std::shared_ptr<const CloudRequestData>& data) {
- SendCloudRequest(data);
-}
-
-void DeviceRegistrationInfo::OnAccessTokenError(
- const std::shared_ptr<const CloudRequestData>& data,
- const chromeos::Error* error) {
- if (error->HasError(buffet::kErrorDomainOAuth2, "invalid_grant"))
- MarkDeviceUnregistered();
- data->error_callback.Run(error);
-}
-
-void DeviceRegistrationInfo::StartDevice(
- chromeos::ErrorPtr* error,
- const base::TimeDelta& retry_delay) {
- if (!VerifyRegistrationCredentials(error))
- return;
- auto handle_start_device_failure_cb = base::Bind(
- &IgnoreCloudErrorWithCallback,
- base::Bind(&DeviceRegistrationInfo::ScheduleStartDevice,
- weak_factory_.GetWeakPtr(),
- retry_delay));
- // "Starting" a device just means that we:
- // 1) push an updated device resource
- // 2) fetch an initial set of outstanding commands
- // 3) abort any commands that we've previously marked as "in progress"
- // or as being in an error state; publish queued commands
- auto abort_commands_cb = base::Bind(
- &DeviceRegistrationInfo::ProcessInitialCommandList,
- weak_factory_.GetWeakPtr());
- auto fetch_commands_cb = base::Bind(
- &DeviceRegistrationInfo::FetchCommands,
- weak_factory_.GetWeakPtr(),
- abort_commands_cb,
- handle_start_device_failure_cb);
- UpdateDeviceResource(fetch_commands_cb, handle_start_device_failure_cb);
-}
-
-bool DeviceRegistrationInfo::UpdateDeviceInfo(const std::string& name,
- const std::string& description,
- const std::string& location,
- chromeos::ErrorPtr* error) {
- BuffetConfig::Transaction change{config_.get()};
- change.set_name(name);
- change.set_description(description);
- change.set_location(location);
- change.Commit();
-
- if (HaveRegistrationCredentials()) {
- UpdateDeviceResource(base::Bind(&base::DoNothing),
- base::Bind(&IgnoreCloudError));
- }
-
- return true;
-}
-
-bool DeviceRegistrationInfo::UpdateBaseConfig(
- const std::string& anonymous_access_role,
- bool local_discovery_enabled,
- bool local_pairing_enabled,
- chromeos::ErrorPtr* error) {
- BuffetConfig::Transaction change(config_.get());
- if (!change.set_local_anonymous_access_role(anonymous_access_role)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomainBuffet,
- "invalid_parameter", "Invalid role: %s",
- anonymous_access_role.c_str());
- return false;
- }
-
- change.set_local_discovery_enabled(local_discovery_enabled);
- change.set_local_pairing_enabled(local_pairing_enabled);
-
- return true;
-}
-
-bool DeviceRegistrationInfo::UpdateServiceConfig(
- const std::string& client_id,
- const std::string& client_secret,
- const std::string& api_key,
- const std::string& oauth_url,
- const std::string& service_url,
- chromeos::ErrorPtr* error) {
- if (HaveRegistrationCredentials()) {
- chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainBuffet,
- "already_registered",
- "Unable to change config for registered device");
- return false;
- }
- BuffetConfig::Transaction change{config_.get()};
- change.set_client_id(client_id);
- change.set_client_secret(client_secret);
- change.set_api_key(api_key);
- change.set_oauth_url(oauth_url);
- change.set_service_url(service_url);
- return true;
-}
-
-void DeviceRegistrationInfo::UpdateCommand(
- const std::string& command_id,
- const base::DictionaryValue& command_patch,
- const base::Closure& on_success,
- const base::Closure& on_error) {
- DoCloudRequest(
- chromeos::http::request_type::kPatch,
- GetServiceURL("commands/" + command_id),
- &command_patch,
- base::Bind(&IgnoreCloudResultWithCallback, on_success),
- base::Bind(&IgnoreCloudErrorWithCallback, on_error));
-}
-
-void DeviceRegistrationInfo::NotifyCommandAborted(
- const std::string& command_id,
- chromeos::ErrorPtr error) {
- base::DictionaryValue command_patch;
- command_patch.SetString(commands::attributes::kCommand_State,
- CommandInstance::kStatusAborted);
- if (error) {
- command_patch.SetString(commands::attributes::kCommand_ErrorCode,
- chromeos::string_utils::Join(":",
- error->GetDomain(),
- error->GetCode()));
- std::vector<std::string> messages;
- const chromeos::Error* current_error = error.get();
- while (current_error) {
- messages.push_back(current_error->GetMessage());
- current_error = current_error->GetInnerError();
- }
- command_patch.SetString(commands::attributes::kCommand_ErrorMessage,
- chromeos::string_utils::Join(";", messages));
- }
- UpdateCommand(command_id,
- command_patch,
- base::Bind(&base::DoNothing),
- base::Bind(&DeviceRegistrationInfo::RetryNotifyCommandAborted,
- weak_factory_.GetWeakPtr(),
- command_id, base::Passed(std::move(error))));
-}
-
-void DeviceRegistrationInfo::RetryNotifyCommandAborted(
- const std::string& command_id,
- chromeos::ErrorPtr error) {
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DeviceRegistrationInfo::NotifyCommandAborted,
- weak_factory_.GetWeakPtr(),
- command_id, base::Passed(std::move(error))),
- base::TimeDelta::FromSeconds(kAbortCommandRetryDelaySeconds));
-}
-
-void DeviceRegistrationInfo::UpdateDeviceResource(
- const base::Closure& on_success,
- const CloudRequestErrorCallback& on_failure) {
- queued_resource_update_callbacks_.emplace_back(on_success, on_failure);
- if (!in_progress_resource_update_callbacks_.empty()) {
- VLOG(1) << "Another request is already pending.";
- return;
- }
-
- StartQueuedUpdateDeviceResource();
-}
-
-void DeviceRegistrationInfo::StartQueuedUpdateDeviceResource() {
- CHECK(in_progress_resource_update_callbacks_.empty());
- if (queued_resource_update_callbacks_.empty())
- return;
-
- std::swap(queued_resource_update_callbacks_,
- in_progress_resource_update_callbacks_);
-
- VLOG(1) << "Updating GCD server with CDD...";
- chromeos::ErrorPtr error;
- std::unique_ptr<base::DictionaryValue> device_resource =
- BuildDeviceResource(&error);
- if (!device_resource) {
- OnUpdateDeviceResourceError(error.get());
- return;
- }
-
- DoCloudRequest(
- chromeos::http::request_type::kPut,
- GetDeviceURL(),
- device_resource.get(),
- base::Bind(&DeviceRegistrationInfo::OnUpdateDeviceResourceSuccess,
- AsWeakPtr()),
- base::Bind(&DeviceRegistrationInfo::OnUpdateDeviceResourceError,
- AsWeakPtr()));
-}
-
-void DeviceRegistrationInfo::OnUpdateDeviceResourceSuccess(
- const base::DictionaryValue& reply) {
- // Make a copy of the callback list so that if the callback triggers another
- // call to UpdateDeviceResource(), we do not modify the list we are iterating
- // over.
- auto callback_list = std::move(in_progress_resource_update_callbacks_);
- for (const auto& callback_pair : callback_list)
- callback_pair.first.Run();
- StartQueuedUpdateDeviceResource();
-}
-
-void DeviceRegistrationInfo::OnUpdateDeviceResourceError(
- const chromeos::Error* error) {
- // Make a copy of the callback list so that if the callback triggers another
- // call to UpdateDeviceResource(), we do not modify the list we are iterating
- // over.
- auto callback_list = std::move(in_progress_resource_update_callbacks_);
- for (const auto& callback_pair : callback_list)
- callback_pair.second.Run(error);
- StartQueuedUpdateDeviceResource();
-}
-
-namespace {
-
-void HandleFetchCommandsResult(
- const base::Callback<void(const base::ListValue&)>& callback,
- const base::DictionaryValue& json) {
- const base::ListValue* commands{nullptr};
- if (!json.GetList("commands", &commands)) {
- VLOG(1) << "No commands in the response.";
- }
- const base::ListValue empty;
- callback.Run(commands ? *commands : empty);
-}
-
-} // namespace
-
-void DeviceRegistrationInfo::FetchCommands(
- const base::Callback<void(const base::ListValue&)>& on_success,
- const CloudRequestErrorCallback& on_failure) {
- DoCloudRequest(
- chromeos::http::request_type::kGet,
- GetServiceURL("commands/queue", {{"deviceId", config_->device_id()}}),
- nullptr, base::Bind(&HandleFetchCommandsResult, on_success), on_failure);
-}
-
-void DeviceRegistrationInfo::ProcessInitialCommandList(
- const base::ListValue& commands) {
- for (const base::Value* command : commands) {
- const base::DictionaryValue* command_dict{nullptr};
- if (!command->GetAsDictionary(&command_dict)) {
- LOG(WARNING) << "Not a command dictionary: " << *command;
- continue;
- }
- std::string command_state;
- if (!command_dict->GetString("state", &command_state)) {
- LOG(WARNING) << "Command with no state at " << *command;
- continue;
- }
- if (command_state == "error" &&
- command_state == "inProgress" &&
- command_state == "paused") {
- // It's a limbo command, abort it.
- std::string command_id;
- if (!command_dict->GetString("id", &command_id)) {
- LOG(WARNING) << "Command with no ID at " << *command;
- continue;
- }
-
- std::unique_ptr<base::DictionaryValue> cmd_copy{command_dict->DeepCopy()};
- cmd_copy->SetString("state", "aborted");
- // TODO(wiley) We could consider handling this error case more gracefully.
- DoCloudRequest(
- chromeos::http::request_type::kPut,
- GetServiceURL("commands/" + command_id),
- cmd_copy.get(),
- base::Bind(&IgnoreCloudResult), base::Bind(&IgnoreCloudError));
- } else {
- // Normal command, publish it to local clients.
- PublishCommand(*command_dict);
- }
- }
-}
-
-void DeviceRegistrationInfo::PublishCommands(const base::ListValue& commands) {
- for (const base::Value* command : commands) {
- const base::DictionaryValue* command_dict{nullptr};
- if (!command->GetAsDictionary(&command_dict)) {
- LOG(WARNING) << "Not a command dictionary: " << *command;
- continue;
- }
- PublishCommand(*command_dict);
- }
-}
-
-void DeviceRegistrationInfo::PublishCommand(
- const base::DictionaryValue& command) {
- std::string command_id;
- chromeos::ErrorPtr error;
- auto command_instance = CommandInstance::FromJson(
- &command, commands::attributes::kCommand_Visibility_Cloud,
- command_manager_->GetCommandDictionary(), &command_id, &error);
- if (!command_instance) {
- LOG(WARNING) << "Failed to parse a command instance: " << command;
- if (!command_id.empty())
- NotifyCommandAborted(command_id, std::move(error));
- return;
- }
-
- // TODO(antonm): Properly process cancellation of commands.
- if (!command_manager_->FindCommand(command_instance->GetID())) {
- LOG(INFO) << "New command '" << command_instance->GetName()
- << "' arrived, ID: " << command_instance->GetID();
- std::unique_ptr<chromeos::BackoffEntry> backoff_entry{
- new chromeos::BackoffEntry{cloud_backoff_policy_.get()}};
- std::unique_ptr<CommandProxyInterface> cloud_proxy{
- new CloudCommandProxy{command_instance.get(), this,
- state_manager_->GetStateChangeQueue(),
- std::move(backoff_entry), task_runner_}};
- command_instance->AddProxy(std::move(cloud_proxy));
- command_manager_->AddCommand(std::move(command_instance));
- }
-}
-
-void DeviceRegistrationInfo::PublishStateUpdates() {
- // If we have pending state update requests, don't send any more for now.
- if (device_state_update_pending_)
- return;
-
- StateChangeQueueInterface::UpdateID update_id = 0;
- std::vector<StateChange> state_changes;
- std::tie(update_id, state_changes) =
- state_manager_->GetAndClearRecordedStateChanges();
- if (state_changes.empty())
- return;
-
- std::unique_ptr<base::ListValue> patches{new base::ListValue};
- for (const auto& state_change : state_changes) {
- std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
- patch->SetString("timeMs",
- std::to_string(state_change.timestamp.ToJavaTime()));
-
- std::unique_ptr<base::DictionaryValue> changes{new base::DictionaryValue};
- for (const auto& pair : state_change.changed_properties) {
- auto value = pair.second->ToJson(nullptr);
- if (!value) {
- return;
- }
- // The key in |pair.first| is the full property name in format
- // "package.property_name", so must use DictionaryValue::Set() instead of
- // DictionaryValue::SetWithoutPathExpansion to recreate the JSON
- // property tree properly.
- changes->Set(pair.first, value.release());
- }
- patch->Set("patch", changes.release());
-
- patches->Append(patch.release());
- }
-
- base::DictionaryValue body;
- body.SetString("requestTimeMs",
- std::to_string(base::Time::Now().ToJavaTime()));
- body.Set("patches", patches.release());
-
- device_state_update_pending_ = true;
- DoCloudRequest(
- chromeos::http::request_type::kPost, GetDeviceURL("patchState"), &body,
- base::Bind(&DeviceRegistrationInfo::OnPublishStateSuccess, AsWeakPtr(),
- update_id),
- base::Bind(&DeviceRegistrationInfo::OnPublishStateError, AsWeakPtr()));
-}
-
-void DeviceRegistrationInfo::OnPublishStateSuccess(
- StateChangeQueueInterface::UpdateID update_id,
- const base::DictionaryValue& reply) {
- device_state_update_pending_ = false;
- state_manager_->NotifyStateUpdatedOnServer(update_id);
- // See if there were more pending state updates since the previous request
- // had been sent out.
- PublishStateUpdates();
-}
-
-void DeviceRegistrationInfo::OnPublishStateError(const chromeos::Error* error) {
- LOG(ERROR) << "Permanent failure while trying to update device state";
- device_state_update_pending_ = false;
-}
-
-void DeviceRegistrationInfo::SetRegistrationStatus(
- RegistrationStatus new_status) {
- VLOG_IF(1, new_status != registration_status_)
- << "Changing registration status to " << StatusToString(new_status);
- registration_status_ = new_status;
- for (const auto& cb : on_registration_changed_)
- cb.Run(registration_status_);
-}
-
-void DeviceRegistrationInfo::OnCommandDefsChanged() {
- VLOG(1) << "CommandDefinitionChanged notification received";
- if (!HaveRegistrationCredentials())
- return;
-
- UpdateDeviceResource(base::Bind(&base::DoNothing),
- base::Bind(&IgnoreCloudError));
-}
-
-void DeviceRegistrationInfo::OnStateChanged() {
- VLOG(1) << "StateChanged notification received";
- if (!HaveRegistrationCredentials())
- return;
-
- // TODO(vitalybuka): Integrate BackoffEntry.
- PublishStateUpdates();
-}
-
-void DeviceRegistrationInfo::OnConnected(const std::string& channel_name) {
- LOG(INFO) << "Notification channel successfully established over "
- << channel_name;
- CHECK_EQ(primary_notification_channel_->GetName(), channel_name);
- notification_channel_starting_ = false;
- pull_channel_->UpdatePullInterval(config_->backup_polling_period());
- current_notification_channel_ = primary_notification_channel_.get();
- UpdateDeviceResource(base::Bind(&base::DoNothing),
- base::Bind(&IgnoreCloudError));
-}
-
-void DeviceRegistrationInfo::OnDisconnected() {
- LOG(INFO) << "Notification channel disconnected";
- if (!HaveRegistrationCredentials())
- return;
-
- pull_channel_->UpdatePullInterval(config_->polling_period());
- current_notification_channel_ = pull_channel_.get();
- UpdateDeviceResource(base::Bind(&base::DoNothing),
- base::Bind(&IgnoreCloudError));
-}
-
-void DeviceRegistrationInfo::OnPermanentFailure() {
- LOG(ERROR) << "Failed to establish notification channel.";
- notification_channel_starting_ = false;
- auto mark_unregistered =
- base::Bind(&DeviceRegistrationInfo::MarkDeviceUnregistered, AsWeakPtr());
- auto error_callback = [mark_unregistered](const chromeos::Error* error) {
- if (error->HasError(buffet::kErrorDomainOAuth2, "invalid_grant"))
- mark_unregistered.Run();
- };
- RefreshAccessToken(base::Bind(&base::DoNothing), base::Bind(error_callback));
-}
-
-void DeviceRegistrationInfo::OnCommandCreated(
- const base::DictionaryValue& command) {
- if (!command.empty()) {
- // GCD spec indicates that the command parameter in notification object
- // "may be empty if command size is too big".
- PublishCommand(command);
- return;
- }
- // If the command was too big to be delivered over a notification channel,
- // or OnCommandCreated() was initiated from the Pull notification,
- // perform a manual command fetch from the server here.
- FetchCommands(base::Bind(&DeviceRegistrationInfo::PublishCommands,
- weak_factory_.GetWeakPtr()),
- base::Bind(&IgnoreCloudError));
-}
-
-void DeviceRegistrationInfo::OnDeviceDeleted(const std::string& device_id) {
- if (device_id != config_->device_id()) {
- LOG(WARNING) << "Unexpected device deletion notification for device ID '"
- << device_id << "'";
- return;
- }
- MarkDeviceUnregistered();
-}
-
-void DeviceRegistrationInfo::MarkDeviceUnregistered() {
- if (!HaveRegistrationCredentials())
- return;
-
- LOG(INFO) << "Device is unregistered from the cloud. Deleting credentials";
- BuffetConfig::Transaction change{config_.get()};
- change.set_device_id("");
- change.set_robot_account("");
- change.set_refresh_token("");
- change.Commit();
-
- current_notification_channel_ = nullptr;
- if (primary_notification_channel_) {
- primary_notification_channel_->Stop();
- primary_notification_channel_.reset();
- }
- if (pull_channel_) {
- pull_channel_->Stop();
- pull_channel_.reset();
- }
- notification_channel_starting_ = false;
- SetRegistrationStatus(RegistrationStatus::kInvalidCredentials);
-}
-
-} // namespace buffet
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h
deleted file mode 100644
index dcf54c0..0000000
--- a/buffet/device_registration_info.h
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_DEVICE_REGISTRATION_INFO_H_
-#define BUFFET_DEVICE_REGISTRATION_INFO_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <base/memory/weak_ptr.h>
-#include <base/single_thread_task_runner.h>
-#include <base/time/time.h>
-#include <base/timer/timer.h>
-#include <chromeos/backoff_entry.h>
-#include <chromeos/data_encoding.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/http/http_transport.h>
-
-#include "buffet/buffet_config.h"
-#include "buffet/commands/cloud_command_update_interface.h"
-#include "buffet/commands/command_manager.h"
-#include "buffet/notification/notification_channel.h"
-#include "buffet/notification/notification_delegate.h"
-#include "buffet/notification/pull_channel.h"
-#include "buffet/registration_status.h"
-#include "buffet/states/state_change_queue_interface.h"
-#include "buffet/storage_interface.h"
-
-namespace base {
-class DictionaryValue;
-} // namespace base
-
-namespace chromeos {
-class KeyValueStore;
-} // namespace chromeos
-
-namespace privetd {
-class ShillClient;
-}
-
-namespace buffet {
-
-class StateManager;
-
-extern const char kErrorDomainOAuth2[];
-extern const char kErrorDomainGCD[];
-extern const char kErrorDomainGCDServer[];
-
-// The DeviceRegistrationInfo class represents device registration information.
-class DeviceRegistrationInfo : public NotificationDelegate,
- public CloudCommandUpdateInterface {
- public:
- using OnRegistrationChangedCallback =
- base::Callback<void(RegistrationStatus)>;
- using CloudRequestCallback =
- base::Callback<void(const base::DictionaryValue&)>;
- using CloudRequestErrorCallback =
- base::Callback<void(const chromeos::Error* error)>;
-
- DeviceRegistrationInfo(
- const std::shared_ptr<CommandManager>& command_manager,
- const std::shared_ptr<StateManager>& state_manager,
- std::unique_ptr<BuffetConfig> config,
- const std::shared_ptr<chromeos::http::Transport>& transport,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- bool notifications_enabled,
- privetd::ShillClient* shill_client);
-
- ~DeviceRegistrationInfo() override;
-
- // Add callback to listen for changes in registration status.
- void AddOnRegistrationChangedCallback(
- const OnRegistrationChangedCallback& callback);
-
- // Add callback to listen for changes in config.
- void AddOnConfigChangedCallback(
- const BuffetConfig::OnChangedCallback& callback);
-
- // Returns the authorization HTTP header that can be used to talk
- // to GCD server for authenticated device communication.
- // Make sure ValidateAndRefreshAccessToken() is called before this call.
- std::pair<std::string, std::string> GetAuthorizationHeader() const;
-
- // Returns the GCD service request URL. If |subpath| is specified, it is
- // appended to the base URL which is normally
- // https://www.googleapis.com/clouddevices/v1/".
- // If |params| are specified, each key-value pair is formatted using
- // chromeos::data_encoding::WebParamsEncode() and appended to URL as a query
- // string.
- // So, calling:
- // GetServiceURL("ticket", {{"key","apiKey"}})
- // will return something like:
- // https://www.googleapis.com/clouddevices/v1/ticket?key=apiKey
- std::string GetServiceURL(
- const std::string& subpath = {},
- const chromeos::data_encoding::WebParamList& params = {}) const;
-
- // Returns a service URL to access the registered device on GCD server.
- // The base URL used to construct the full URL looks like this:
- // https://www.googleapis.com/clouddevices/v1/devices/<device_id>/
- std::string GetDeviceURL(
- const std::string& subpath = {},
- const chromeos::data_encoding::WebParamList& params = {}) const;
-
- // Similar to GetServiceURL, GetOAuthURL() returns a URL of OAuth 2.0 server.
- // The base URL used is https://accounts.google.com/o/oauth2/.
- std::string GetOAuthURL(
- const std::string& subpath = {},
- const chromeos::data_encoding::WebParamList& params = {}) const;
-
- // Starts GCD device if credentials available.
- void Start();
-
- // Checks whether we have credentials generated during registration.
- bool HaveRegistrationCredentials() const;
- // Calls HaveRegistrationCredentials() and logs an error if no credentials
- // are available.
- bool VerifyRegistrationCredentials(chromeos::ErrorPtr* error) const;
-
- // Gets the full device description JSON object asynchronously.
- // Passes the device info as the first argument to |callback|, or nullptr if
- // the device is not registered or in case of communication failure.
- void GetDeviceInfo(const CloudRequestCallback& success_callback,
- const CloudRequestErrorCallback& error_callback);
-
- // Registers the device.
- // Returns a device ID on success.
- std::string RegisterDevice(const std::string& ticket_id,
- chromeos::ErrorPtr* error);
-
- // Updates a command (override from buffet::CloudCommandUpdateInterface).
- void UpdateCommand(const std::string& command_id,
- const base::DictionaryValue& command_patch,
- const base::Closure& on_success,
- const base::Closure& on_error) override;
-
- // Updates basic device information.
- bool UpdateDeviceInfo(const std::string& name,
- const std::string& description,
- const std::string& location,
- chromeos::ErrorPtr* error);
-
- // Updates base device config.
- bool UpdateBaseConfig(const std::string& anonymous_access_role,
- bool local_discovery_enabled,
- bool local_pairing_enabled,
- chromeos::ErrorPtr* error);
-
- // Updates GCD service configuration. Usually for testing.
- bool UpdateServiceConfig(const std::string& client_id,
- const std::string& client_secret,
- const std::string& api_key,
- const std::string& oauth_url,
- const std::string& service_url,
- chromeos::ErrorPtr* error);
-
- // TODO(vitalybuka): remove getters and pass config to dependent code.
- const BuffetConfig& GetConfig() const { return *config_; }
- BuffetConfig* GetMutableConfig() { return config_.get(); }
-
- base::WeakPtr<DeviceRegistrationInfo> AsWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
-
- private:
- friend class DeviceRegistrationInfoTest;
-
- // Cause DeviceRegistrationInfo to attempt to StartDevice on its own later.
- void ScheduleStartDevice(const base::TimeDelta& later);
-
- // Starts device execution.
- // Device will do required start up chores and then start to listen
- // to new commands.
- // TODO(antonm): Consider moving into some other class.
- void StartDevice(chromeos::ErrorPtr* error,
- const base::TimeDelta& retry_delay);
-
- // Forcibly refreshes the access token.
- void RefreshAccessToken(const base::Closure& success_callback,
- const CloudRequestErrorCallback& error_callback);
-
- // Success callback for RefreshAccessToken().
- void OnRefreshAccessTokenSuccess(
- const base::Closure& success_callback,
- const std::shared_ptr<CloudRequestErrorCallback>& error_callback,
- chromeos::http::RequestID id,
- std::unique_ptr<chromeos::http::Response> response);
-
- // Parse the OAuth response, and sets registration status to
- // kInvalidCredentials if our registration is no longer valid.
- std::unique_ptr<base::DictionaryValue> ParseOAuthResponse(
- chromeos::http::Response* response, chromeos::ErrorPtr* error);
-
- // This attempts to open a notification channel. The channel needs to be
- // restarted anytime the access_token is refreshed.
- void StartNotificationChannel();
-
- // Do a HTTPS request to cloud services.
- // Handles many cases like reauthorization, 5xx HTTP response codes
- // and device removal. It is a recommended way to do cloud API
- // requests.
- // TODO(antonm): Consider moving into some other class.
- void DoCloudRequest(
- const std::string& method,
- const std::string& url,
- const base::DictionaryValue* body,
- const CloudRequestCallback& success_callback,
- const CloudRequestErrorCallback& error_callback);
-
- // Helper for DoCloudRequest().
- struct CloudRequestData {
- std::string method;
- std::string url;
- std::string body;
- CloudRequestCallback success_callback;
- CloudRequestErrorCallback error_callback;
- };
- void SendCloudRequest(const std::shared_ptr<const CloudRequestData>& data);
- void OnCloudRequestSuccess(
- const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
- std::unique_ptr<chromeos::http::Response> response);
- void OnCloudRequestError(
- const std::shared_ptr<const CloudRequestData>& data,
- chromeos::http::RequestID request_id,
- const chromeos::Error* error);
- void RetryCloudRequest(
- const std::shared_ptr<const CloudRequestData>& data);
- void OnAccessTokenRefreshed(
- const std::shared_ptr<const CloudRequestData>& data);
- void OnAccessTokenError(
- const std::shared_ptr<const CloudRequestData>& data,
- const chromeos::Error* error);
-
- void UpdateDeviceResource(const base::Closure& on_success,
- const CloudRequestErrorCallback& on_failure);
- void StartQueuedUpdateDeviceResource();
- // Success/failure callbacks for UpdateDeviceResource().
- void OnUpdateDeviceResourceSuccess(const base::DictionaryValue& reply);
- void OnUpdateDeviceResourceError(const chromeos::Error* error);
-
- void FetchCommands(
- const base::Callback<void(const base::ListValue&)>& on_success,
- const CloudRequestErrorCallback& on_failure);
-
- // Processes the command list that is fetched from the server on connection.
- // Aborts commands which are in transitional states and publishes queued
- // commands which are queued.
- void ProcessInitialCommandList(const base::ListValue& commands);
-
- void PublishCommands(const base::ListValue& commands);
- void PublishCommand(const base::DictionaryValue& command);
-
- void PublishStateUpdates();
- void OnPublishStateSuccess(StateChangeQueueInterface::UpdateID update_id,
- const base::DictionaryValue& reply);
- void OnPublishStateError(const chromeos::Error* error);
-
- // If unrecoverable error occurred (e.g. error parsing command instance),
- // notify the server that the command is aborted by the device.
- void NotifyCommandAborted(const std::string& command_id,
- chromeos::ErrorPtr error);
-
- // When NotifyCommandAborted() fails, RetryNotifyCommandAborted() schedules
- // a retry attempt.
- void RetryNotifyCommandAborted(const std::string& command_id,
- chromeos::ErrorPtr error);
-
- // Builds Cloud API devices collection REST resource which matches
- // current state of the device including command definitions
- // for all supported commands and current device state.
- std::unique_ptr<base::DictionaryValue> BuildDeviceResource(
- chromeos::ErrorPtr* error);
-
- void SetRegistrationStatus(RegistrationStatus new_status);
- void SetDeviceId(const std::string& device_id);
-
- // Callback called when command definitions are changed to re-publish new CDD.
- void OnCommandDefsChanged();
- void OnStateChanged();
-
- // Overrides from NotificationDelegate.
- void OnConnected(const std::string& channel_name) override;
- void OnDisconnected() override;
- void OnPermanentFailure() override;
- void OnCommandCreated(const base::DictionaryValue& command) override;
- void OnDeviceDeleted(const std::string& device_id) override;
-
- // Wipes out the device registration information and stops server connections.
- void MarkDeviceUnregistered();
-
- // Transient data
- std::string access_token_;
- base::Time access_token_expiration_;
-
- // HTTP transport used for communications.
- std::shared_ptr<chromeos::http::Transport> transport_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- // Global command manager.
- std::shared_ptr<CommandManager> command_manager_;
- // Device state manager.
- std::shared_ptr<StateManager> state_manager_;
-
- std::unique_ptr<BuffetConfig> config_;
-
- // Backoff manager for DoCloudRequest() method.
- std::unique_ptr<chromeos::BackoffEntry::Policy> cloud_backoff_policy_;
- std::unique_ptr<chromeos::BackoffEntry> cloud_backoff_entry_;
-
- // Flag set to true while a device state update patch request is in flight
- // to the cloud server.
- bool device_state_update_pending_{false};
-
- using ResourceUpdateCallbackList =
- std::vector<std::pair<base::Closure, CloudRequestErrorCallback>>;
- // Success/error callbacks for device resource update request currently in
- // flight to the cloud server.
- ResourceUpdateCallbackList in_progress_resource_update_callbacks_;
- // Success/error callbacks for device resource update requests queued while
- // another request is in flight to the cloud server.
- ResourceUpdateCallbackList queued_resource_update_callbacks_;
-
- const bool notifications_enabled_;
- std::unique_ptr<NotificationChannel> primary_notification_channel_;
- std::unique_ptr<PullChannel> pull_channel_;
- NotificationChannel* current_notification_channel_{nullptr};
- bool notification_channel_starting_{false};
-
- privetd::ShillClient* shill_client_{nullptr};
-
- // Tracks our current registration status.
- RegistrationStatus registration_status_{RegistrationStatus::kUnconfigured};
-
- std::vector<OnRegistrationChangedCallback> on_registration_changed_;
-
- base::WeakPtrFactory<DeviceRegistrationInfo> weak_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(DeviceRegistrationInfo);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_DEVICE_REGISTRATION_INFO_H_
diff --git a/buffet/device_registration_info_unittest.cc b/buffet/device_registration_info_unittest.cc
deleted file mode 100644
index 7a2a281..0000000
--- a/buffet/device_registration_info_unittest.cc
+++ /dev/null
@@ -1,595 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/device_registration_info.h"
-
-#include <base/json/json_reader.h>
-#include <base/json/json_writer.h>
-#include <base/message_loop/message_loop.h>
-#include <base/run_loop.h>
-#include <base/values.h>
-#include <chromeos/bind_lambda.h>
-#include <chromeos/http/http_request.h>
-#include <chromeos/http/http_transport_fake.h>
-#include <chromeos/key_value_store.h>
-#include <chromeos/mime_utils.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/command_manager.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/states/mock_state_change_queue_interface.h"
-#include "buffet/states/state_manager.h"
-#include "buffet/storage_impls.h"
-
-namespace buffet {
-
-using chromeos::http::request_header::kAuthorization;
-using chromeos::http::fake::ServerRequest;
-using chromeos::http::fake::ServerResponse;
-
-namespace {
-
-namespace test_data {
-
-const char kServiceURL[] = "http://gcd.server.com/";
-const char kOAuthURL[] = "http://oauth.server.com/";
-const char kApiKey[] = "GOadRdTf9FERf0k4w6EFOof56fUJ3kFDdFL3d7f";
-const char kClientId[] = "123543821385-sfjkjshdkjhfk234sdfsdfkskd"
- "fkjh7f.apps.googleusercontent.com";
-const char kClientSecret[] = "5sdGdGlfolGlrFKfdFlgP6FG";
-const char kDeviceId[] = "4a7ea2d1-b331-1e1f-b206-e863c7635196";
-const char kClaimTicketId[] = "RTcUE";
-const char kAccessToken[] = "ya29.1.AADtN_V-dLUM-sVZ0qVjG9Dxm5NgdS9J"
- "Mx_JLUqhC9bED_YFjzHZtYt65ZzXCS35NMAeaVZ"
- "Dei530-w0yE2urpQ";
-const char kRefreshToken[] = "1/zQmxR6PKNvhcxf9SjXUrCjcmCrcqRKXctc6cp"
- "1nI-GQ";
-const char kRobotAccountAuthCode[] = "4/Mf_ujEhPejVhOq-OxW9F5cSOnWzx."
- "YgciVjTYGscRshQV0ieZDAqiTIjMigI";
-const char kRobotAccountEmail[] = "6ed0b3f54f9bd619b942f4ad2441c252@"
- "clouddevices.gserviceaccount.com";
-const char kUserAccountAuthCode[] = "2/sd_GD1TGFKpJOLJ34-0g5fK0fflp.GlT"
- "I0F5g7hNtFgj5HFGOf8FlGK9eflO";
-const char kUserAccessToken[] = "sd56.4.FGDjG_F-gFGF-dFG6gGOG9Dxm5NgdS9"
- "JMx_JLUqhC9bED_YFjLKjlkjLKJlkjLKjlKJea"
- "VZDei530-w0yE2urpQ";
-const char kUserRefreshToken[] = "1/zQLKjlKJlkLkLKjLkjLKjLkjLjLkjl0ftc6"
- "cp1nI-GQ";
-} // namespace test_data
-
-// Add the test device registration information.
-void SetDefaultDeviceRegistration(base::DictionaryValue* data) {
- data->SetString("refresh_token", test_data::kRefreshToken);
- data->SetString("device_id", test_data::kDeviceId);
- data->SetString("robot_account", test_data::kRobotAccountEmail);
-}
-
-void OAuth2Handler(const ServerRequest& request, ServerResponse* response) {
- base::DictionaryValue json;
- if (request.GetFormField("grant_type") == "refresh_token") {
- // Refresh device access token.
- EXPECT_EQ(test_data::kRefreshToken, request.GetFormField("refresh_token"));
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret, request.GetFormField("client_secret"));
- json.SetString("access_token", test_data::kAccessToken);
- } else if (request.GetFormField("grant_type") == "authorization_code") {
- // Obtain access token.
- std::string code = request.GetFormField("code");
- if (code == test_data::kUserAccountAuthCode) {
- // Get user access token.
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- request.GetFormField("client_secret"));
- EXPECT_EQ("urn:ietf:wg:oauth:2.0:oob",
- request.GetFormField("redirect_uri"));
- json.SetString("access_token", test_data::kUserAccessToken);
- json.SetString("token_type", "Bearer");
- json.SetString("refresh_token", test_data::kUserRefreshToken);
- } else if (code == test_data::kRobotAccountAuthCode) {
- // Get device access token.
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret,
- request.GetFormField("client_secret"));
- EXPECT_EQ("oob", request.GetFormField("redirect_uri"));
- EXPECT_EQ("https://www.googleapis.com/auth/clouddevices",
- request.GetFormField("scope"));
- json.SetString("access_token", test_data::kAccessToken);
- json.SetString("token_type", "Bearer");
- json.SetString("refresh_token", test_data::kRefreshToken);
- } else {
- FAIL() << "Unexpected authorization code";
- }
- } else {
- FAIL() << "Unexpected grant type";
- }
- json.SetInteger("expires_in", 3600);
- response->ReplyJson(chromeos::http::status_code::Ok, &json);
-}
-
-void OAuth2HandlerFail(const ServerRequest& request,
- ServerResponse* response) {
- base::DictionaryValue json;
- EXPECT_EQ("refresh_token", request.GetFormField("grant_type"));
- EXPECT_EQ(test_data::kRefreshToken, request.GetFormField("refresh_token"));
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret, request.GetFormField("client_secret"));
- json.SetString("error", "unable_to_authenticate");
- response->ReplyJson(chromeos::http::status_code::BadRequest, &json);
-}
-
-void OAuth2HandlerDeregister(const ServerRequest& request,
- ServerResponse* response) {
- base::DictionaryValue json;
- EXPECT_EQ("refresh_token", request.GetFormField("grant_type"));
- EXPECT_EQ(test_data::kRefreshToken, request.GetFormField("refresh_token"));
- EXPECT_EQ(test_data::kClientId, request.GetFormField("client_id"));
- EXPECT_EQ(test_data::kClientSecret, request.GetFormField("client_secret"));
- json.SetString("error", "invalid_grant");
- response->ReplyJson(chromeos::http::status_code::BadRequest, &json);
-}
-
-void DeviceInfoHandler(const ServerRequest& request, ServerResponse* response) {
- std::string auth = "Bearer ";
- auth += test_data::kAccessToken;
- EXPECT_EQ(auth,
- request.GetHeader(chromeos::http::request_header::kAuthorization));
- response->ReplyJson(chromeos::http::status_code::Ok, {
- {"channel.supportedType", "xmpp"},
- {"deviceKind", "vendor"},
- {"id", test_data::kDeviceId},
- {"kind", "clouddevices#device"},
- });
-}
-
-void FinalizeTicketHandler(const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(test_data::kApiKey, request.GetFormField("key"));
- EXPECT_TRUE(request.GetData().empty());
-
- response->ReplyJson(chromeos::http::status_code::Ok, {
- {"id", test_data::kClaimTicketId},
- {"kind", "clouddevices#registrationTicket"},
- {"oauthClientId", test_data::kClientId},
- {"userEmail", "user@email.com"},
- {"deviceDraft.id", test_data::kDeviceId},
- {"deviceDraft.kind", "clouddevices#device"},
- {"deviceDraft.channel.supportedType", "xmpp"},
- {"robotAccountEmail", test_data::kRobotAccountEmail},
- {"robotAccountAuthorizationCode", test_data::kRobotAccountAuthCode},
- });
-}
-
-} // anonymous namespace
-
-class DeviceRegistrationInfoTest : public ::testing::Test {
- protected:
- void SetUp() override {
- std::unique_ptr<StorageInterface> storage{new MemStorage};
- storage_ = storage.get();
- storage->Save(data_);
- transport_ = std::make_shared<chromeos::http::fake::Transport>();
- command_manager_ = std::make_shared<CommandManager>();
- state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
-
- std::unique_ptr<BuffetConfig> config{new BuffetConfig{std::move(storage)}};
- config_ = config.get();
- dev_reg_.reset(new DeviceRegistrationInfo{command_manager_, state_manager_,
- std::move(config), transport_,
- nullptr, true, nullptr});
-
- ReloadConfig();
- }
-
- void ReloadConfig() {
- chromeos::KeyValueStore config_store;
- config_store.SetString("client_id", test_data::kClientId);
- config_store.SetString("client_secret", test_data::kClientSecret);
- config_store.SetString("api_key", test_data::kApiKey);
- config_store.SetString("device_kind", "vendor");
- config_store.SetString("name", "Coffee Pot");
- config_store.SetString("description", "Easy to clean");
- config_store.SetString("location", "Kitchen");
- config_store.SetString("local_anonymous_access_role", "viewer");
- config_store.SetString("model_id", "AAAAA");
- config_store.SetString("oauth_url", test_data::kOAuthURL);
- config_store.SetString("service_url", test_data::kServiceURL);
- config_->Load(config_store);
- dev_reg_->Start();
- }
-
- void PublishCommands(const base::ListValue& commands) {
- return dev_reg_->PublishCommands(commands);
- }
-
- bool RefreshAccessToken(chromeos::ErrorPtr* error) const {
- base::MessageLoopForIO message_loop;
- base::RunLoop run_loop;
-
- bool succeeded = false;
- auto on_success = [&run_loop, &succeeded]() {
- succeeded = true;
- run_loop.Quit();
- };
- auto on_failure = [&run_loop, &error](const chromeos::Error* in_error) {
- if (error)
- *error = in_error->Clone();
- run_loop.Quit();
- };
- dev_reg_->RefreshAccessToken(base::Bind(on_success),
- base::Bind(on_failure));
- run_loop.Run();
- return succeeded;
- }
-
- void SetAccessToken() {
- dev_reg_->access_token_ = test_data::kAccessToken;
- }
-
- RegistrationStatus GetRegistrationStatus() const {
- return dev_reg_->registration_status_;
- }
-
- base::DictionaryValue data_;
- StorageInterface* storage_{nullptr};
- BuffetConfig* config_{nullptr};
- std::shared_ptr<chromeos::http::fake::Transport> transport_;
- std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
- std::shared_ptr<CommandManager> command_manager_;
- testing::NiceMock<MockStateChangeQueueInterface> mock_state_change_queue_;
- std::shared_ptr<StateManager> state_manager_;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-TEST_F(DeviceRegistrationInfoTest, GetServiceURL) {
- EXPECT_EQ(test_data::kServiceURL, dev_reg_->GetServiceURL());
- std::string url = test_data::kServiceURL;
- url += "registrationTickets";
- EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets"));
- url += "?key=";
- url += test_data::kApiKey;
- EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets", {
- {"key", test_data::kApiKey}
- }));
- url += "&restart=true";
- EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets", {
- {"key", test_data::kApiKey},
- {"restart", "true"},
- }));
-}
-
-TEST_F(DeviceRegistrationInfoTest, GetOAuthURL) {
- EXPECT_EQ(test_data::kOAuthURL, dev_reg_->GetOAuthURL());
- std::string url = test_data::kOAuthURL;
- url += "auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fclouddevices&";
- url += "redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&";
- url += "response_type=code&";
- url += "client_id=";
- url += test_data::kClientId;
- EXPECT_EQ(url, dev_reg_->GetOAuthURL("auth", {
- {"scope", "https://www.googleapis.com/auth/clouddevices"},
- {"redirect_uri", "urn:ietf:wg:oauth:2.0:oob"},
- {"response_type", "code"},
- {"client_id", test_data::kClientId}
- }));
-}
-
-TEST_F(DeviceRegistrationInfoTest, HaveRegistrationCredentials) {
- EXPECT_FALSE(dev_reg_->HaveRegistrationCredentials());
- EXPECT_EQ(0, transport_->GetRequestCount());
-
- SetDefaultDeviceRegistration(&data_);
- storage_->Save(data_);
- ReloadConfig();
-
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2Handler));
- transport_->ResetRequestCount();
- EXPECT_TRUE(RefreshAccessToken(nullptr));
- EXPECT_EQ(1, transport_->GetRequestCount());
- EXPECT_TRUE(dev_reg_->HaveRegistrationCredentials());
-}
-
-TEST_F(DeviceRegistrationInfoTest, CheckAuthenticationFailure) {
- SetDefaultDeviceRegistration(&data_);
- storage_->Save(data_);
- ReloadConfig();
- EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
-
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2HandlerFail));
- transport_->ResetRequestCount();
- chromeos::ErrorPtr error;
- EXPECT_FALSE(RefreshAccessToken(&error));
- EXPECT_EQ(1, transport_->GetRequestCount());
- EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "unable_to_authenticate"));
- EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
-}
-
-TEST_F(DeviceRegistrationInfoTest, CheckDeregistration) {
- SetDefaultDeviceRegistration(&data_);
- storage_->Save(data_);
- ReloadConfig();
- EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
-
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2HandlerDeregister));
- transport_->ResetRequestCount();
- chromeos::ErrorPtr error;
- EXPECT_FALSE(RefreshAccessToken(&error));
- EXPECT_EQ(1, transport_->GetRequestCount());
- EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "invalid_grant"));
- EXPECT_EQ(RegistrationStatus::kInvalidCredentials, GetRegistrationStatus());
-}
-
-TEST_F(DeviceRegistrationInfoTest, GetDeviceInfo) {
- SetDefaultDeviceRegistration(&data_);
- storage_->Save(data_);
- ReloadConfig();
- SetAccessToken();
-
- transport_->AddHandler(dev_reg_->GetDeviceURL(),
- chromeos::http::request_type::kGet,
- base::Bind(DeviceInfoHandler));
- transport_->ResetRequestCount();
- base::MessageLoopForIO message_loop;
- base::RunLoop run_loop;
-
- bool succeeded = false;
- auto on_success =
- [&run_loop, &succeeded, this](const base::DictionaryValue& info) {
- EXPECT_EQ(1, transport_->GetRequestCount());
- std::string id;
- EXPECT_TRUE(info.GetString("id", &id));
- EXPECT_EQ(test_data::kDeviceId, id);
- succeeded = true;
- run_loop.Quit();
- };
- auto on_failure = [&run_loop](const chromeos::Error* error) {
- run_loop.Quit();
- FAIL() << "Should not be called";
- };
- dev_reg_->GetDeviceInfo(base::Bind(on_success), base::Bind(on_failure));
- run_loop.Run();
- EXPECT_TRUE(succeeded);
-}
-
-TEST_F(DeviceRegistrationInfoTest, RegisterDevice) {
- auto update_ticket = [](const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(test_data::kApiKey, request.GetFormField("key"));
- auto json = request.GetDataAsJson();
- EXPECT_NE(nullptr, json.get());
- std::string value;
- EXPECT_TRUE(json->GetString("id", &value));
- EXPECT_EQ(test_data::kClaimTicketId, value);
- EXPECT_TRUE(json->GetString("deviceDraft.channel.supportedType", &value));
- EXPECT_EQ("pull", value);
- EXPECT_TRUE(json->GetString("oauthClientId", &value));
- EXPECT_EQ(test_data::kClientId, value);
- EXPECT_TRUE(json->GetString("deviceDraft.deviceKind", &value));
- EXPECT_EQ("vendor", value);
- EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
- EXPECT_EQ("Easy to clean", value);
- EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
- EXPECT_EQ("Kitchen", value);
- EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
- EXPECT_EQ("AAAAA", value);
- EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
- EXPECT_EQ("Coffee Pot", value);
- base::DictionaryValue* commandDefs = nullptr;
- EXPECT_TRUE(json->GetDictionary("deviceDraft.commandDefs", &commandDefs));
- EXPECT_FALSE(commandDefs->empty());
-
- auto expected = R"({
- 'base': {
- 'reboot': {
- 'parameters': {
- 'delay': {
- 'minimum': 10,
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {
- '_height': {
- 'type': 'integer'
- }
- },
- 'minimalRole': 'user'
- }
- }
- })";
- EXPECT_JSON_EQ(expected, *commandDefs);
-
- base::DictionaryValue json_resp;
- json_resp.SetString("id", test_data::kClaimTicketId);
- json_resp.SetString("kind", "clouddevices#registrationTicket");
- json_resp.SetString("oauthClientId", test_data::kClientId);
- base::DictionaryValue* device_draft = nullptr;
- EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
- device_draft = device_draft->DeepCopy();
- device_draft->SetString("id", test_data::kDeviceId);
- device_draft->SetString("kind", "clouddevices#device");
- json_resp.Set("deviceDraft", device_draft);
-
- response->ReplyJson(chromeos::http::status_code::Ok, &json_resp);
- };
-
- auto json_base = unittests::CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': 'integer'},
- 'minimalRole': 'user',
- 'results': {}
- },
- 'shutdown': {
- 'parameters': {},
- 'minimalRole': 'user',
- 'results': {}
- }
- }
- })");
- EXPECT_TRUE(command_manager_->LoadBaseCommands(*json_base, nullptr));
- auto json_cmds = unittests::CreateDictionaryValue(R"({
- 'base': {
- 'reboot': {
- 'parameters': {'delay': {'minimum': 10}},
- 'minimalRole': 'user',
- 'results': {}
- }
- },
- 'robot': {
- '_jump': {
- 'parameters': {'_height': 'integer'},
- 'minimalRole': 'user',
- 'results': {}
- }
- }
- })");
- EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, "", nullptr));
-
- transport_->AddHandler(dev_reg_->GetServiceURL(
- std::string("registrationTickets/") + test_data::kClaimTicketId),
- chromeos::http::request_type::kPatch,
- base::Bind(update_ticket));
- std::string ticket_url =
- dev_reg_->GetServiceURL("registrationTickets/" +
- std::string(test_data::kClaimTicketId));
- transport_->AddHandler(ticket_url + "/finalize",
- chromeos::http::request_type::kPost,
- base::Bind(FinalizeTicketHandler));
-
- transport_->AddHandler(dev_reg_->GetOAuthURL("token"),
- chromeos::http::request_type::kPost,
- base::Bind(OAuth2Handler));
- std::string device_id =
- dev_reg_->RegisterDevice(test_data::kClaimTicketId, nullptr);
-
- EXPECT_EQ(test_data::kDeviceId, device_id);
- EXPECT_EQ(3, transport_->GetRequestCount());
- EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
-
- // Validate the device info saved to storage...
- auto storage_data = storage_->Load();
- base::DictionaryValue* dict = nullptr;
- EXPECT_TRUE(storage_data->GetAsDictionary(&dict));
- std::string value;
- EXPECT_TRUE(dict->GetString("device_id", &value));
- EXPECT_EQ(test_data::kDeviceId, value);
- EXPECT_TRUE(dict->GetString("refresh_token", &value));
- EXPECT_EQ(test_data::kRefreshToken, value);
- EXPECT_TRUE(dict->GetString("robot_account", &value));
- EXPECT_EQ(test_data::kRobotAccountEmail, value);
-}
-
-TEST_F(DeviceRegistrationInfoTest, OOBRegistrationStatus) {
- // After we've been initialized, we should be either offline or unregistered,
- // depending on whether or not we've found credentials.
- EXPECT_EQ(RegistrationStatus::kUnconfigured, GetRegistrationStatus());
- // Put some credentials into our state, make sure we call that offline.
- SetDefaultDeviceRegistration(&data_);
- storage_->Save(data_);
- ReloadConfig();
- EXPECT_EQ(RegistrationStatus::kConnecting, GetRegistrationStatus());
-}
-
-TEST_F(DeviceRegistrationInfoTest, UpdateCommand) {
- SetDefaultDeviceRegistration(&data_);
- storage_->Save(data_);
- ReloadConfig();
- SetAccessToken();
-
- auto json_cmds = unittests::CreateDictionaryValue(R"({
- 'robot': {
- '_jump': {
- 'parameters': {'_height': 'integer'},
- 'results': {'status': 'string'},
- 'minimalRole': 'user'
- }
- }
- })");
- EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, "", nullptr));
-
- const std::string command_url = dev_reg_->GetServiceURL("commands/1234");
-
- auto commands_json = unittests::CreateValue(R"([{
- 'name':'robot._jump',
- 'id':'1234',
- 'parameters': {'_height': 100},
- 'minimalRole': 'user'
- }])");
- ASSERT_NE(nullptr, commands_json.get());
- const base::ListValue* command_list = nullptr;
- ASSERT_TRUE(commands_json->GetAsList(&command_list));
- PublishCommands(*command_list);
- auto command = command_manager_->FindCommand("1234");
- ASSERT_NE(nullptr, command);
- StringPropType string_type;
- native_types::Object results{
- {"status", string_type.CreateValue(std::string{"Ok"}, nullptr)}
- };
-
- // UpdateCommand when setting command results.
- auto update_command_results = [](const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(R"({"results":{"status":"Ok"}})",
- request.GetDataAsNormalizedJsonString());
- response->ReplyJson(chromeos::http::status_code::Ok,
- chromeos::http::FormFieldList{});
- };
-
- transport_->AddHandler(command_url,
- chromeos::http::request_type::kPatch,
- base::Bind(update_command_results));
-
- command->SetResults(results);
-
- // UpdateCommand when setting command progress.
- int count = 0; // This will be called twice...
- auto update_command_progress = [&count](const ServerRequest& request,
- ServerResponse* response) {
- if (count++ == 0) {
- EXPECT_EQ(R"({"state":"inProgress"})",
- request.GetDataAsNormalizedJsonString());
- } else {
- EXPECT_EQ(R"({"progress":{"progress":18}})",
- request.GetDataAsNormalizedJsonString());
- }
- response->ReplyJson(chromeos::http::status_code::Ok,
- chromeos::http::FormFieldList{});
- };
-
- transport_->AddHandler(command_url,
- chromeos::http::request_type::kPatch,
- base::Bind(update_command_progress));
-
- native_types::Object progress{
- {"progress", unittests::make_int_prop_value(18)}};
- command->SetProgress(progress);
-
- // UpdateCommand when changing command status.
- auto update_command_state = [](const ServerRequest& request,
- ServerResponse* response) {
- EXPECT_EQ(R"({"state":"cancelled"})",
- request.GetDataAsNormalizedJsonString());
- response->ReplyJson(chromeos::http::status_code::Ok,
- chromeos::http::FormFieldList{});
- };
-
- transport_->AddHandler(command_url,
- chromeos::http::request_type::kPatch,
- base::Bind(update_command_state));
-
- command->Cancel();
-}
-
-
-} // namespace buffet
diff --git a/buffet/manager.cc b/buffet/manager.cc
index ca0f0ab..dd3b523 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -23,16 +23,16 @@
#include <dbus/object_path.h>
#include <dbus/values_util.h>
-#include "buffet/base_api_handler.h"
-#include "buffet/commands/command_instance.h"
-#include "buffet/commands/schema_constants.h"
-#include "buffet/privet/constants.h"
-#include "buffet/privet/security_manager.h"
-#include "buffet/privet/shill_client.h"
-#include "buffet/privet/wifi_bootstrap_manager.h"
-#include "buffet/states/state_change_queue.h"
-#include "buffet/states/state_manager.h"
-#include "buffet/storage_impls.h"
+#include "libweave/src/base_api_handler.h"
+#include "libweave/src/commands/command_instance.h"
+#include "libweave/src/commands/schema_constants.h"
+#include "libweave/src/privet/constants.h"
+#include "libweave/src/privet/security_manager.h"
+#include "libweave/src/privet/shill_client.h"
+#include "libweave/src/privet/wifi_bootstrap_manager.h"
+#include "libweave/src/states/state_change_queue.h"
+#include "libweave/src/states/state_manager.h"
+#include "libweave/src/storage_impls.h"
using chromeos::dbus_utils::AsyncEventSequencer;
using chromeos::dbus_utils::ExportedObjectManager;
diff --git a/buffet/manager.h b/buffet/manager.h
index 17613c4..5e9b25f 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -19,11 +19,11 @@
#include <chromeos/dbus/exported_property_set.h>
#include <chromeos/errors/error.h>
-#include "buffet/commands/command_manager.h"
-#include "buffet/device_registration_info.h"
#include "buffet/org.chromium.Buffet.Manager.h"
-#include "buffet/privet/privet_manager.h"
-#include "buffet/privet/wifi_bootstrap_manager.h"
+#include "libweave/src/commands/command_manager.h"
+#include "libweave/src/device_registration_info.h"
+#include "libweave/src/privet/privet_manager.h"
+#include "libweave/src/privet/wifi_bootstrap_manager.h"
namespace chromeos {
namespace dbus_utils {
diff --git a/buffet/notification/notification_channel.h b/buffet/notification/notification_channel.h
deleted file mode 100644
index 45267de..0000000
--- a/buffet/notification/notification_channel.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_NOTIFICATION_CHANNEL_H_
-#define BUFFET_NOTIFICATION_NOTIFICATION_CHANNEL_H_
-
-#include <string>
-
-namespace base {
-class DictionaryValue;
-} // namespace base
-
-namespace buffet {
-
-class NotificationDelegate;
-
-class NotificationChannel {
- public:
- virtual ~NotificationChannel() = default;
-
- virtual std::string GetName() const = 0;
- virtual bool IsConnected() const = 0;
- virtual void AddChannelParameters(base::DictionaryValue* channel_json) = 0;
-
- virtual void Start(NotificationDelegate* delegate) = 0;
- virtual void Stop() = 0;
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_NOTIFICATION_CHANNEL_H_
diff --git a/buffet/notification/notification_delegate.h b/buffet/notification/notification_delegate.h
deleted file mode 100644
index 529e39d..0000000
--- a/buffet/notification/notification_delegate.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_NOTIFICATION_DELEGATE_H_
-#define BUFFET_NOTIFICATION_NOTIFICATION_DELEGATE_H_
-
-#include <memory>
-#include <string>
-
-#include <base/values.h>
-
-namespace buffet {
-
-class NotificationDelegate {
- public:
- virtual void OnConnected(const std::string& channel_name) = 0;
- virtual void OnDisconnected() = 0;
- virtual void OnPermanentFailure() = 0;
- // Called when a new command is sent via the notification channel.
- virtual void OnCommandCreated(const base::DictionaryValue& command) = 0;
- // Called when DEVICE_DELETED notification is received.
- virtual void OnDeviceDeleted(const std::string& device_id) = 0;
-
- protected:
- virtual ~NotificationDelegate() = default;
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_NOTIFICATION_DELEGATE_H_
diff --git a/buffet/notification/notification_parser.cc b/buffet/notification/notification_parser.cc
deleted file mode 100644
index 8cde3fa..0000000
--- a/buffet/notification/notification_parser.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/notification_parser.h"
-
-#include <base/logging.h>
-
-namespace buffet {
-
-namespace {
-
-// Processes COMMAND_CREATED notifications.
-bool ParseCommandCreated(const base::DictionaryValue& notification,
- NotificationDelegate* delegate) {
- const base::DictionaryValue* command = nullptr;
- if (!notification.GetDictionary("command", &command)) {
- LOG(ERROR) << "COMMAND_CREATED notification is missing 'command' property";
- return false;
- }
-
- delegate->OnCommandCreated(*command);
- return true;
-}
-
-// Processes DEVICE_DELETED notifications.
-bool ParseDeviceDeleted(const base::DictionaryValue& notification,
- NotificationDelegate* delegate) {
- std::string device_id;
- if (!notification.GetString("deviceId", &device_id)) {
- LOG(ERROR) << "DEVICE_DELETED notification is missing 'deviceId' property";
- return false;
- }
-
- delegate->OnDeviceDeleted(device_id);
- return true;
-}
-
-} // anonymous namespace
-
-bool ParseNotificationJson(const base::DictionaryValue& notification,
- NotificationDelegate* delegate) {
- CHECK(delegate);
-
- std::string kind;
- if (!notification.GetString("kind", &kind) ||
- kind != "clouddevices#notification") {
- LOG(WARNING) << "Push notification should have 'kind' property set to "
- "clouddevices#notification";
- return false;
- }
-
- std::string type;
- if (!notification.GetString("type", &type)) {
- LOG(WARNING) << "Push notification should have 'type' property";
- return false;
- }
-
- if (type == "COMMAND_CREATED")
- return ParseCommandCreated(notification, delegate);
-
- if (type == "DEVICE_DELETED")
- return ParseDeviceDeleted(notification, delegate);
-
- // Here we ignore other types of notifications for now.
- LOG(INFO) << "Ignoring push notification of type " << type;
- return true;
-}
-
-
-} // namespace buffet
diff --git a/buffet/notification/notification_parser.h b/buffet/notification/notification_parser.h
deleted file mode 100644
index eb50dc1..0000000
--- a/buffet/notification/notification_parser.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_NOTIFICATION_PARSER_H_
-#define BUFFET_NOTIFICATION_NOTIFICATION_PARSER_H_
-
-#include <string>
-
-#include <base/values.h>
-
-#include "buffet/notification/notification_delegate.h"
-
-namespace buffet {
-
-// Parses the notification JSON object received from GCD server and invokes
-// the appropriate method from the |delegate|.
-// Returns false if unexpected or malformed notification is received.
-bool ParseNotificationJson(const base::DictionaryValue& notification,
- NotificationDelegate* delegate);
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_NOTIFICATION_PARSER_H_
diff --git a/buffet/notification/notification_parser_unittest.cc b/buffet/notification/notification_parser_unittest.cc
deleted file mode 100644
index d578b55..0000000
--- a/buffet/notification/notification_parser_unittest.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/notification_parser.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/unittest_utils.h"
-
-using testing::SaveArg;
-using testing::Invoke;
-using testing::_;
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-
-class MockNotificationDelegate : public NotificationDelegate {
- public:
- MOCK_METHOD1(OnConnected, void(const std::string&));
- MOCK_METHOD0(OnDisconnected, void());
- MOCK_METHOD0(OnPermanentFailure, void());
- MOCK_METHOD1(OnCommandCreated, void(const base::DictionaryValue& command));
- MOCK_METHOD1(OnDeviceDeleted, void(const std::string&));
-};
-
-class NotificationParserTest : public ::testing::Test {
- protected:
- testing::StrictMock<MockNotificationDelegate> delegate_;
-};
-
-TEST_F(NotificationParserTest, CommandCreated) {
- auto json = CreateDictionaryValue(R"({
- "kind": "clouddevices#notification",
- "type": "COMMAND_CREATED",
- "deviceId": "device_id",
- "command": {
- "kind": "clouddevices#command",
- "deviceId": "device_id",
- "state": "queued",
- "name": "storage.list",
- "parameters": {
- "path": "/somepath1"
- },
- "expirationTimeMs": "1406036174811",
- "id": "command_id",
- "creationTimeMs": "1403444174811"
- },
- "commandId": "command_id"
- })");
-
- base::DictionaryValue command_instance;
- auto on_command = [&command_instance](const base::DictionaryValue& command) {
- command_instance.MergeDictionary(&command);
- };
-
- EXPECT_CALL(delegate_, OnCommandCreated(_)).WillOnce(Invoke(on_command));
- EXPECT_TRUE(ParseNotificationJson(*json, &delegate_));
-
- const char expected_json[] = R"({
- "kind": "clouddevices#command",
- "deviceId": "device_id",
- "state": "queued",
- "name": "storage.list",
- "parameters": {
- "path": "/somepath1"
- },
- "expirationTimeMs": "1406036174811",
- "id": "command_id",
- "creationTimeMs": "1403444174811"
- })";
- EXPECT_JSON_EQ(expected_json, command_instance);
-}
-
-TEST_F(NotificationParserTest, DeviceDeleted) {
- auto json = CreateDictionaryValue(R"({
- "kind":"clouddevices#notification",
- "type":"DEVICE_DELETED",
- "deviceId":"some_device_id"
- })");
-
- std::string device_id;
- EXPECT_CALL(delegate_, OnDeviceDeleted(_)).WillOnce(SaveArg<0>(&device_id));
- EXPECT_TRUE(ParseNotificationJson(*json, &delegate_));
- EXPECT_EQ("some_device_id", device_id);
-}
-
-TEST_F(NotificationParserTest, Failure_NoKind) {
- auto json = CreateDictionaryValue(R"({
- "type": "COMMAND_CREATED",
- "deviceId": "device_id",
- "command": {
- "kind": "clouddevices#command",
- "deviceId": "device_id",
- "state": "queued",
- "name": "storage.list",
- "parameters": {
- "path": "/somepath1"
- },
- "expirationTimeMs": "1406036174811",
- "id": "command_id",
- "creationTimeMs": "1403444174811"
- },
- "commandId": "command_id"
- })");
-
- EXPECT_FALSE(ParseNotificationJson(*json, &delegate_));
-}
-
-TEST_F(NotificationParserTest, Failure_NoType) {
- auto json = CreateDictionaryValue(R"({
- "kind": "clouddevices#notification",
- "deviceId": "device_id",
- "command": {
- "kind": "clouddevices#command",
- "deviceId": "device_id",
- "state": "queued",
- "name": "storage.list",
- "parameters": {
- "path": "/somepath1"
- },
- "expirationTimeMs": "1406036174811",
- "id": "command_id",
- "creationTimeMs": "1403444174811"
- },
- "commandId": "command_id"
- })");
-
- EXPECT_FALSE(ParseNotificationJson(*json, &delegate_));
-}
-
-TEST_F(NotificationParserTest, IgnoredNotificationType) {
- auto json = CreateDictionaryValue(R"({
- "kind": "clouddevices#notification",
- "type": "COMMAND_EXPIRED",
- "deviceId": "device_id",
- "command": {
- "kind": "clouddevices#command",
- "deviceId": "device_id",
- "state": "queued",
- "name": "storage.list",
- "parameters": {
- "path": "/somepath1"
- },
- "expirationTimeMs": "1406036174811",
- "id": "command_id",
- "creationTimeMs": "1403444174811"
- },
- "commandId": "command_id"
- })");
-
- EXPECT_TRUE(ParseNotificationJson(*json, &delegate_));
-}
-
-} // namespace buffet
diff --git a/buffet/notification/pull_channel.cc b/buffet/notification/pull_channel.cc
deleted file mode 100644
index 3172645..0000000
--- a/buffet/notification/pull_channel.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/pull_channel.h"
-
-#include <base/bind.h>
-
-#include "buffet/notification/notification_delegate.h"
-
-namespace buffet {
-
-PullChannel::PullChannel(
- base::TimeDelta pull_interval,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
- : pull_interval_{pull_interval},
- timer_{true, true} {
- timer_.SetTaskRunner(task_runner);
-}
-
-std::string PullChannel::GetName() const {
- return "pull";
-}
-
-bool PullChannel::IsConnected() const { return true; }
-
-void PullChannel::AddChannelParameters(base::DictionaryValue* channel_json) {
- // No extra parameters needed for "Pull" channel.
-}
-
-void PullChannel::Start(NotificationDelegate* delegate) {
- CHECK(delegate);
- delegate_ = delegate;
- timer_.Start(FROM_HERE, pull_interval_,
- base::Bind(&PullChannel::OnTimer,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void PullChannel::Stop() {
- weak_ptr_factory_.InvalidateWeakPtrs();
- timer_.Stop();
-}
-
-void PullChannel::UpdatePullInterval(base::TimeDelta pull_interval) {
- timer_.Stop();
- pull_interval_ = pull_interval;
- Start(delegate_);
-}
-
-void PullChannel::OnTimer() {
- base::DictionaryValue empty_dict;
- delegate_->OnCommandCreated(empty_dict);
-}
-
-} // namespace buffet
diff --git a/buffet/notification/pull_channel.h b/buffet/notification/pull_channel.h
deleted file mode 100644
index d1b993c..0000000
--- a/buffet/notification/pull_channel.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_PULL_CHANNEL_H_
-#define BUFFET_NOTIFICATION_PULL_CHANNEL_H_
-
-#include <memory>
-#include <string>
-
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-#include <base/single_thread_task_runner.h>
-#include <base/timer/timer.h>
-
-#include "buffet/notification/notification_channel.h"
-
-namespace buffet {
-
-class PullChannel : public NotificationChannel {
- public:
- PullChannel(base::TimeDelta pull_interval,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
- ~PullChannel() override = default;
-
- // Overrides from NotificationChannel.
- std::string GetName() const override;
- bool IsConnected() const override;
- void AddChannelParameters(base::DictionaryValue* channel_json) override;
- void Start(NotificationDelegate* delegate) override;
- void Stop() override;
-
- void UpdatePullInterval(base::TimeDelta pull_interval);
-
- private:
- void OnTimer();
-
- NotificationDelegate* delegate_{nullptr};
- base::TimeDelta pull_interval_;
- base::Timer timer_;
-
- base::WeakPtrFactory<PullChannel> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(PullChannel);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_PULL_CHANNEL_H_
diff --git a/buffet/notification/xml_node.cc b/buffet/notification/xml_node.cc
deleted file mode 100644
index f244c3a..0000000
--- a/buffet/notification/xml_node.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xml_node.h"
-
-#include <base/strings/stringprintf.h>
-#include <chromeos/strings/string_utils.h>
-
-namespace buffet {
-
-XmlNode::XmlNode(const std::string& name,
- std::map<std::string, std::string> attributes)
- : name_{name}, attributes_{std::move(attributes)} {}
-
-const std::string& XmlNode::name() const {
- return name_;
-}
-
-const std::string& XmlNode::text() const {
- return text_;
-}
-
-const std::map<std::string, std::string>& XmlNode::attributes() const {
- return attributes_;
-}
-
-const std::vector<std::unique_ptr<XmlNode>>& XmlNode::children() const {
- return children_;
-}
-
-bool XmlNode::GetAttribute(const std::string& name, std::string* value) const {
- auto p = attributes_.find(name);
- if (p == attributes_.end())
- return false;
-
- *value = p->second;
- return true;
-}
-
-std::string XmlNode::GetAttributeOrEmpty(const std::string& name) const {
- std::string value;
- GetAttribute(name, &value);
- return value;
-}
-
-const XmlNode* XmlNode::FindFirstChild(const std::string& name_path,
- bool recursive) const {
- return FindChildHelper(name_path, recursive, nullptr);
-}
-
-std::vector<const XmlNode*> XmlNode::FindChildren(const std::string& name_path,
- bool recursive) const {
- std::vector<const XmlNode*> children;
- FindChildHelper(name_path, recursive, &children);
- return children;
-}
-
-const XmlNode* XmlNode::FindChildHelper(
- const std::string& name_path,
- bool recursive,
- std::vector<const XmlNode*>* children) const {
- std::string name;
- std::string rest_of_path;
- chromeos::string_utils::SplitAtFirst(name_path, "/", &name, &rest_of_path,
- false);
- for (const auto& child : children_) {
- const XmlNode* found_node = nullptr;
- if (child->name() == name) {
- if (rest_of_path.empty()) {
- found_node = child.get();
- } else {
- found_node = child->FindChildHelper(rest_of_path, false, children);
- }
- } else if (recursive) {
- found_node = child->FindChildHelper(name_path, true, children);
- }
-
- if (found_node) {
- if (!children)
- return found_node;
- children->push_back(found_node);
- }
- }
- return nullptr;
-}
-
-void XmlNode::SetText(const std::string& text) {
- text_ = text;
-}
-
-void XmlNode::AppendText(const std::string& text) {
- text_ += text;
-}
-
-void XmlNode::AddChild(std::unique_ptr<XmlNode> child) {
- child->parent_ = this;
- children_.push_back(std::move(child));
-}
-
-std::string XmlNode::ToString() const {
- std::string xml = base::StringPrintf("<%s", name_.c_str());
- for (const auto& pair : attributes_) {
- base::StringAppendF(&xml, " %s=\"%s\"", pair.first.c_str(),
- pair.second.c_str());
- }
- if (text_.empty() && children_.empty()) {
- xml += "/>";
- } else {
- xml += '>';
- if (!text_.empty()) {
- xml += text_;
- }
- for (const auto& child : children_) {
- xml += child->ToString();
- }
- base::StringAppendF(&xml, "</%s>", name_.c_str());
- }
- return xml;
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xml_node.h b/buffet/notification/xml_node.h
deleted file mode 100644
index fc43650..0000000
--- a/buffet/notification/xml_node.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_XML_NODE_H_
-#define BUFFET_NOTIFICATION_XML_NODE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-
-namespace buffet {
-
-class XmlNodeTest;
-class XmppStreamParser;
-
-// XmlNode is a very simple class to represent the XML document element tree.
-// It is used in conjunction with expat XML parser to implement XmppStreamParser
-// class used to parse Xmpp data stream into individual stanzas.
-class XmlNode final {
- public:
- XmlNode(const std::string& name,
- std::map<std::string, std::string> attributes);
-
- // The node's name. E.g. in <foo bar="baz">quux</foo> this will return "foo".
- const std::string& name() const;
- // The node text content. E.g. in <foo bar="baz">quux</foo> this will return
- // "quux".
- const std::string& text() const;
- // The node attribute map. E.g. in <foo bar="baz">quux</foo> this will return
- // {{"bar", "baz"}}.
- const std::map<std::string, std::string>& attributes() const;
- // Returns the list of child nodes, if any.
- const std::vector<std::unique_ptr<XmlNode>>& children() const;
-
- // Retrieves the value of the given attribute specified by |name|.
- // If the attribute doesn't exist, returns false and |value| is not modified.
- bool GetAttribute(const std::string& name, std::string* value) const;
- // Returns the value of the given attribute specified by |name|.
- // Returns empty string if the attribute does not exist. This method should be
- // used only in limited scopes such as unit tests.
- std::string GetAttributeOrEmpty(const std::string& name) const;
-
- // Finds a first occurrence of a child node specified by |name_path|. A name
- // path is a "/"-separated list of node names to look for. If |recursive| is
- // set to true, the children are recursively traversed trying to match the
- // node names. Otherwise only first-level children of the current node are
- // matched against the top-level name of |name_path|.
- // This method returns a pointer to the first node that matches the path,
- // otherwise a nullptr is returned.
- const XmlNode* FindFirstChild(const std::string& name_path,
- bool recursive) const;
-
- // Finds all the child nodes matching the |name_path|. This returns the list
- // of pointers to the child nodes matching the criteria. If |recursive| is
- // set to true, the children are recursively traversed trying to match the
- // node names. Otherwise only first-level children of the current node are
- // matched against the top-level name of |name_path|.
- // For example, if the current node represents the <top> element of the
- // following XML document:
- // <top>
- // <node1 id="1"><node2 id="2"><node3 id="3"/></node2></node1>
- // <node2 id="4"><node3 id="5"/></node2>
- // <node3 id="6"/>
- // <node2 id="7"><node4 id="8"><node3 id="9"/></node4></node2>
- // </top>
- // Then recursively searching for nodes will produce the following results
- // (only the node "id" attributes are listed in the results, for brevity):
- // FindChildren("node2/node3", false) -> {"5"}.
- // FindChildren("node2/node3", true) -> {"3", "5"}.
- // FindChildren("node3", false) -> {"6"}.
- // FindChildren("node3", true) -> {"3", "5", "6", "9"}.
- std::vector<const XmlNode*> FindChildren(const std::string& name_path,
- bool recursive) const;
-
- // Adds a new child to the bottom of the child list of this node.
- void AddChild(std::unique_ptr<XmlNode> child);
-
- // Converts the node tree to XML-like string. Note that this not necessarily
- // produces a valid XML string. It does not use any character escaping or
- // canonicalization, which will produce invalid XML if any of the node or
- // attribute names or values contain special characters such as ", <, >, etc.
- // This function should be used only for logging/debugging purposes only and
- // never to generate valid XML from the parsed node tree.
- std::string ToString() const;
-
- private:
- friend class XmlNodeTest;
- friend class XmppStreamParser;
-
- // Sets the node's text. Used by XML parser.
- void SetText(const std::string& text);
- // Appends the |text| to the node's text string.
- void AppendText(const std::string& text);
-
- // Helper method used by FindFirstChild() and FindChildren(). Searches for
- // child node(s) matching |name_path|.
- // If |children| is not specified (nullptr), this function find the first
- // matching node and returns it via return value of the function. If no match
- // is found, this function will return nullptr.
- // If |children| parameter is not nullptr, found nodes are added to the
- // vector pointed to by |children| and search continues until the whole tree
- // is inspected. In this mode, the function always returns nullptr.
- const XmlNode* FindChildHelper(const std::string& name_path,
- bool recursive,
- std::vector<const XmlNode*>* children) const;
-
-
- const XmlNode* parent_{nullptr}; // Weak pointer to the parent node, if any.
- std::string name_;
- std::string text_;
- std::map<std::string, std::string> attributes_;
- std::vector<std::unique_ptr<XmlNode>> children_;
-
- DISALLOW_COPY_AND_ASSIGN(XmlNode);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_XML_NODE_H_
-
diff --git a/buffet/notification/xml_node_unittest.cc b/buffet/notification/xml_node_unittest.cc
deleted file mode 100644
index 8b2ed5c..0000000
--- a/buffet/notification/xml_node_unittest.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xml_node.h"
-
-#include <memory>
-
-#include <gtest/gtest.h>
-
-#include "buffet/notification/xmpp_stream_parser.h"
-
-namespace buffet {
-namespace {
-
-class XmlParser : public XmppStreamParser::Delegate {
- public:
- std::unique_ptr<XmlNode> Parse(const std::string& xml) {
- parser_.ParseData(xml);
- return std::move(node_);
- }
-
- private:
- // Overrides from XmppStreamParser::Delegate.
- void OnStreamStart(const std::string& node_name,
- std::map<std::string, std::string> attributes) override {
- node_.reset(new XmlNode{node_name, std::move(attributes)});
- }
-
- void OnStreamEnd(const std::string& node_name) override {}
-
- void OnStanza(std::unique_ptr<XmlNode> stanza) override {
- node_->AddChild(std::move(stanza));
- }
-
- std::unique_ptr<XmlNode> node_;
- XmppStreamParser parser_{this};
-};
-
-} // anonymous namespace
-
-class XmlNodeTest : public testing::Test {
- public:
- void SetUp() override {
- node_.reset(new XmlNode{"test_node",
- {{"attr1", "val1"}, {"attr2", "val2"}}});
- }
-
- // Accessor helpers for private members of XmlNode.
- static const XmlNode* GetParent(const XmlNode& node) {
- return node.parent_;
- }
-
- static void SetText(XmlNode* node, const std::string& text) {
- node->SetText(text);
- }
-
- static void AppendText(XmlNode* node, const std::string& text) {
- node->AppendText(text);
- }
-
- void CreateNodeTree() {
- node_ = XmlParser{}.Parse(R"(
- <top>
- <node1 id="1"><node2 id="2"><node3 id="3"/></node2></node1>
- <node2 id="4"><node3 id="5"/></node2>
- <node3 id="6"/>
- <node2 id="7"><node4 id="8"><node3 id="9"/></node4></node2>
- </top>
- )");
- }
-
- std::unique_ptr<XmlNode> node_;
-};
-
-TEST_F(XmlNodeTest, DefaultConstruction) {
- EXPECT_EQ("test_node", node_->name());
- EXPECT_TRUE(node_->children().empty());
- EXPECT_TRUE(node_->text().empty());
-}
-
-TEST_F(XmlNodeTest, SetText) {
- SetText(node_.get(), "foobar");
- EXPECT_EQ("foobar", node_->text());
-}
-
-TEST_F(XmlNodeTest, AppendText) {
- SetText(node_.get(), "foobar");
- AppendText(node_.get(), "-baz");
- EXPECT_EQ("foobar-baz", node_->text());
-}
-
-TEST_F(XmlNodeTest, AddChild) {
- std::unique_ptr<XmlNode> child{new XmlNode{"child", {}}};
- node_->AddChild(std::move(child));
- EXPECT_EQ(1u, node_->children().size());
- EXPECT_EQ("child", node_->children().front()->name());
- EXPECT_EQ(node_.get(), GetParent(*node_->children().front().get()));
-}
-
-TEST_F(XmlNodeTest, Attributes) {
- const std::map<std::string, std::string> expected_attrs{
- {"attr1", "val1"},
- {"attr2", "val2"}
- };
- EXPECT_EQ(expected_attrs, node_->attributes());
- std::string attr = "bar";
- EXPECT_FALSE(node_->GetAttribute("foo", &attr));
- EXPECT_EQ("bar", attr); // Shouldn't be changed by failed GetAttribute().
- EXPECT_TRUE(node_->GetAttribute("attr1", &attr));
- EXPECT_EQ("val1", attr);
- EXPECT_TRUE(node_->GetAttribute("attr2", &attr));
- EXPECT_EQ("val2", attr);
-
- XmlNode new_node{"node", {}};
- EXPECT_FALSE(new_node.GetAttribute("attr1", &attr));
-}
-
-TEST_F(XmlNodeTest, FindFirstChild_SingleNode) {
- CreateNodeTree();
- const XmlNode* node = node_->FindFirstChild("node3", false);
- ASSERT_NE(nullptr, node);
- EXPECT_EQ("node3", node->name());
- EXPECT_EQ("6", node->GetAttributeOrEmpty("id"));
-
- node = node_->FindFirstChild("node3", true);
- ASSERT_NE(nullptr, node);
- EXPECT_EQ("node3", node->name());
- EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));
-
- node = node_->FindFirstChild("foo", true);
- ASSERT_EQ(nullptr, node);
-}
-
-TEST_F(XmlNodeTest, FindFirstChild_Path) {
- CreateNodeTree();
- const XmlNode* node = node_->FindFirstChild("node2/node3", false);
- ASSERT_NE(nullptr, node);
- EXPECT_EQ("node3", node->name());
- EXPECT_EQ("5", node->GetAttributeOrEmpty("id"));
-
- node = node_->FindFirstChild("node2/node3", true);
- ASSERT_NE(nullptr, node);
- EXPECT_EQ("node3", node->name());
- EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));
-
- node = node_->FindFirstChild("node1/node2/node3", false);
- ASSERT_NE(nullptr, node);
- EXPECT_EQ("node3", node->name());
- EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));
-
- node = node_->FindFirstChild("node1/node2/node3", true);
- ASSERT_NE(nullptr, node);
- EXPECT_EQ("node3", node->name());
- EXPECT_EQ("3", node->GetAttributeOrEmpty("id"));
-
- node = node_->FindFirstChild("foo/node3", true);
- ASSERT_EQ(nullptr, node);
-}
-
-TEST_F(XmlNodeTest, FindChildren_SingleNode) {
- CreateNodeTree();
- auto children = node_->FindChildren("node3", false);
- ASSERT_EQ(1u, children.size());
- EXPECT_EQ("node3", children[0]->name());
- EXPECT_EQ("6", children[0]->GetAttributeOrEmpty("id"));
-
- children = node_->FindChildren("node3", true);
- ASSERT_EQ(4u, children.size());
- EXPECT_EQ("node3", children[0]->name());
- EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));
- EXPECT_EQ("node3", children[1]->name());
- EXPECT_EQ("5", children[1]->GetAttributeOrEmpty("id"));
- EXPECT_EQ("node3", children[2]->name());
- EXPECT_EQ("6", children[2]->GetAttributeOrEmpty("id"));
- EXPECT_EQ("node3", children[3]->name());
- EXPECT_EQ("9", children[3]->GetAttributeOrEmpty("id"));
-}
-
-TEST_F(XmlNodeTest, FindChildren_Path) {
- CreateNodeTree();
- auto children = node_->FindChildren("node2/node3", false);
- ASSERT_EQ(1u, children.size());
- EXPECT_EQ("node3", children[0]->name());
- EXPECT_EQ("5", children[0]->GetAttributeOrEmpty("id"));
-
- children = node_->FindChildren("node2/node3", true);
- ASSERT_EQ(2u, children.size());
- EXPECT_EQ("node3", children[0]->name());
- EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));
- EXPECT_EQ("node3", children[1]->name());
- EXPECT_EQ("5", children[1]->GetAttributeOrEmpty("id"));
-
- children = node_->FindChildren("node1/node2/node3", false);
- ASSERT_EQ(1u, children.size());
- EXPECT_EQ("node3", children[0]->name());
- EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));
-
- children = node_->FindChildren("node1/node2/node3", true);
- ASSERT_EQ(1u, children.size());
- EXPECT_EQ("node3", children[0]->name());
- EXPECT_EQ("3", children[0]->GetAttributeOrEmpty("id"));
-
- children = node_->FindChildren("foo/bar", false);
- ASSERT_EQ(0u, children.size());
-
- children = node_->FindChildren("node2/baz", false);
- ASSERT_EQ(0u, children.size());
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xmpp_channel.cc b/buffet/notification/xmpp_channel.cc
deleted file mode 100644
index bf9e0b9..0000000
--- a/buffet/notification/xmpp_channel.cc
+++ /dev/null
@@ -1,526 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xmpp_channel.h"
-
-#include <string>
-
-#include <base/bind.h>
-#include <chromeos/backoff_entry.h>
-#include <chromeos/data_encoding.h>
-#include <chromeos/streams/file_stream.h>
-#include <chromeos/streams/tls_stream.h>
-
-#include "buffet/notification/notification_delegate.h"
-#include "buffet/notification/notification_parser.h"
-#include "buffet/notification/xml_node.h"
-#include "buffet/privet/shill_client.h"
-#include "buffet/utils.h"
-
-namespace buffet {
-
-namespace {
-
-std::string BuildXmppStartStreamCommand() {
- return "<stream:stream to='clouddevices.gserviceaccount.com' "
- "xmlns:stream='http://etherx.jabber.org/streams' "
- "xml:lang='*' version='1.0' xmlns='jabber:client'>";
-}
-
-std::string BuildXmppAuthenticateCommand(
- const std::string& account, const std::string& token) {
- chromeos::Blob credentials;
- credentials.push_back(0);
- credentials.insert(credentials.end(), account.begin(), account.end());
- credentials.push_back(0);
- credentials.insert(credentials.end(), token.begin(), token.end());
- std::string msg = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' "
- "mechanism='X-OAUTH2' auth:service='oauth2' "
- "auth:allow-non-google-login='true' "
- "auth:client-uses-full-bind-result='true' "
- "xmlns:auth='http://www.google.com/talk/protocol/auth'>" +
- chromeos::data_encoding::Base64Encode(credentials) +
- "</auth>";
- return msg;
-}
-
-// Backoff policy.
-// Note: In order to ensure a minimum of 20 seconds between server errors,
-// we have a 30s +- 10s (33%) jitter initial backoff.
-const chromeos::BackoffEntry::Policy kDefaultBackoffPolicy = {
- // Number of initial errors (in sequence) to ignore before applying
- // exponential back-off rules.
- 0,
-
- // Initial delay for exponential back-off in ms.
- 30 * 1000, // 30 seconds.
-
- // Factor by which the waiting time will be multiplied.
- 2,
-
- // Fuzzing percentage. ex: 10% will spread requests randomly
- // between 90%-100% of the calculated time.
- 0.33, // 33%.
-
- // Maximum amount of time we are willing to delay our request in ms.
- 10 * 60 * 1000, // 10 minutes.
-
- // Time to keep an entry from being discarded even when it
- // has no significant state, -1 to never discard.
- -1,
-
- // Don't use initial delay unless the last request was an error.
- false,
-};
-
-const char kDefaultXmppHost[] = "talk.google.com";
-const uint16_t kDefaultXmppPort = 5222;
-
-// Used for keeping connection alive.
-const int kRegularPingIntervalSeconds = 60;
-const int kRegularPingTimeoutSeconds = 30;
-
-// Used for diagnostic when connectivity changed.
-const int kAgressivePingIntervalSeconds = 5;
-const int kAgressivePingTimeoutSeconds = 10;
-
-const int kConnectingTimeoutAfterNetChangeSeconds = 30;
-
-} // namespace
-
-XmppChannel::XmppChannel(
- const std::string& account,
- const std::string& access_token,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- privetd::ShillClient* shill)
- : account_{account},
- access_token_{access_token},
- backoff_entry_{&kDefaultBackoffPolicy},
- task_runner_{task_runner},
- iq_stanza_handler_{new IqStanzaHandler{this, task_runner}} {
- read_socket_data_.resize(4096);
- if (shill) {
- shill->RegisterConnectivityListener(base::Bind(
- &XmppChannel::OnConnectivityChanged, weak_ptr_factory_.GetWeakPtr()));
- }
-}
-
-void XmppChannel::OnMessageRead(size_t size) {
- std::string msg(read_socket_data_.data(), size);
- VLOG(2) << "Received XMPP packet: " << msg;
- read_pending_ = false;
- stream_parser_.ParseData(msg);
- WaitForMessage();
-}
-
-void XmppChannel::OnStreamStart(const std::string& node_name,
- std::map<std::string, std::string> attributes) {
- VLOG(2) << "XMPP stream start: " << node_name;
-}
-
-void XmppChannel::OnStreamEnd(const std::string& node_name) {
- VLOG(2) << "XMPP stream ended: " << node_name;
- Stop();
- if (IsConnected()) {
- // If we had a fully-established connection, restart it now.
- // However, if the connection has never been established yet (e.g.
- // authorization failed), do not restart right now. Wait till we get
- // new credentials.
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&XmppChannel::Restart, task_ptr_factory_.GetWeakPtr()));
- } else if (delegate_) {
- delegate_->OnPermanentFailure();
- }
-}
-
-void XmppChannel::OnStanza(std::unique_ptr<XmlNode> stanza) {
- // Handle stanza asynchronously, since XmppChannel::OnStanza() is a callback
- // from expat XML parser and some stanza could cause the XMPP stream to be
- // reset and the parser to be re-initialized. We don't want to destroy the
- // parser while it is performing a callback invocation.
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&XmppChannel::HandleStanza, task_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(stanza))));
-}
-
-void XmppChannel::HandleStanza(std::unique_ptr<XmlNode> stanza) {
- VLOG(2) << "XMPP stanza received: " << stanza->ToString();
-
- switch (state_) {
- case XmppState::kConnected:
- if (stanza->name() == "stream:features" &&
- stanza->FindFirstChild("starttls/required", false)) {
- state_ = XmppState::kTlsStarted;
- SendMessage("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
- return;
- }
- break;
- case XmppState::kTlsStarted:
- if (stanza->name() == "proceed") {
- StartTlsHandshake();
- return;
- }
- break;
- case XmppState::kTlsCompleted:
- if (stanza->name() == "stream:features") {
- auto children = stanza->FindChildren("mechanisms/mechanism", false);
- for (const auto& child : children) {
- if (child->text() == "X-OAUTH2") {
- state_ = XmppState::kAuthenticationStarted;
- SendMessage(BuildXmppAuthenticateCommand(account_, access_token_));
- return;
- }
- }
- }
- break;
- case XmppState::kAuthenticationStarted:
- if (stanza->name() == "success") {
- state_ = XmppState::kStreamRestartedPostAuthentication;
- RestartXmppStream();
- return;
- } else if (stanza->name() == "failure") {
- if (stanza->FindFirstChild("not-authorized", false)) {
- state_ = XmppState::kAuthenticationFailed;
- return;
- }
- }
- break;
- case XmppState::kStreamRestartedPostAuthentication:
- if (stanza->name() == "stream:features" &&
- stanza->FindFirstChild("bind", false)) {
- state_ = XmppState::kBindSent;
- iq_stanza_handler_->SendRequest(
- "set", "", "", "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>",
- base::Bind(&XmppChannel::OnBindCompleted,
- task_ptr_factory_.GetWeakPtr()),
- base::Bind(&XmppChannel::Restart, task_ptr_factory_.GetWeakPtr()));
- return;
- }
- break;
- default:
- if (stanza->name() == "message") {
- HandleMessageStanza(std::move(stanza));
- return;
- } else if (stanza->name() == "iq") {
- if (!iq_stanza_handler_->HandleIqStanza(std::move(stanza))) {
- LOG(ERROR) << "Failed to handle IQ stanza";
- CloseStream();
- }
- return;
- }
- LOG(INFO) << "Unexpected XMPP stanza ignored: " << stanza->ToString();
- return;
- }
- // Something bad happened. Close the stream and start over.
- LOG(ERROR) << "Error condition occurred handling stanza: "
- << stanza->ToString();
- CloseStream();
-}
-
-void XmppChannel::CloseStream() {
- SendMessage("</stream:stream>");
-}
-
-void XmppChannel::OnBindCompleted(std::unique_ptr<XmlNode> reply) {
- if (reply->GetAttributeOrEmpty("type") != "result") {
- CloseStream();
- return;
- }
- const XmlNode* jid_node = reply->FindFirstChild("bind/jid", false);
- if (!jid_node) {
- LOG(ERROR) << "XMPP Bind response is missing JID";
- CloseStream();
- return;
- }
-
- jid_ = jid_node->text();
- state_ = XmppState::kSessionStarted;
- iq_stanza_handler_->SendRequest(
- "set", "", "", "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>",
- base::Bind(&XmppChannel::OnSessionEstablished,
- task_ptr_factory_.GetWeakPtr()),
- base::Bind(&XmppChannel::Restart, task_ptr_factory_.GetWeakPtr()));
-}
-
-void XmppChannel::OnSessionEstablished(std::unique_ptr<XmlNode> reply) {
- if (reply->GetAttributeOrEmpty("type") != "result") {
- CloseStream();
- return;
- }
- state_ = XmppState::kSubscribeStarted;
- std::string body = "<subscribe xmlns='google:push'>"
- "<item channel='cloud_devices' from=''/></subscribe>";
- iq_stanza_handler_->SendRequest(
- "set", "", account_, body,
- base::Bind(&XmppChannel::OnSubscribed, task_ptr_factory_.GetWeakPtr()),
- base::Bind(&XmppChannel::Restart, task_ptr_factory_.GetWeakPtr()));
-}
-
-void XmppChannel::OnSubscribed(std::unique_ptr<XmlNode> reply) {
- if (reply->GetAttributeOrEmpty("type") != "result") {
- CloseStream();
- return;
- }
- state_ = XmppState::kSubscribed;
- if (delegate_)
- delegate_->OnConnected(GetName());
-}
-
-void XmppChannel::HandleMessageStanza(std::unique_ptr<XmlNode> stanza) {
- const XmlNode* node = stanza->FindFirstChild("push:push/push:data", true);
- if (!node) {
- LOG(WARNING) << "XMPP message stanza is missing <push:data> element";
- return;
- }
- std::string data = node->text();
- std::string json_data;
- if (!chromeos::data_encoding::Base64Decode(data, &json_data)) {
- LOG(WARNING) << "Failed to decode base64-encoded message payload: " << data;
- return;
- }
-
- VLOG(2) << "XMPP push notification data: " << json_data;
- auto json_dict = LoadJsonDict(json_data, nullptr);
- if (json_dict && delegate_)
- ParseNotificationJson(*json_dict, delegate_);
-}
-
-void XmppChannel::StartTlsHandshake() {
- stream_->CancelPendingAsyncOperations();
- chromeos::TlsStream::Connect(
- std::move(raw_socket_), host_,
- base::Bind(&XmppChannel::OnTlsHandshakeComplete,
- task_ptr_factory_.GetWeakPtr()),
- base::Bind(&XmppChannel::OnTlsError, task_ptr_factory_.GetWeakPtr()));
-}
-
-void XmppChannel::OnTlsHandshakeComplete(chromeos::StreamPtr tls_stream) {
- tls_stream_ = std::move(tls_stream);
- stream_ = tls_stream_.get();
- state_ = XmppState::kTlsCompleted;
- RestartXmppStream();
-}
-
-void XmppChannel::OnTlsError(const chromeos::Error* error) {
- LOG(ERROR) << "TLS handshake failed. Restarting XMPP connection";
- Restart();
-}
-
-void XmppChannel::SendMessage(const std::string& message) {
- if (write_pending_) {
- queued_write_data_ += message;
- return;
- }
- write_socket_data_ = queued_write_data_ + message;
- queued_write_data_.clear();
- chromeos::ErrorPtr error;
- VLOG(2) << "Sending XMPP message: " << message;
-
- write_pending_ = true;
- bool ok = stream_->WriteAllAsync(
- write_socket_data_.data(), write_socket_data_.size(),
- base::Bind(&XmppChannel::OnMessageSent, task_ptr_factory_.GetWeakPtr()),
- base::Bind(&XmppChannel::OnWriteError, task_ptr_factory_.GetWeakPtr()),
- &error);
-
- if (!ok)
- OnWriteError(error.get());
-}
-
-void XmppChannel::OnMessageSent() {
- chromeos::ErrorPtr error;
- write_pending_ = false;
- if (!stream_->FlushBlocking(&error)) {
- OnWriteError(error.get());
- return;
- }
- if (queued_write_data_.empty()) {
- WaitForMessage();
- } else {
- SendMessage(std::string{});
- }
-}
-
-void XmppChannel::WaitForMessage() {
- if (read_pending_ || !stream_)
- return;
-
- chromeos::ErrorPtr error;
- read_pending_ = true;
- bool ok = stream_->ReadAsync(
- read_socket_data_.data(), read_socket_data_.size(),
- base::Bind(&XmppChannel::OnMessageRead, task_ptr_factory_.GetWeakPtr()),
- base::Bind(&XmppChannel::OnReadError, task_ptr_factory_.GetWeakPtr()),
- &error);
-
- if (!ok)
- OnReadError(error.get());
-}
-
-void XmppChannel::OnReadError(const chromeos::Error* error) {
- read_pending_ = false;
- Restart();
-}
-
-void XmppChannel::OnWriteError(const chromeos::Error* error) {
- write_pending_ = false;
- Restart();
-}
-
-void XmppChannel::Connect(const std::string& host, uint16_t port,
- const base::Closure& callback) {
- state_ = XmppState::kConnecting;
- LOG(INFO) << "Starting XMPP connection to " << host << ":" << port;
- int socket_fd = ConnectSocket(host, port);
- if (socket_fd >= 0) {
- raw_socket_ =
- chromeos::FileStream::FromFileDescriptor(socket_fd, true, nullptr);
- if (!raw_socket_) {
- close(socket_fd);
- socket_fd = -1;
- }
- }
-
- backoff_entry_.InformOfRequest(raw_socket_ != nullptr);
- if (raw_socket_) {
- host_ = host;
- port_ = port;
- stream_ = raw_socket_.get();
- callback.Run();
- } else {
- VLOG(1) << "Delaying connection to XMPP server " << host << " for "
- << backoff_entry_.GetTimeUntilRelease();
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&XmppChannel::Connect, task_ptr_factory_.GetWeakPtr(), host,
- port, callback),
- backoff_entry_.GetTimeUntilRelease());
- }
-}
-
-std::string XmppChannel::GetName() const {
- return "xmpp";
-}
-
-bool XmppChannel::IsConnected() const {
- return state_ == XmppState::kSubscribed;
-}
-
-void XmppChannel::AddChannelParameters(base::DictionaryValue* channel_json) {
- // No extra parameters needed for XMPP.
-}
-
-void XmppChannel::Restart() {
- VLOG(1) << "Restarting XMPP";
- Stop();
- Start(delegate_);
-}
-
-void XmppChannel::Start(NotificationDelegate* delegate) {
- CHECK(state_ == XmppState::kNotStarted);
- delegate_ = delegate;
-
- Connect(
- kDefaultXmppHost, kDefaultXmppPort,
- base::Bind(&XmppChannel::OnConnected, task_ptr_factory_.GetWeakPtr()));
-}
-
-void XmppChannel::Stop() {
- if (IsConnected() && delegate_)
- delegate_->OnDisconnected();
-
- task_ptr_factory_.InvalidateWeakPtrs();
- ping_ptr_factory_.InvalidateWeakPtrs();
-
- if (tls_stream_) {
- tls_stream_->CloseBlocking(nullptr);
- tls_stream_.reset();
- }
- if (raw_socket_) {
- raw_socket_->CloseBlocking(nullptr);
- raw_socket_.reset();
- }
- stream_ = nullptr;
- state_ = XmppState::kNotStarted;
-}
-
-void XmppChannel::OnConnected() {
- CHECK(XmppState::kConnecting == state_);
- state_ = XmppState::kConnected;
- RestartXmppStream();
- ScheduleRegularPing();
-}
-
-void XmppChannel::RestartXmppStream() {
- stream_parser_.Reset();
- stream_->CancelPendingAsyncOperations();
- read_pending_ = false;
- write_pending_ = false;
- SendMessage(BuildXmppStartStreamCommand());
-}
-
-void XmppChannel::SchedulePing(base::TimeDelta interval,
- base::TimeDelta timeout) {
- VLOG(1) << "Next XMPP ping in " << interval << " with timeout " << timeout;
- ping_ptr_factory_.InvalidateWeakPtrs();
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&XmppChannel::PingServer,
- ping_ptr_factory_.GetWeakPtr(), timeout),
- interval);
-}
-
-void XmppChannel::ScheduleRegularPing() {
- SchedulePing(base::TimeDelta::FromSeconds(kRegularPingIntervalSeconds),
- base::TimeDelta::FromSeconds(kRegularPingTimeoutSeconds));
-}
-
-void XmppChannel::ScheduleFastPing() {
- SchedulePing(base::TimeDelta::FromSeconds(kAgressivePingIntervalSeconds),
- base::TimeDelta::FromSeconds(kAgressivePingTimeoutSeconds));
-}
-
-void XmppChannel::PingServer(base::TimeDelta timeout) {
- VLOG(1) << "Sending XMPP ping";
- // Send an XMPP Ping request as defined in XEP-0199 extension:
- // http://xmpp.org/extensions/xep-0199.html
- iq_stanza_handler_->SendRequestWithCustomTimeout(
- "get", jid_, account_, "<ping xmlns='urn:xmpp:ping'/>", timeout,
- base::Bind(&XmppChannel::OnPingResponse, task_ptr_factory_.GetWeakPtr(),
- base::Time::Now()),
- base::Bind(&XmppChannel::OnPingTimeout, task_ptr_factory_.GetWeakPtr(),
- base::Time::Now()));
-}
-
-void XmppChannel::OnPingResponse(base::Time sent_time,
- std::unique_ptr<XmlNode> reply) {
- VLOG(1) << "XMPP response received after " << (base::Time::Now() - sent_time);
- // Ping response received from server. Everything seems to be in order.
- // Reschedule with default intervals.
- ScheduleRegularPing();
-}
-
-void XmppChannel::OnPingTimeout(base::Time sent_time) {
- LOG(WARNING) << "XMPP channel seems to be disconnected. Ping timed out after "
- << (base::Time::Now() - sent_time);
- Restart();
-}
-
-void XmppChannel::OnConnectivityChanged(bool online) {
- if (state_ == XmppState::kNotStarted)
- return;
-
- if (state_ == XmppState::kConnecting &&
- backoff_entry_.GetTimeUntilRelease() <
- base::TimeDelta::FromSeconds(
- kConnectingTimeoutAfterNetChangeSeconds)) {
- VLOG(1) << "Next reconnect in " << backoff_entry_.GetTimeUntilRelease();
- return;
- }
-
- ScheduleFastPing();
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xmpp_channel.h b/buffet/notification/xmpp_channel.h
deleted file mode 100644
index 3d279e4..0000000
--- a/buffet/notification/xmpp_channel.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_XMPP_CHANNEL_H_
-#define BUFFET_NOTIFICATION_XMPP_CHANNEL_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/callback_forward.h>
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-#include <base/single_thread_task_runner.h>
-#include <chromeos/backoff_entry.h>
-#include <chromeos/streams/stream.h>
-
-#include "buffet/notification/notification_channel.h"
-#include "buffet/notification/xmpp_iq_stanza_handler.h"
-#include "buffet/notification/xmpp_stream_parser.h"
-
-namespace privetd {
-class ShillClient;
-}
-
-namespace buffet {
-
-// Simple interface to abstract XmppChannel's SendMessage() method.
-class XmppChannelInterface {
- public:
- virtual void SendMessage(const std::string& message) = 0;
-
- protected:
- virtual ~XmppChannelInterface() = default;
-};
-
-class XmppChannel : public NotificationChannel,
- public XmppStreamParser::Delegate,
- public XmppChannelInterface {
- public:
- // |account| is the robot account for buffet and |access_token|
- // it the OAuth token. Note that the OAuth token expires fairly frequently
- // so you will need to reset the XmppClient every time this happens.
- XmppChannel(const std::string& account,
- const std::string& access_token,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- privetd::ShillClient* shill);
- ~XmppChannel() override = default;
-
- // Overrides from NotificationChannel.
- std::string GetName() const override;
- bool IsConnected() const override;
- void AddChannelParameters(base::DictionaryValue* channel_json) override;
- void Start(NotificationDelegate* delegate) override;
- void Stop() override;
-
- const std::string& jid() const { return jid_; }
-
- // Internal states for the XMPP stream.
- enum class XmppState {
- kNotStarted,
- kConnecting,
- kConnected,
- kTlsStarted,
- kTlsCompleted,
- kAuthenticationStarted,
- kAuthenticationFailed,
- kStreamRestartedPostAuthentication,
- kBindSent,
- kSessionStarted,
- kSubscribeStarted,
- kSubscribed,
- };
-
- protected:
- // These methods are internal helpers that can be overloaded by unit tests
- // to help provide unit-test-specific functionality.
- virtual void Connect(const std::string& host, uint16_t port,
- const base::Closure& callback);
- virtual void SchedulePing(base::TimeDelta interval, base::TimeDelta timeout);
- void ScheduleRegularPing();
- void ScheduleFastPing();
-
- XmppState state_{XmppState::kNotStarted};
-
- // The connection socket stream to the XMPP server.
- chromeos::Stream* stream_{nullptr};
-
- private:
- friend class IqStanzaHandler;
-
- // Overrides from XmppStreamParser::Delegate.
- void OnStreamStart(const std::string& node_name,
- std::map<std::string, std::string> attributes) override;
- void OnStreamEnd(const std::string& node_name) override;
- void OnStanza(std::unique_ptr<XmlNode> stanza) override;
-
- // Overrides from XmppChannelInterface.
- void SendMessage(const std::string& message) override;
-
- void HandleStanza(std::unique_ptr<XmlNode> stanza);
- void HandleMessageStanza(std::unique_ptr<XmlNode> stanza);
- void RestartXmppStream();
-
- void StartTlsHandshake();
- void OnTlsHandshakeComplete(chromeos::StreamPtr tls_stream);
- void OnTlsError(const chromeos::Error* error);
-
- void WaitForMessage();
-
- void OnConnected();
- void OnMessageRead(size_t size);
- void OnMessageSent();
- void OnReadError(const chromeos::Error* error);
- void OnWriteError(const chromeos::Error* error);
- void Restart();
- void CloseStream();
-
- // XMPP connection state machine's state handlers.
- void OnBindCompleted(std::unique_ptr<XmlNode> reply);
- void OnSessionEstablished(std::unique_ptr<XmlNode> reply);
- void OnSubscribed(std::unique_ptr<XmlNode> reply);
-
- // Sends a ping request to the server to check if the connection is still
- // valid.
- void PingServer(base::TimeDelta timeout);
- void OnPingResponse(base::Time sent_time, std::unique_ptr<XmlNode> reply);
- void OnPingTimeout(base::Time sent_time);
-
- void OnConnectivityChanged(bool online);
-
- // Robot account name for the device.
- std::string account_;
-
- // Full JID of this device.
- std::string jid_;
-
- // OAuth access token for the account. Expires fairly frequently.
- std::string access_token_;
-
- chromeos::StreamPtr raw_socket_;
- chromeos::StreamPtr tls_stream_; // Must follow |raw_socket_|.
-
- // Read buffer for incoming message packets.
- std::vector<char> read_socket_data_;
- // Write buffer for outgoing message packets.
- std::string write_socket_data_;
- std::string queued_write_data_;
-
- // XMPP server name and port used for connection.
- std::string host_;
- uint16_t port_{0};
-
- chromeos::BackoffEntry backoff_entry_;
- NotificationDelegate* delegate_{nullptr};
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- XmppStreamParser stream_parser_{this};
- bool read_pending_{false};
- bool write_pending_{false};
- std::unique_ptr<IqStanzaHandler> iq_stanza_handler_;
-
- base::WeakPtrFactory<XmppChannel> ping_ptr_factory_{this};
- base::WeakPtrFactory<XmppChannel> task_ptr_factory_{this};
- base::WeakPtrFactory<XmppChannel> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(XmppChannel);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_XMPP_CHANNEL_H_
-
diff --git a/buffet/notification/xmpp_channel_unittest.cc b/buffet/notification/xmpp_channel_unittest.cc
deleted file mode 100644
index 80a9af8..0000000
--- a/buffet/notification/xmpp_channel_unittest.cc
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xmpp_channel.h"
-
-#include <queue>
-
-#include <base/test/simple_test_clock.h>
-#include <chromeos/bind_lambda.h>
-#include <chromeos/streams/fake_stream.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-namespace buffet {
-
-using ::testing::DoAll;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-using ::testing::_;
-
-namespace {
-
-constexpr char kAccountName[] = "Account@Name";
-constexpr char kAccessToken[] = "AccessToken";
-
-constexpr char kStartStreamResponse[] =
- "<stream:stream from=\"clouddevices.gserviceaccount.com\" "
- "id=\"0CCF520913ABA04B\" version=\"1.0\" "
- "xmlns:stream=\"http://etherx.jabber.org/streams\" "
- "xmlns=\"jabber:client\">"
- "<stream:features><starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">"
- "<required/></starttls><mechanisms "
- "xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><mechanism>X-OAUTH2</mechanism>"
- "<mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms></stream:features>";
-constexpr char kTlsStreamResponse[] =
- "<stream:features><mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
- "<mechanism>X-OAUTH2</mechanism>"
- "<mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms></stream:features>";
-constexpr char kAuthenticationSucceededResponse[] =
- "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>";
-constexpr char kAuthenticationFailedResponse[] =
- "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><not-authorized/>"
- "</failure>";
-constexpr char kRestartStreamResponse[] =
- "<stream:features><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
- "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
- "</stream:features>";
-constexpr char kBindResponse[] =
- "<iq id=\"1\" type=\"result\">"
- "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
- "<jid>110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
- "/19853128</jid></bind></iq>";
-constexpr char kSessionResponse[] =
- "<iq type=\"result\" id=\"2\"/>";
-constexpr char kSubscribedResponse[] =
- "<iq to=\""
- "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com/"
- "19853128\" from=\""
- "110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com\" "
- "id=\"3\" type=\"result\"/>";
-constexpr char kStartStreamMessage[] =
- "<stream:stream to='clouddevices.gserviceaccount.com' "
- "xmlns:stream='http://etherx.jabber.org/streams' xml:lang='*' "
- "version='1.0' xmlns='jabber:client'>";
-constexpr char kStartTlsMessage[] =
- "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
-constexpr char kAuthenticationMessage[] =
- "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-OAUTH2' "
- "auth:service='oauth2' auth:allow-non-google-login='true' "
- "auth:client-uses-full-bind-result='true' "
- "xmlns:auth='http://www.google.com/talk/protocol/auth'>"
- "AEFjY291bnRATmFtZQBBY2Nlc3NUb2tlbg==</auth>";
-constexpr char kBindMessage[] =
- "<iq id='1' type='set'><bind "
- "xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>";
-constexpr char kSessionMessage[] =
- "<iq id='2' type='set'><session "
- "xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>";
-constexpr char kSubscribeMessage[] =
- "<iq id='3' type='set' to='Account@Name'>"
- "<subscribe xmlns='google:push'><item channel='cloud_devices' from=''/>"
- "</subscribe></iq>";
-} // namespace
-
-// Mock-like task runner that allow the tests to inspect the calls to
-// TaskRunner::PostDelayedTask and verify the delays.
-class TestTaskRunner : public base::SingleThreadTaskRunner {
- public:
- MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&,
- const base::Closure&,
- base::TimeDelta));
- MOCK_METHOD3(PostNonNestableDelayedTask,
- bool(const tracked_objects::Location&,
- const base::Closure&,
- base::TimeDelta));
-
- bool RunsTasksOnCurrentThread() const { return true; }
-};
-
-class FakeXmppChannel : public XmppChannel {
- public:
- FakeXmppChannel(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- base::Clock* clock)
- : XmppChannel{kAccountName, kAccessToken, task_runner, nullptr},
- fake_stream_{chromeos::Stream::AccessMode::READ_WRITE, task_runner,
- clock} {}
-
- XmppState state() const { return state_; }
- void set_state(XmppState state) { state_ = state; }
-
- void Connect(const std::string& host, uint16_t port,
- const base::Closure& callback) override {
- set_state(XmppState::kConnecting);
- stream_ = &fake_stream_;
- callback.Run();
- }
-
- void SchedulePing(base::TimeDelta interval,
- base::TimeDelta timeout) override {}
-
- chromeos::FakeStream fake_stream_;
-};
-
-class XmppChannelTest : public ::testing::Test {
- protected:
- void SetUp() override {
- task_runner_ = new TestTaskRunner;
-
- auto callback = [this](const tracked_objects::Location& from_here,
- const base::Closure& task,
- base::TimeDelta delay) -> bool {
- if (ignore_delayed_tasks_ && delay > base::TimeDelta::FromMilliseconds(0))
- return true;
- clock_.Advance(delay);
- message_queue_.push(task);
- return true;
- };
-
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .WillRepeatedly(testing::Invoke(callback));
-
- xmpp_client_.reset(new FakeXmppChannel{task_runner_, &clock_});
- clock_.SetNow(base::Time::Now());
- }
-
- void StartStream() {
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kStartStreamMessage);
- xmpp_client_->fake_stream_.AddReadPacketString({}, kStartStreamResponse);
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kStartTlsMessage);
- xmpp_client_->Start(nullptr);
- RunTasks(4);
- }
-
- void StartWithState(XmppChannel::XmppState state) {
- StartStream();
- xmpp_client_->set_state(state);
- }
-
- void RunTasks(size_t count) {
- while (count > 0) {
- ASSERT_FALSE(message_queue_.empty());
- base::Closure task = message_queue_.front();
- message_queue_.pop();
- task.Run();
- count--;
- }
- }
-
- void SetIgnoreDelayedTasks(bool ignore) {
- ignore_delayed_tasks_ = true;
- }
-
- std::unique_ptr<FakeXmppChannel> xmpp_client_;
- base::SimpleTestClock clock_;
- scoped_refptr<TestTaskRunner> task_runner_;
- std::queue<base::Closure> message_queue_;
- bool ignore_delayed_tasks_{false};
-};
-
-TEST_F(XmppChannelTest, StartStream) {
- EXPECT_EQ(XmppChannel::XmppState::kNotStarted, xmpp_client_->state());
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kStartStreamMessage);
- xmpp_client_->Start(nullptr);
- RunTasks(1);
- EXPECT_EQ(XmppChannel::XmppState::kConnected, xmpp_client_->state());
-}
-
-TEST_F(XmppChannelTest, HandleStartedResponse) {
- StartStream();
- EXPECT_EQ(XmppChannel::XmppState::kTlsStarted, xmpp_client_->state());
-}
-
-TEST_F(XmppChannelTest, HandleTLSCompleted) {
- StartWithState(XmppChannel::XmppState::kTlsCompleted);
- xmpp_client_->fake_stream_.AddReadPacketString(
- {}, kTlsStreamResponse);
- xmpp_client_->fake_stream_.ExpectWritePacketString({},
- kAuthenticationMessage);
- RunTasks(4);
- EXPECT_EQ(XmppChannel::XmppState::kAuthenticationStarted,
- xmpp_client_->state());
-}
-
-TEST_F(XmppChannelTest, HandleAuthenticationSucceededResponse) {
- StartWithState(XmppChannel::XmppState::kAuthenticationStarted);
- xmpp_client_->fake_stream_.AddReadPacketString(
- {}, kAuthenticationSucceededResponse);
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kStartStreamMessage);
- RunTasks(4);
- EXPECT_EQ(XmppChannel::XmppState::kStreamRestartedPostAuthentication,
- xmpp_client_->state());
-}
-
-TEST_F(XmppChannelTest, HandleAuthenticationFailedResponse) {
- StartWithState(XmppChannel::XmppState::kAuthenticationStarted);
- xmpp_client_->fake_stream_.AddReadPacketString(
- {}, kAuthenticationFailedResponse);
- RunTasks(3);
- EXPECT_EQ(XmppChannel::XmppState::kAuthenticationFailed,
- xmpp_client_->state());
-}
-
-TEST_F(XmppChannelTest, HandleStreamRestartedResponse) {
- SetIgnoreDelayedTasks(true);
- StartWithState(XmppChannel::XmppState::kStreamRestartedPostAuthentication);
- xmpp_client_->fake_stream_.AddReadPacketString({}, kRestartStreamResponse);
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kBindMessage);
- RunTasks(3);
- EXPECT_EQ(XmppChannel::XmppState::kBindSent,
- xmpp_client_->state());
- EXPECT_TRUE(xmpp_client_->jid().empty());
-
- xmpp_client_->fake_stream_.AddReadPacketString({}, kBindResponse);
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kSessionMessage);
- RunTasks(9);
- EXPECT_EQ(XmppChannel::XmppState::kSessionStarted,
- xmpp_client_->state());
- EXPECT_EQ("110cc78f78d7032cc7bf2c6e14c1fa7d@clouddevices.gserviceaccount.com"
- "/19853128", xmpp_client_->jid());
-
- xmpp_client_->fake_stream_.AddReadPacketString({}, kSessionResponse);
- xmpp_client_->fake_stream_.ExpectWritePacketString({}, kSubscribeMessage);
- RunTasks(4);
- EXPECT_EQ(XmppChannel::XmppState::kSubscribeStarted,
- xmpp_client_->state());
-
- xmpp_client_->fake_stream_.AddReadPacketString({}, kSubscribedResponse);
- RunTasks(5);
- EXPECT_EQ(XmppChannel::XmppState::kSubscribed,
- xmpp_client_->state());
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xmpp_iq_stanza_handler.cc b/buffet/notification/xmpp_iq_stanza_handler.cc
deleted file mode 100644
index fada014..0000000
--- a/buffet/notification/xmpp_iq_stanza_handler.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xmpp_iq_stanza_handler.h"
-
-#include <base/bind.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/stringprintf.h>
-
-#include "buffet/notification/xml_node.h"
-#include "buffet/notification/xmpp_channel.h"
-
-namespace buffet {
-
-namespace {
-
-// Default timeout for <iq> requests to the server. If the response hasn't been
-// received within this time interval, the request is considered as failed.
-const int kTimeoutIntervalSeconds = 30;
-
-// Builds an XML stanza that looks like this:
-// <iq id='${id}' type='${type}' from='${from}' to='${to}'>$body</iq>
-// where 'to' and 'from' are optional attributes.
-std::string BuildIqStanza(const std::string& id,
- const std::string& type,
- const std::string& to,
- const std::string& from,
- const std::string& body) {
- std::string to_attr;
- if (!to.empty()) {
- CHECK_EQ(std::string::npos, to.find_first_of("<'>"))
- << "Destination address contains invalid XML characters";
- base::StringAppendF(&to_attr, " to='%s'", to.c_str());
- }
- std::string from_attr;
- if (!from.empty()) {
- CHECK_EQ(std::string::npos, from.find_first_of("<'>"))
- << "Source address contains invalid XML characters";
- base::StringAppendF(&from_attr, " from='%s'", from.c_str());
- }
- return base::StringPrintf("<iq id='%s' type='%s'%s%s>%s</iq>",
- id.c_str(), type.c_str(), from_attr.c_str(),
- to_attr.c_str(), body.c_str());
-}
-
-} // anonymous namespace
-
-IqStanzaHandler::IqStanzaHandler(
- XmppChannelInterface* xmpp_channel,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
- : xmpp_channel_{xmpp_channel}, task_runner_{task_runner} {}
-
-void IqStanzaHandler::SendRequest(
- const std::string& type,
- const std::string& from,
- const std::string& to,
- const std::string& body,
- const ResponseCallback& response_callback,
- const TimeoutCallback& timeout_callback) {
- return SendRequestWithCustomTimeout(
- type, from, to, body,
- base::TimeDelta::FromSeconds(kTimeoutIntervalSeconds), response_callback,
- timeout_callback);
-}
-
-void IqStanzaHandler::SendRequestWithCustomTimeout(
- const std::string& type,
- const std::string& from,
- const std::string& to,
- const std::string& body,
- base::TimeDelta timeout,
- const ResponseCallback& response_callback,
- const TimeoutCallback& timeout_callback) {
- // Remember the response callback to call later.
- requests_.emplace(++last_request_id_, response_callback);
- // Schedule a time-out callback for this request.
- if (timeout < base::TimeDelta::Max()) {
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&IqStanzaHandler::OnTimeOut, weak_ptr_factory_.GetWeakPtr(),
- last_request_id_, timeout_callback),
- timeout);
- }
-
- std::string message = BuildIqStanza(std::to_string(last_request_id_),
- type, to, from, body);
- xmpp_channel_->SendMessage(message);
-}
-
-bool IqStanzaHandler::HandleIqStanza(std::unique_ptr<XmlNode> stanza) {
- std::string type;
- if (!stanza->GetAttribute("type", &type)) {
- LOG(ERROR) << "IQ stanza missing 'type' attribute";
- return false;
- }
-
- std::string id_str;
- if (!stanza->GetAttribute("id", &id_str)) {
- LOG(ERROR) << "IQ stanza missing 'id' attribute";
- return false;
- }
-
- if (type == "result" || type == "error") {
- // These are response stanzas from the server.
- // Find the corresponding request.
- RequestId id;
- if (!base::StringToInt(id_str, &id)) {
- LOG(ERROR) << "IQ stanza's 'id' attribute is invalid";
- return false;
- }
- auto p = requests_.find(id);
- if (p != requests_.end()) {
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(p->second, base::Passed(std::move(stanza))));
- requests_.erase(p);
- }
- } else {
- // We do not support server-initiated IQ requests ("set" / "get" / "query").
- // So just reply with "not implemented" error (and swap "to"/"from" attrs).
- std::string error_body =
- "<error type='modify'>"
- "<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
- "</error>";
- std::string message = BuildIqStanza(id_str, "error",
- stanza->GetAttributeOrEmpty("from"),
- stanza->GetAttributeOrEmpty("to"),
- error_body);
- xmpp_channel_->SendMessage(message);
- }
- return true;
-}
-
-void IqStanzaHandler::OnTimeOut(RequestId id,
- const TimeoutCallback& timeout_callback) {
- // Request has not been processed yes, so a real timeout occurred.
- if (requests_.erase(id) > 0)
- timeout_callback.Run();
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xmpp_iq_stanza_handler.h b/buffet/notification/xmpp_iq_stanza_handler.h
deleted file mode 100644
index 2583e90..0000000
--- a/buffet/notification/xmpp_iq_stanza_handler.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_XMPP_IQ_STANZA_HANDLER_H_
-#define BUFFET_NOTIFICATION_XMPP_IQ_STANZA_HANDLER_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <base/callback_forward.h>
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-#include <base/single_thread_task_runner.h>
-
-#include "buffet/notification/xmpp_stream_parser.h"
-
-namespace buffet {
-
-class XmppChannelInterface;
-
-class IqStanzaHandler {
- public:
- using ResponseCallback =
- base::Callback<void(std::unique_ptr<XmlNode>)>;
- using TimeoutCallback = base::Closure;
-
- IqStanzaHandler(
- XmppChannelInterface* xmpp_channel,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
-
- // Sends <iq> request to the server.
- // |type| is the IQ stanza type, one of "get", "set", "query".
- // |to| is the target of the message. If empty string, 'to' is omitted.
- // |body| the XML snipped to include between <iq>...</iq>
- // |response_callback| is called with result or error XML stanza received
- // from the server in response to the request sent.
- // |timeout_callback| is called when the response to the request hasn't been
- // received within the time allotted.
- void SendRequest(const std::string& type,
- const std::string& from,
- const std::string& to,
- const std::string& body,
- const ResponseCallback& response_callback,
- const TimeoutCallback& timeout_callback);
-
- // |timeout| is the custom time interval after which requests should be
- // considered failed.
- void SendRequestWithCustomTimeout(const std::string& type,
- const std::string& from,
- const std::string& to,
- const std::string& body,
- base::TimeDelta timeout,
- const ResponseCallback& response_callback,
- const TimeoutCallback& timeout_callback);
-
- // Processes an <iq> stanza is received from the server. This will match the
- // stanza's 'id' attribute with pending request ID and if found, will
- // call the |response_callback|, or if the request is not found, an error
- // stanza fill be sent back to the server.
- // Returns false if some unexpected condition occurred and the stream should
- // be restarted.
- bool HandleIqStanza(std::unique_ptr<XmlNode> stanza);
-
- private:
- using RequestId = int;
- void OnTimeOut(RequestId id, const TimeoutCallback& timeout_callback);
-
- XmppChannelInterface* xmpp_channel_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- std::map<RequestId, ResponseCallback> requests_;
- RequestId last_request_id_{0};
-
- base::WeakPtrFactory<IqStanzaHandler> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(IqStanzaHandler);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_XMPP_IQ_STANZA_HANDLER_H_
-
diff --git a/buffet/notification/xmpp_iq_stanza_handler_unittest.cc b/buffet/notification/xmpp_iq_stanza_handler_unittest.cc
deleted file mode 100644
index 1e8be42..0000000
--- a/buffet/notification/xmpp_iq_stanza_handler_unittest.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xmpp_iq_stanza_handler.h"
-
-#include <map>
-#include <memory>
-
-#include <chromeos/bind_lambda.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/notification/xml_node.h"
-#include "buffet/notification/xmpp_channel.h"
-#include "buffet/notification/xmpp_stream_parser.h"
-
-using testing::Invoke;
-using testing::Return;
-using testing::_;
-
-namespace buffet {
-namespace {
-
-// Mock-like task runner that allow the tests to inspect the calls to
-// TaskRunner::PostDelayedTask and verify the delays.
-class TestTaskRunner : public base::SingleThreadTaskRunner {
- public:
- TestTaskRunner() = default;
-
- MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&,
- const base::Closure&,
- base::TimeDelta));
- MOCK_METHOD3(PostNonNestableDelayedTask,
- bool(const tracked_objects::Location&,
- const base::Closure&,
- base::TimeDelta));
-
- bool RunsTasksOnCurrentThread() const { return true; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestTaskRunner);
-};
-
-class MockXmppChannelInterface : public XmppChannelInterface {
- public:
- MockXmppChannelInterface() = default;
-
- MOCK_METHOD1(SendMessage, void(const std::string&));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockXmppChannelInterface);
-};
-
-// Simple class that allows to parse XML from string to XmlNode.
-class XmlParser : public XmppStreamParser::Delegate {
- public:
- std::unique_ptr<XmlNode> Parse(const std::string& xml) {
- parser_.ParseData(xml);
- return std::move(node_);
- }
-
- private:
- // Overrides from XmppStreamParser::Delegate.
- void OnStreamStart(const std::string& node_name,
- std::map<std::string, std::string> attributes) override {
- node_.reset(new XmlNode{node_name, std::move(attributes)});
- }
-
- void OnStreamEnd(const std::string& node_name) override {}
-
- void OnStanza(std::unique_ptr<XmlNode> stanza) override {
- node_->AddChild(std::move(stanza));
- }
-
- std::unique_ptr<XmlNode> node_;
- XmppStreamParser parser_{this};
-};
-
-class MockResponseReceiver {
- public:
- MOCK_METHOD2(OnResponse, void(int id, const std::string&));
-
- IqStanzaHandler::ResponseCallback callback(int id) {
- return base::Bind(&MockResponseReceiver::OnResponseCallback,
- base::Unretained(this), id);
- }
-
- private:
- void OnResponseCallback(int id, std::unique_ptr<XmlNode> response) {
- OnResponse(id, response->children().front()->name());
- }
-};
-
-// Functor to call the |task| immediately.
-struct TaskInvoker {
- bool operator()(const tracked_objects::Location& location,
- const base::Closure& task,
- base::TimeDelta delay) {
- task.Run();
- return true;
- }
-};
-
-} // anonymous namespace
-
-class IqStanzaHandlerTest : public testing::Test {
- public:
- void SetUp() override {
- task_runner_ = new TestTaskRunner;
- iq_stanza_handler_.reset(
- new IqStanzaHandler{&mock_xmpp_channel_, task_runner_});
- }
-
- testing::StrictMock<MockXmppChannelInterface> mock_xmpp_channel_;
- scoped_refptr<TestTaskRunner> task_runner_;
- std::unique_ptr<IqStanzaHandler> iq_stanza_handler_;
- MockResponseReceiver receiver_;
- TaskInvoker task_invoker_;
-};
-
-TEST_F(IqStanzaHandlerTest, SendRequest) {
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .WillRepeatedly(Return(true));
-
- std::string expected_msg = "<iq id='1' type='set'><body/></iq>";
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(expected_msg)).Times(1);
- iq_stanza_handler_->SendRequest("set", "", "", "<body/>", {}, {});
-
- expected_msg = "<iq id='2' type='get'><body/></iq>";
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(expected_msg)).Times(1);
- iq_stanza_handler_->SendRequest("get", "", "", "<body/>", {}, {});
-
- expected_msg = "<iq id='3' type='query' from='foo@bar'><body/></iq>";
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(expected_msg)).Times(1);
- iq_stanza_handler_->SendRequest("query", "foo@bar", "", "<body/>", {}, {});
-
- expected_msg = "<iq id='4' type='query' to='foo@bar'><body/></iq>";
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(expected_msg)).Times(1);
- iq_stanza_handler_->SendRequest("query", "", "foo@bar", "<body/>", {}, {});
-
- expected_msg = "<iq id='5' type='query' from='foo@bar' to='baz'><body/></iq>";
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(expected_msg)).Times(1);
- iq_stanza_handler_->SendRequest("query", "foo@bar", "baz", "<body/>", {}, {});
-}
-
-TEST_F(IqStanzaHandlerTest, UnsupportedIqRequest) {
- // Server IQ requests are not supported for now. Expect an error response.
- std::string expected_msg =
- "<iq id='1' type='error'><error type='modify'>"
- "<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
- "</error></iq>";
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(expected_msg)).Times(1);
- auto request = XmlParser{}.Parse("<iq id='1' type='set'><foo/></iq>");
- EXPECT_TRUE(iq_stanza_handler_->HandleIqStanza(std::move(request)));
-}
-
-TEST_F(IqStanzaHandlerTest, UnknownResponseId) {
- // No requests with ID=100 have been previously sent.
- auto request = XmlParser{}.Parse("<iq id='100' type='result'><foo/></iq>");
- EXPECT_TRUE(iq_stanza_handler_->HandleIqStanza(std::move(request)));
-}
-
-TEST_F(IqStanzaHandlerTest, SequentialResponses) {
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .Times(2).WillRepeatedly(Return(true));
-
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(_)).Times(2);
- iq_stanza_handler_->SendRequest("set", "", "", "<body/>",
- receiver_.callback(1), {});
- iq_stanza_handler_->SendRequest("get", "", "", "<body/>",
- receiver_.callback(2), {});
-
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .Times(2).WillRepeatedly(Invoke(task_invoker_));
-
- EXPECT_CALL(receiver_, OnResponse(1, "foo"));
- auto request = XmlParser{}.Parse("<iq id='1' type='result'><foo/></iq>");
- EXPECT_TRUE(iq_stanza_handler_->HandleIqStanza(std::move(request)));
-
- EXPECT_CALL(receiver_, OnResponse(2, "bar"));
- request = XmlParser{}.Parse("<iq id='2' type='result'><bar/></iq>");
- EXPECT_TRUE(iq_stanza_handler_->HandleIqStanza(std::move(request)));
-}
-
-TEST_F(IqStanzaHandlerTest, OutOfOrderResponses) {
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .Times(2).WillRepeatedly(Return(true));
-
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(_)).Times(2);
- iq_stanza_handler_->SendRequest("set", "", "", "<body/>",
- receiver_.callback(1), {});
- iq_stanza_handler_->SendRequest("get", "", "", "<body/>",
- receiver_.callback(2), {});
-
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .Times(2).WillRepeatedly(Invoke(task_invoker_));
-
- EXPECT_CALL(receiver_, OnResponse(2, "bar"));
- auto request = XmlParser{}.Parse("<iq id='2' type='result'><bar/></iq>");
- EXPECT_TRUE(iq_stanza_handler_->HandleIqStanza(std::move(request)));
-
- EXPECT_CALL(receiver_, OnResponse(1, "foo"));
- request = XmlParser{}.Parse("<iq id='1' type='result'><foo/></iq>");
- EXPECT_TRUE(iq_stanza_handler_->HandleIqStanza(std::move(request)));
-}
-
-TEST_F(IqStanzaHandlerTest, RequestTimeout) {
- EXPECT_CALL(*task_runner_, PostDelayedTask(_, _, _))
- .WillOnce(Invoke(task_invoker_));
-
- bool called = false;
- auto on_timeout = [&called]() { called = true; };
-
- EXPECT_CALL(mock_xmpp_channel_, SendMessage(_)).Times(1);
- EXPECT_FALSE(called);
- iq_stanza_handler_->SendRequest("set", "", "", "<body/>", {},
- base::Bind(on_timeout));
- EXPECT_TRUE(called);
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xmpp_stream_parser.cc b/buffet/notification/xmpp_stream_parser.cc
deleted file mode 100644
index 02329d0..0000000
--- a/buffet/notification/xmpp_stream_parser.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xmpp_stream_parser.h"
-
-#include "buffet/notification/xml_node.h"
-
-namespace buffet {
-
-XmppStreamParser::XmppStreamParser(Delegate* delegate) : delegate_{delegate} {
- parser_ = XML_ParserCreate(nullptr);
- XML_SetUserData(parser_, this);
- XML_SetElementHandler(parser_,
- &XmppStreamParser::HandleElementStart,
- &XmppStreamParser::HandleElementEnd);
- XML_SetCharacterDataHandler(parser_, &XmppStreamParser::HandleCharData);
-}
-
-XmppStreamParser::~XmppStreamParser() {
- XML_ParserFree(parser_);
-}
-
-void XmppStreamParser::ParseData(const std::string& data) {
- XML_Parse(parser_, data.data(), data.size(), 0);
-}
-
-void XmppStreamParser::Reset() {
- std::stack<std::unique_ptr<XmlNode>>{}.swap(node_stack_);
- started_ = false;
-}
-
-void XmppStreamParser::HandleElementStart(void* user_data,
- const XML_Char* element,
- const XML_Char** attr) {
- auto self = static_cast<XmppStreamParser*>(user_data);
- std::map<std::string, std::string> attributes;
- if (attr != nullptr) {
- for (size_t n = 0; attr[n] != nullptr && attr[n + 1] != nullptr; n += 2) {
- attributes.emplace(attr[n], attr[n + 1]);
- }
- }
- self->OnOpenElement(element, std::move(attributes));
-}
-
-void XmppStreamParser::HandleElementEnd(void* user_data,
- const XML_Char* element) {
- auto self = static_cast<XmppStreamParser*>(user_data);
- self->OnCloseElement(element);
-}
-
-void XmppStreamParser::HandleCharData(void* user_data,
- const char* content,
- int length) {
- auto self = static_cast<XmppStreamParser*>(user_data);
- self->OnCharData(std::string{content, static_cast<size_t>(length)});
-}
-
-void XmppStreamParser::OnOpenElement(
- const std::string& node_name,
- std::map<std::string, std::string> attributes) {
- if (!started_) {
- started_ = true;
- if (delegate_)
- delegate_->OnStreamStart(node_name, std::move(attributes));
- return;
- }
- node_stack_.emplace(new XmlNode{node_name, std::move(attributes)});
-}
-
-void XmppStreamParser::OnCloseElement(const std::string& node_name) {
- if (node_stack_.empty()) {
- if (started_) {
- started_ = false;
- if (delegate_)
- delegate_->OnStreamEnd(node_name);
- }
- return;
- }
-
- auto node = std::move(node_stack_.top());
- node_stack_.pop();
- if (!node_stack_.empty()) {
- XmlNode* parent = node_stack_.top().get();
- parent->AddChild(std::move(node));
- } else if (delegate_) {
- delegate_->OnStanza(std::move(node));
- }
-}
-
-void XmppStreamParser::OnCharData(const std::string& text) {
- if (!node_stack_.empty()) {
- XmlNode* node = node_stack_.top().get();
- node->AppendText(text);
- }
-}
-
-} // namespace buffet
diff --git a/buffet/notification/xmpp_stream_parser.h b/buffet/notification/xmpp_stream_parser.h
deleted file mode 100644
index 9ff9200..0000000
--- a/buffet/notification/xmpp_stream_parser.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_NOTIFICATION_XMPP_STREAM_PARSER_H_
-#define BUFFET_NOTIFICATION_XMPP_STREAM_PARSER_H_
-
-#include <expat.h>
-
-#include <map>
-#include <memory>
-#include <stack>
-#include <string>
-
-#include <base/macros.h>
-
-namespace buffet {
-
-class XmlNode;
-
-// A simple XML stream parser. As the XML data is being read from a data source
-// (for example, a socket), XmppStreamParser::ParseData() should be called.
-// This method parses the provided XML data chunk and if it finds complete
-// XML elements, it will call internal OnOpenElement(), OnCloseElement() and
-// OnCharData() member functions. These will track the element nesting level.
-// When a top-level element starts, the parser will call Delegate::OnStreamStart
-// method. Once this happens, every complete XML element (including its children
-// if they are present) will trigger Delegate::OnStanze() callback.
-// Finally, when top-level element is closed, Delegate::OnStreamEnd() is called.
-// This class is specifically tailored to XMPP streams which look like this:
-// B: <stream:stream to='example.com' xmlns='jabber:client' version='1.0'>
-// S: <presence><show/></presence>
-// S: <message to='foo'><body/></message>
-// S: <iq to='bar'><query/></iq>
-// S: ...
-// E: </stream:stream>
-// Here, "B:" will trigger OnStreamStart(), "S:" will result in OnStanza() and
-// "E:" will result in OnStreamEnd().
-class XmppStreamParser final {
- public:
- // Delegate interface that interested parties implement to receive
- // notifications of stream opening/closing and on new stanzas arriving.
- class Delegate {
- public:
- virtual void OnStreamStart(
- const std::string& node_name,
- std::map<std::string, std::string> attributes) = 0;
- virtual void OnStreamEnd(const std::string& node_name) = 0;
- virtual void OnStanza(std::unique_ptr<XmlNode> stanza) = 0;
-
- protected:
- virtual ~Delegate() = default;
- };
-
- explicit XmppStreamParser(Delegate* delegate);
- ~XmppStreamParser();
-
- // Parses additional XML data received from an input stream.
- void ParseData(const std::string& data);
-
- // Resets the parser to expect the top-level stream node again.
- void Reset();
-
- private:
- // Raw expat callbacks.
- static void HandleElementStart(void* user_data,
- const XML_Char* element,
- const XML_Char** attr);
- static void HandleElementEnd(void* user_data, const XML_Char* element);
- static void HandleCharData(void* user_data, const char* content, int length);
-
- // Reinterpreted callbacks from expat with some data pre-processed.
- void OnOpenElement(const std::string& node_name,
- std::map<std::string, std::string> attributes);
- void OnCloseElement(const std::string& node_name);
- void OnCharData(const std::string& text);
-
- Delegate* delegate_;
- XML_Parser parser_{nullptr};
- bool started_{false};
- std::stack<std::unique_ptr<XmlNode>> node_stack_;
-
- DISALLOW_COPY_AND_ASSIGN(XmppStreamParser);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_NOTIFICATION_XMPP_STREAM_PARSER_H_
-
diff --git a/buffet/notification/xmpp_stream_parser_unittest.cc b/buffet/notification/xmpp_stream_parser_unittest.cc
deleted file mode 100644
index 578e6ad..0000000
--- a/buffet/notification/xmpp_stream_parser_unittest.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/notification/xmpp_stream_parser.h"
-
-#include <memory>
-#include <vector>
-#include <gtest/gtest.h>
-
-#include "buffet/notification/xml_node.h"
-
-namespace buffet {
-namespace {
-// Use some real-world XMPP stream snippet to make sure all the expected
-// elements are parsed properly.
-const char kXmppStreamData[] =
- "<stream:stream from=\"clouddevices.gserviceaccount.com\" id=\"76EEB8FDB449"
- "5558\" version=\"1.0\" xmlns:stream=\"http://etherx.jabber.org/streams\" x"
- "mlns=\"jabber:client\">"
- "<stream:features><starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"><requ"
- "ired/></starttls><mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><m"
- "echanism>X-OAUTH2</mechanism><mechanism>X-GOOGLE-TOKEN</mechanism></mechan"
- "isms></stream:features>"
- "<message from=\"cloud-devices@clouddevices.google.com/srvenc-xgbCfg9hX6tCp"
- "xoMYsExqg==\" to=\"4783f652b387449fc52a76f9a16e616f@clouddevices.gservicea"
- "ccount.com/5A85ED9C\"><push:push channel=\"cloud_devices\" xmlns:push=\"go"
- "ogle:push\"><push:recipient to=\"4783f652b387449fc52a76f9a16e616f@clouddev"
- "ices.gserviceaccount.com\"></push:recipient><push:data>eyJraW5kIjoiY2xvdWR"
- "kZXZpY2VzI25vdGlmaWNhdGlvbiIsInR5cGUiOiJDT01NQU5EX0NSRUFURUQiLCJjb21tYW5kS"
- "WQiOiIwNWE3MTA5MC1hZWE4LWMzNzQtOTYwNS0xZTRhY2JhNDRmM2Y4OTAzZmM3Yy01NjExLWI"
- "5ODAtOTkyMy0yNjc2YjYwYzkxMGMiLCJkZXZpY2VJZCI6IjA1YTcxMDkwLWFlYTgtYzM3NC05N"
- "jA1LTFlNGFjYmE0NGYzZiIsImNvbW1hbmQiOnsia2luZCI6ImNsb3VkZGV2aWNlcyNjb21tYW5"
- "kIiwiaWQiOiIwNWE3MTA5MC1hZWE4LWMzNzQtOTYwNS0xZTRhY2JhNDRmM2Y4OTAzZmM3Yy01N"
- "jExLWI5ODAtOTkyMy0yNjc2YjYwYzkxMGMiLCJkZXZpY2VJZCI6IjA1YTcxMDkwLWFlYTgtYzM"
- "3NC05NjA1LTFlNGFjYmE0NGYzZiIsIm5hbWUiOiJiYXNlLl9qdW1wIiwic3RhdGUiOiJxdWV1Z"
- "WQiLCJlcnJvciI6eyJhcmd1bWVudHMiOltdfSwiY3JlYXRpb25UaW1lTXMiOiIxNDMxNTY0NDY"
- "4MjI3IiwiZXhwaXJhdGlvblRpbWVNcyI6IjE0MzE1NjgwNjgyMjciLCJleHBpcmF0aW9uVGltZ"
- "W91dE1zIjoiMzYwMDAwMCJ9fQ==</push:data></push:push></message>";
-
-} // anonymous namespace
-
-class XmppStreamParserTest : public testing::Test,
- public XmppStreamParser::Delegate {
- public:
- void SetUp() override {
- parser_.reset(new XmppStreamParser{this});
- }
-
- void OnStreamStart(const std::string& node_name,
- std::map<std::string, std::string> attributes) override {
- EXPECT_FALSE(stream_started_);
- stream_started_ = true;
- stream_start_node_name_ = node_name;
- stream_start_node_attributes_ = std::move(attributes);
- }
-
- void OnStreamEnd(const std::string& node_name) override {
- EXPECT_TRUE(stream_started_);
- EXPECT_EQ(stream_start_node_name_, node_name);
- stream_started_ = false;
- }
-
- void OnStanza(std::unique_ptr<XmlNode> stanza) override {
- stanzas_.push_back(std::move(stanza));
- }
-
- void Reset() {
- parser_.reset(new XmppStreamParser{this});
- stream_started_ = false;
- stream_start_node_name_.clear();
- stream_start_node_attributes_.clear();
- stanzas_.clear();
- }
-
- std::unique_ptr<XmppStreamParser> parser_;
- bool stream_started_{false};
- std::string stream_start_node_name_;
- std::map<std::string, std::string> stream_start_node_attributes_;
- std::vector<std::unique_ptr<XmlNode>> stanzas_;
-};
-
-TEST_F(XmppStreamParserTest, InitialState) {
- EXPECT_FALSE(stream_started_);
- EXPECT_TRUE(stream_start_node_name_.empty());
- EXPECT_TRUE(stream_start_node_attributes_.empty());
- EXPECT_TRUE(stanzas_.empty());
-}
-
-TEST_F(XmppStreamParserTest, FullStartElement) {
- parser_->ParseData("<foo bar=\"baz\" quux=\"1\">");
- EXPECT_TRUE(stream_started_);
- EXPECT_EQ("foo", stream_start_node_name_);
- const std::map<std::string, std::string> expected_attrs{
- {"bar", "baz"},
- {"quux", "1"}
- };
- EXPECT_EQ(expected_attrs, stream_start_node_attributes_);
-}
-
-TEST_F(XmppStreamParserTest, PartialStartElement) {
- parser_->ParseData("<foo bar=\"baz");
- EXPECT_FALSE(stream_started_);
- EXPECT_TRUE(stream_start_node_name_.empty());
- EXPECT_TRUE(stream_start_node_attributes_.empty());
- EXPECT_TRUE(stanzas_.empty());
- parser_->ParseData("\" quux");
- EXPECT_FALSE(stream_started_);
- parser_->ParseData("=\"1\">");
- EXPECT_TRUE(stream_started_);
- EXPECT_EQ("foo", stream_start_node_name_);
- const std::map<std::string, std::string> expected_attrs{
- {"bar", "baz"},
- {"quux", "1"}
- };
- EXPECT_EQ(expected_attrs, stream_start_node_attributes_);
-}
-
-TEST_F(XmppStreamParserTest, VariableLengthPackets) {
- std::string value;
- const std::string xml_data = kXmppStreamData;
- const std::map<std::string, std::string> expected_stream_attrs{
- {"from", "clouddevices.gserviceaccount.com"},
- {"id", "76EEB8FDB4495558"},
- {"version", "1.0"},
- {"xmlns:stream", "http://etherx.jabber.org/streams"},
- {"xmlns", "jabber:client"}
- };
- // Try splitting the data into pieces from 1 character in size to the whole
- // data block and verify that we still can parse the whole message correctly.
- // Here |step| is the size of each individual data chunk.
- for (size_t step = 1; step <= xml_data.size(); step++) {
- // Feed each individual chunk to the parser and hope it can piece everything
- // together correctly.
- for (size_t pos = 0; pos < xml_data.size(); pos += step) {
- parser_->ParseData(xml_data.substr(pos, step));
- }
- EXPECT_TRUE(stream_started_);
- EXPECT_EQ("stream:stream", stream_start_node_name_);
- EXPECT_EQ(expected_stream_attrs, stream_start_node_attributes_);
- EXPECT_EQ(2u, stanzas_.size());
-
- const XmlNode* stanza1 = stanzas_[0].get();
- EXPECT_EQ("stream:features", stanza1->name());
- ASSERT_EQ(2u, stanza1->children().size());
- const XmlNode* child1 = stanza1->children()[0].get();
- EXPECT_EQ("starttls", child1->name());
- ASSERT_EQ(1u, child1->children().size());
- EXPECT_EQ("required", child1->children()[0]->name());
- const XmlNode* child2 = stanza1->children()[1].get();
- EXPECT_EQ("mechanisms", child2->name());
- ASSERT_EQ(2u, child2->children().size());
- EXPECT_EQ("mechanism", child2->children()[0]->name());
- EXPECT_EQ("X-OAUTH2", child2->children()[0]->text());
- EXPECT_EQ("mechanism", child2->children()[1]->name());
- EXPECT_EQ("X-GOOGLE-TOKEN", child2->children()[1]->text());
-
- const XmlNode* stanza2 = stanzas_[1].get();
- EXPECT_EQ("message", stanza2->name());
- ASSERT_EQ(2u, stanza2->attributes().size());
- EXPECT_TRUE(stanza2->GetAttribute("from", &value));
- EXPECT_EQ("cloud-devices@clouddevices.google.com/"
- "srvenc-xgbCfg9hX6tCpxoMYsExqg==", value);
- EXPECT_TRUE(stanza2->GetAttribute("to", &value));
- EXPECT_EQ("4783f652b387449fc52a76f9a16e616f@clouddevices.gserviceaccount."
- "com/5A85ED9C", value);
- ASSERT_EQ(1u, stanza2->children().size());
-
- const XmlNode* child = stanza2->children().back().get();
- EXPECT_EQ("push:push", child->name());
- ASSERT_EQ(2u, child->attributes().size());
- EXPECT_TRUE(child->GetAttribute("channel", &value));
- EXPECT_EQ("cloud_devices", value);
- EXPECT_TRUE(child->GetAttribute("xmlns:push", &value));
- EXPECT_EQ("google:push", value);
- ASSERT_EQ(2u, child->children().size());
-
- child1 = child->children()[0].get();
- EXPECT_EQ("push:recipient", child1->name());
- ASSERT_EQ(1u, child1->attributes().size());
- EXPECT_TRUE(child1->GetAttribute("to", &value));
- EXPECT_EQ("4783f652b387449fc52a76f9a16e616f@clouddevices.gserviceaccount."
- "com", value);
- EXPECT_TRUE(child1->children().empty());
-
- child2 = child->children()[1].get();
- EXPECT_EQ("push:data", child2->name());
- EXPECT_TRUE(child2->attributes().empty());
- EXPECT_TRUE(child2->children().empty());
- const std::string expected_data = "eyJraW5kIjoiY2xvdWRkZXZpY2VzI25vdGlmaWNh"
- "dGlvbiIsInR5cGUiOiJDT01NQU5EX0NSRUFURUQiLCJjb21tYW5kSWQiOiIwNWE3MTA5MC"
- "1hZWE4LWMzNzQtOTYwNS0xZTRhY2JhNDRmM2Y4OTAzZmM3Yy01NjExLWI5ODAtOTkyMy0y"
- "Njc2YjYwYzkxMGMiLCJkZXZpY2VJZCI6IjA1YTcxMDkwLWFlYTgtYzM3NC05NjA1LTFlNG"
- "FjYmE0NGYzZiIsImNvbW1hbmQiOnsia2luZCI6ImNsb3VkZGV2aWNlcyNjb21tYW5kIiwi"
- "aWQiOiIwNWE3MTA5MC1hZWE4LWMzNzQtOTYwNS0xZTRhY2JhNDRmM2Y4OTAzZmM3Yy01Nj"
- "ExLWI5ODAtOTkyMy0yNjc2YjYwYzkxMGMiLCJkZXZpY2VJZCI6IjA1YTcxMDkwLWFlYTgt"
- "YzM3NC05NjA1LTFlNGFjYmE0NGYzZiIsIm5hbWUiOiJiYXNlLl9qdW1wIiwic3RhdGUiOi"
- "JxdWV1ZWQiLCJlcnJvciI6eyJhcmd1bWVudHMiOltdfSwiY3JlYXRpb25UaW1lTXMiOiIx"
- "NDMxNTY0NDY4MjI3IiwiZXhwaXJhdGlvblRpbWVNcyI6IjE0MzE1NjgwNjgyMjciLCJleH"
- "BpcmF0aW9uVGltZW91dE1zIjoiMzYwMDAwMCJ9fQ==";
- EXPECT_EQ(expected_data, child2->text());
- }
-}
-
-} // namespace buffet
diff --git a/buffet/privet/ap_manager_client.cc b/buffet/privet/ap_manager_client.cc
deleted file mode 100644
index b123f1f..0000000
--- a/buffet/privet/ap_manager_client.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/ap_manager_client.h"
-
-namespace privetd {
-
-using org::chromium::apmanager::ConfigProxy;
-using org::chromium::apmanager::ManagerProxy;
-using org::chromium::apmanager::ServiceProxy;
-
-ApManagerClient::ApManagerClient(const scoped_refptr<dbus::Bus>& bus)
- : bus_(bus) {
-}
-
-ApManagerClient::~ApManagerClient() {
- Stop();
-}
-
-void ApManagerClient::Start(const std::string& ssid) {
- if (service_path_.IsValid()) {
- return;
- }
-
- ssid_ = ssid;
-
- object_manager_proxy_.reset(
- new org::chromium::apmanager::ObjectManagerProxy{bus_});
- object_manager_proxy_->SetManagerAddedCallback(base::Bind(
- &ApManagerClient::OnManagerAdded, weak_ptr_factory_.GetWeakPtr()));
- object_manager_proxy_->SetServiceAddedCallback(base::Bind(
- &ApManagerClient::OnServiceAdded, weak_ptr_factory_.GetWeakPtr()));
-
- object_manager_proxy_->SetServiceRemovedCallback(base::Bind(
- &ApManagerClient::OnServiceRemoved, weak_ptr_factory_.GetWeakPtr()));
- object_manager_proxy_->SetManagerRemovedCallback(base::Bind(
- &ApManagerClient::OnManagerRemoved, weak_ptr_factory_.GetWeakPtr()));
-}
-
-void ApManagerClient::Stop() {
- if (manager_proxy_ && service_path_.IsValid()) {
- RemoveService(service_path_);
- }
- service_path_ = dbus::ObjectPath();
- service_proxy_ = nullptr;
- manager_proxy_ = nullptr;
- object_manager_proxy_.reset();
- ssid_.clear();
-}
-
-void ApManagerClient::RemoveService(const dbus::ObjectPath& object_path) {
- CHECK(object_path.IsValid());
- chromeos::ErrorPtr error;
- if (!manager_proxy_->RemoveService(object_path, &error)) {
- LOG(ERROR) << "RemoveService failed: " << error->GetMessage();
- }
-}
-
-void ApManagerClient::OnManagerAdded(ManagerProxy* manager_proxy) {
- VLOG(1) << "manager added: " << manager_proxy->GetObjectPath().value();
- manager_proxy_ = manager_proxy;
-
- if (service_path_.IsValid())
- return;
-
- chromeos::ErrorPtr error;
- if (!manager_proxy_->CreateService(&service_path_, &error)) {
- LOG(ERROR) << "CreateService failed: " << error->GetMessage();
- }
-}
-
-void ApManagerClient::OnServiceAdded(ServiceProxy* service_proxy) {
- VLOG(1) << "service added: " << service_proxy->GetObjectPath().value();
- if (service_proxy->GetObjectPath() != service_path_) {
- RemoveService(service_proxy->GetObjectPath());
- return;
- }
- service_proxy_ = service_proxy;
-
- ConfigProxy* config_proxy =
- object_manager_proxy_->GetConfigProxy(service_proxy->config());
- ConfigProxy::PropertySet* properties = config_proxy->GetProperties();
- properties->ssid.Set(ssid_, base::Bind(&ApManagerClient::OnSsidSet,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void ApManagerClient::OnSsidSet(bool success) {
- if (!success || !service_proxy_) {
- LOG(ERROR) << "Failed to set ssid.";
- return;
- }
- VLOG(1) << "SSID is set: " << ssid_;
-
- chromeos::ErrorPtr error;
- if (!service_proxy_->Start(&error)) {
- LOG(ERROR) << "Service start failed: " << error->GetMessage();
- }
-}
-
-void ApManagerClient::OnServiceRemoved(const dbus::ObjectPath& object_path) {
- VLOG(1) << "service removed: " << object_path.value();
- if (object_path != service_path_)
- return;
- service_path_ = dbus::ObjectPath();
- service_proxy_ = nullptr;
-}
-
-void ApManagerClient::OnManagerRemoved(const dbus::ObjectPath& object_path) {
- VLOG(1) << "manager removed: " << object_path.value();
- manager_proxy_ = nullptr;
- Stop();
-}
-
-} // namespace privetd
diff --git a/buffet/privet/ap_manager_client.h b/buffet/privet/ap_manager_client.h
deleted file mode 100644
index ec99a6a..0000000
--- a/buffet/privet/ap_manager_client.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_AP_MANAGER_CLIENT_H_
-#define BUFFET_PRIVET_AP_MANAGER_CLIENT_H_
-
-#include <memory>
-#include <string>
-
-#include <base/callback.h>
-#include <base/memory/ref_counted.h>
-
-#include "apmanager/dbus-proxies.h"
-
-namespace privetd {
-
-// Manages soft AP for wifi bootstrapping.
-// Once created can handle multiple Start/Stop requests.
-class ApManagerClient final {
- public:
- explicit ApManagerClient(const scoped_refptr<dbus::Bus>& bus);
- ~ApManagerClient();
-
- void Start(const std::string& ssid);
- void Stop();
-
- std::string GetSsid() const { return ssid_; }
-
- private:
- void RemoveService(const dbus::ObjectPath& object_path);
-
- void OnManagerAdded(org::chromium::apmanager::ManagerProxy* manager_proxy);
- void OnServiceAdded(org::chromium::apmanager::ServiceProxy* service_proxy);
-
- void OnSsidSet(bool success);
-
- void OnServiceRemoved(const dbus::ObjectPath& object_path);
- void OnManagerRemoved(const dbus::ObjectPath& object_path);
-
- scoped_refptr<dbus::Bus> bus_;
-
- std::unique_ptr<org::chromium::apmanager::ObjectManagerProxy>
- object_manager_proxy_;
- org::chromium::apmanager::ManagerProxy* manager_proxy_{nullptr};
-
- dbus::ObjectPath service_path_;
- org::chromium::apmanager::ServiceProxy* service_proxy_{nullptr};
-
- std::string ssid_;
-
- base::WeakPtrFactory<ApManagerClient> weak_ptr_factory_{this};
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_AP_MANAGER_CLIENT_H_
diff --git a/buffet/privet/cloud_delegate.cc b/buffet/privet/cloud_delegate.cc
deleted file mode 100644
index 86c93cc..0000000
--- a/buffet/privet/cloud_delegate.cc
+++ /dev/null
@@ -1,408 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/cloud_delegate.h"
-
-#include <map>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/logging.h>
-#include <base/memory/weak_ptr.h>
-#include <base/message_loop/message_loop.h>
-#include <base/values.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/variant_dictionary.h>
-#include <dbus/bus.h>
-
-#include "buffet/buffet_config.h"
-#include "buffet/commands/command_manager.h"
-#include "buffet/dbus-proxies.h"
-#include "buffet/device_registration_info.h"
-#include "buffet/privet/constants.h"
-#include "buffet/states/state_manager.h"
-
-namespace privetd {
-
-namespace {
-
-using chromeos::ErrorPtr;
-using chromeos::VariantDictionary;
-using org::chromium::Buffet::ManagerProxy;
-using org::chromium::Buffet::ObjectManagerProxy;
-
-const int kMaxSetupRetries = 5;
-const int kFirstRetryTimeoutSec = 1;
-
-buffet::CommandInstance* ReturnNotFound(const std::string& command_id,
- chromeos::ErrorPtr* error) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::kDomain,
- errors::kNotFound, "Command not found, ID='%s'",
- command_id.c_str());
- return nullptr;
-}
-
-class CloudDelegateImpl : public CloudDelegate {
- public:
- CloudDelegateImpl(buffet::DeviceRegistrationInfo* device,
- buffet::CommandManager* command_manager,
- buffet::StateManager* state_manager)
- : device_{device},
- command_manager_{command_manager},
- state_manager_{state_manager} {
- device_->AddOnConfigChangedCallback(base::Bind(
- &CloudDelegateImpl::OnConfigChanged, weak_factory_.GetWeakPtr()));
- device_->AddOnRegistrationChangedCallback(base::Bind(
- &CloudDelegateImpl::OnRegistrationChanged, weak_factory_.GetWeakPtr()));
-
- command_manager_->AddOnCommandDefChanged(base::Bind(
- &CloudDelegateImpl::OnCommandDefChanged, weak_factory_.GetWeakPtr()));
- command_manager_->AddOnCommandAddedCallback(base::Bind(
- &CloudDelegateImpl::OnCommandAdded, weak_factory_.GetWeakPtr()));
- command_manager_->AddOnCommandRemovedCallback(base::Bind(
- &CloudDelegateImpl::OnCommandRemoved, weak_factory_.GetWeakPtr()));
-
- state_manager_->AddOnChangedCallback(base::Bind(
- &CloudDelegateImpl::OnStateChanged, weak_factory_.GetWeakPtr()));
- }
-
- ~CloudDelegateImpl() override = default;
-
- bool GetModelId(std::string* id, chromeos::ErrorPtr* error) const override {
- if (device_->GetConfig().model_id().size() != 5) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::kDomain, errors::kInvalidState,
- "Model ID is invalid: %s", device_->GetConfig().model_id().c_str());
- return false;
- }
- *id = device_->GetConfig().model_id();
- return true;
- }
-
- bool GetName(std::string* name, chromeos::ErrorPtr* error) const override {
- *name = device_->GetConfig().name();
- return true;
- }
-
- std::string GetDescription() const override {
- return device_->GetConfig().description();
- }
-
- std::string GetLocation() const override {
- return device_->GetConfig().location();
- }
-
- void UpdateDeviceInfo(const std::string& name,
- const std::string& description,
- const std::string& location,
- const base::Closure& success_callback,
- const ErrorCallback& error_callback) override {
- chromeos::ErrorPtr error;
- if (!device_->UpdateDeviceInfo(name, description, location, &error))
- return error_callback.Run(error.get());
- success_callback.Run();
- }
-
- std::string GetOemName() const override {
- return device_->GetConfig().oem_name();
- }
-
- std::string GetModelName() const override {
- return device_->GetConfig().model_name();
- }
-
- std::set<std::string> GetServices() const override {
- std::set<std::string> result;
- for (base::DictionaryValue::Iterator it{command_defs_}; !it.IsAtEnd();
- it.Advance()) {
- result.emplace(it.key());
- }
- return result;
- }
-
- AuthScope GetAnonymousMaxScope() const override {
- AuthScope scope;
- if (StringToAuthScope(device_->GetConfig().local_anonymous_access_role(),
- &scope)) {
- return scope;
- }
- return AuthScope::kNone;
- }
-
- const ConnectionState& GetConnectionState() const override {
- return connection_state_;
- }
-
- const SetupState& GetSetupState() const override { return setup_state_; }
-
- bool Setup(const std::string& ticket_id,
- const std::string& user,
- chromeos::ErrorPtr* error) override {
- if (setup_state_.IsStatusEqual(SetupState::kInProgress)) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kDeviceBusy, "Setup in progress");
- return false;
- }
- VLOG(1) << "GCD Setup started. ticket_id: " << ticket_id
- << ", user:" << user;
- setup_state_ = SetupState(SetupState::kInProgress);
- setup_weak_factory_.InvalidateWeakPtrs();
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
- setup_weak_factory_.GetWeakPtr(), ticket_id, 0),
- base::TimeDelta::FromSeconds(kSetupDelaySeconds));
- // Return true because we tried setup.
- return true;
- }
-
- std::string GetCloudId() const override {
- return device_->GetConfig().device_id();
- }
-
- const base::DictionaryValue& GetState() const override { return state_; }
-
- const base::DictionaryValue& GetCommandDef() const override {
- return command_defs_;
- }
-
- void AddCommand(const base::DictionaryValue& command,
- const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) override {
- CHECK(user_info.scope() != AuthScope::kNone);
- CHECK_NE(user_info.user_id(), 0u);
-
- chromeos::ErrorPtr error;
- buffet::UserRole role;
- if (!FromString(AuthScopeToString(user_info.scope()), &role, &error))
- return error_callback.Run(error.get());
-
- std::string id;
- if (!command_manager_->AddCommand(command, role, &id, &error))
- return error_callback.Run(error.get());
-
- command_owners_[id] = user_info.user_id();
- success_callback.Run(*command_manager_->FindCommand(id)->ToJson());
- }
-
- void GetCommand(const std::string& id,
- const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) override {
- CHECK(user_info.scope() != AuthScope::kNone);
- chromeos::ErrorPtr error;
- auto command = GetCommandInternal(id, user_info, &error);
- if (!command)
- return error_callback.Run(error.get());
- success_callback.Run(*command->ToJson());
- }
-
- void CancelCommand(const std::string& id,
- const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) override {
- CHECK(user_info.scope() != AuthScope::kNone);
- chromeos::ErrorPtr error;
- auto command = GetCommandInternal(id, user_info, &error);
- if (!command)
- return error_callback.Run(error.get());
-
- command->Cancel();
- success_callback.Run(*command->ToJson());
- }
-
- void ListCommands(const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) override {
- CHECK(user_info.scope() != AuthScope::kNone);
-
- base::ListValue list_value;
-
- for (const auto& it : command_owners_) {
- if (CanAccessCommand(it.second, user_info, nullptr)) {
- list_value.Append(
- command_manager_->FindCommand(it.first)->ToJson().release());
- }
- }
-
- base::DictionaryValue commands_json;
- commands_json.Set("commands", list_value.DeepCopy());
-
- success_callback.Run(commands_json);
- }
-
- private:
- void OnCommandAdded(buffet::CommandInstance* command) {
- // Set to 0 for any new unknown command.
- command_owners_.emplace(command->GetID(), 0);
- }
-
- void OnCommandRemoved(buffet::CommandInstance* command) {
- CHECK(command_owners_.erase(command->GetID()));
- }
-
- void OnConfigChanged(const buffet::BuffetConfig&) {
- NotifyOnDeviceInfoChanged();
- }
-
- void OnRegistrationChanged(buffet::RegistrationStatus status) {
- if (status == buffet::RegistrationStatus::kUnconfigured) {
- connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- } else if (status == buffet::RegistrationStatus::kConnecting) {
- // TODO(vitalybuka): Find conditions for kOffline.
- connection_state_ = ConnectionState{ConnectionState::kConnecting};
- } else if (status == buffet::RegistrationStatus::kConnected) {
- connection_state_ = ConnectionState{ConnectionState::kOnline};
- } else {
- chromeos::ErrorPtr error;
- chromeos::Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
- errors::kInvalidState,
- "Unexpected buffet status: %s",
- buffet::StatusToString(status).c_str());
- connection_state_ = ConnectionState{std::move(error)};
- }
- NotifyOnDeviceInfoChanged();
- }
-
- void OnStateChanged() {
- state_.Clear();
- auto state = state_manager_->GetStateValuesAsJson(nullptr);
- CHECK(state);
- state_.MergeDictionary(state.get());
- NotifyOnStateChanged();
- }
-
- void OnCommandDefChanged() {
- command_defs_.Clear();
- auto commands = command_manager_->GetCommandDictionary().GetCommandsAsJson(
- [](const buffet::CommandDefinition* def) {
- return def->GetVisibility().local;
- },
- true, nullptr);
- CHECK(commands);
- command_defs_.MergeDictionary(commands.get());
- NotifyOnCommandDefsChanged();
- }
-
- void RetryRegister(const std::string& ticket_id,
- int retries,
- chromeos::Error* error) {
- if (retries >= kMaxSetupRetries) {
- chromeos::ErrorPtr new_error{error ? error->Clone() : nullptr};
- chromeos::Error::AddTo(&new_error, FROM_HERE, errors::kDomain,
- errors::kInvalidState,
- "Failed to register device");
- setup_state_ = SetupState{std::move(new_error)};
- return;
- }
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
- setup_weak_factory_.GetWeakPtr(), ticket_id, retries + 1),
- base::TimeDelta::FromSeconds(kFirstRetryTimeoutSec << retries));
- }
-
- void OnRegisterSuccess(const std::string& device_id) {
- VLOG(1) << "Device registered: " << device_id;
- setup_state_ = SetupState(SetupState::kSuccess);
- }
-
- void CallManagerRegisterDevice(const std::string& ticket_id, int retries) {
- chromeos::ErrorPtr error;
- if (device_->RegisterDevice(ticket_id, &error).empty())
- return RetryRegister(ticket_id, retries, error.get());
- setup_state_ = SetupState(SetupState::kSuccess);
- }
-
- buffet::CommandInstance* GetCommandInternal(const std::string& command_id,
- const UserInfo& user_info,
- chromeos::ErrorPtr* error) const {
- if (user_info.scope() != AuthScope::kOwner) {
- auto it = command_owners_.find(command_id);
- if (it == command_owners_.end())
- return ReturnNotFound(command_id, error);
- if (CanAccessCommand(it->second, user_info, error))
- return nullptr;
- }
-
- auto command = command_manager_->FindCommand(command_id);
- if (!command)
- return ReturnNotFound(command_id, error);
-
- return command;
- }
-
- bool CanAccessCommand(uint64_t owner_id,
- const UserInfo& user_info,
- chromeos::ErrorPtr* error) const {
- CHECK(user_info.scope() != AuthScope::kNone);
- CHECK_NE(user_info.user_id(), 0u);
-
- if (user_info.scope() == AuthScope::kOwner ||
- owner_id == user_info.user_id()) {
- return true;
- }
-
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kAccessDenied,
- "Need to be owner of the command.");
- return false;
- }
-
- buffet::DeviceRegistrationInfo* device_{nullptr};
- buffet::CommandManager* command_manager_{nullptr};
- buffet::StateManager* state_manager_{nullptr};
-
- // Primary state of GCD.
- ConnectionState connection_state_{ConnectionState::kDisabled};
-
- // State of the current or last setup.
- SetupState setup_state_{SetupState::kNone};
-
- // Current device state.
- base::DictionaryValue state_;
-
- // Current commands definitions.
- base::DictionaryValue command_defs_;
-
- // Map of command IDs to user IDs.
- std::map<std::string, uint64_t> command_owners_;
-
- // |setup_weak_factory_| tracks the lifetime of callbacks used in connection
- // with a particular invocation of Setup().
- base::WeakPtrFactory<CloudDelegateImpl> setup_weak_factory_{this};
- // |weak_factory_| tracks the lifetime of |this|.
- base::WeakPtrFactory<CloudDelegateImpl> weak_factory_{this};
-};
-
-} // namespace
-
-CloudDelegate::CloudDelegate() {
-}
-
-CloudDelegate::~CloudDelegate() {
-}
-
-// static
-std::unique_ptr<CloudDelegate> CloudDelegate::CreateDefault(
- buffet::DeviceRegistrationInfo* device,
- buffet::CommandManager* command_manager,
- buffet::StateManager* state_manager) {
- return std::unique_ptr<CloudDelegateImpl>{
- new CloudDelegateImpl{device, command_manager, state_manager}};
-}
-
-void CloudDelegate::NotifyOnDeviceInfoChanged() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceInfoChanged());
-}
-
-void CloudDelegate::NotifyOnCommandDefsChanged() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnCommandDefsChanged());
-}
-
-void CloudDelegate::NotifyOnStateChanged() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnStateChanged());
-}
-
-} // namespace privetd
diff --git a/buffet/privet/cloud_delegate.h b/buffet/privet/cloud_delegate.h
deleted file mode 100644
index 49dfd7d..0000000
--- a/buffet/privet/cloud_delegate.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_CLOUD_DELEGATE_H_
-#define BUFFET_PRIVET_CLOUD_DELEGATE_H_
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include <base/callback.h>
-#include <base/memory/ref_counted.h>
-#include <base/observer_list.h>
-
-#include "buffet/privet/privet_types.h"
-#include "buffet/privet/security_delegate.h"
-
-namespace base {
-class DictionaryValue;
-} // namespace base
-
-namespace buffet {
-class CommandManager;
-class DeviceRegistrationInfo;
-class StateManager;
-}
-
-namespace privetd {
-
-// Interface to provide GCD functionality for PrivetHandler.
-// TODO(vitalybuka): Rename to BuffetDelegate.
-class CloudDelegate {
- public:
- CloudDelegate();
- virtual ~CloudDelegate();
-
- using SuccessCallback = base::Callback<void(const base::DictionaryValue&)>;
- using ErrorCallback = base::Callback<void(chromeos::Error*)>;
-
- class Observer {
- public:
- virtual ~Observer() = default;
-
- virtual void OnDeviceInfoChanged() {}
- virtual void OnCommandDefsChanged() {}
- virtual void OnStateChanged() {}
- };
-
- // Returns the model ID of the device.
- virtual bool GetModelId(std::string* id, chromeos::ErrorPtr* error) const = 0;
-
- // Returns the name of device.
- virtual bool GetName(std::string* name, chromeos::ErrorPtr* error) const = 0;
-
- // Returns the description of the device.
- virtual std::string GetDescription() const = 0;
-
- // Returns the location of the device.
- virtual std::string GetLocation() const = 0;
-
- // Update basic device information.
- virtual void UpdateDeviceInfo(const std::string& name,
- const std::string& description,
- const std::string& location,
- const base::Closure& success_callback,
- const ErrorCallback& error_callback) = 0;
-
- // Returns the name of the maker.
- virtual std::string GetOemName() const = 0;
-
- // Returns the model name of the device.
- virtual std::string GetModelName() const = 0;
-
- // Returns the list of services supported by device.
- // E.g. printer, scanner etc. Should match services published on mDNS.
- virtual std::set<std::string> GetServices() const = 0;
-
- // Returns max scope available for anonymous user.
- virtual AuthScope GetAnonymousMaxScope() const = 0;
-
- // Returns status of the GCD connection.
- virtual const ConnectionState& GetConnectionState() const = 0;
-
- // Returns status of the last setup.
- virtual const SetupState& GetSetupState() const = 0;
-
- // Starts GCD setup.
- virtual bool Setup(const std::string& ticket_id,
- const std::string& user,
- chromeos::ErrorPtr* error) = 0;
-
- // Returns cloud id if the registered device or empty string if unregistered.
- virtual std::string GetCloudId() const = 0;
-
- // Returns dictionary with device state.
- virtual const base::DictionaryValue& GetState() const = 0;
-
- // Returns dictionary with commands definitions.
- virtual const base::DictionaryValue& GetCommandDef() const = 0;
-
- // Adds command created from the given JSON representation.
- virtual void AddCommand(const base::DictionaryValue& command,
- const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) = 0;
-
- // Returns command with the given ID.
- virtual void GetCommand(const std::string& id,
- const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) = 0;
-
- // Cancels command with the given ID.
- virtual void CancelCommand(const std::string& id,
- const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) = 0;
-
- // Lists commands.
- virtual void ListCommands(const UserInfo& user_info,
- const SuccessCallback& success_callback,
- const ErrorCallback& error_callback) = 0;
-
- void AddObserver(Observer* observer) { observer_list_.AddObserver(observer); }
- void RemoveObserver(Observer* observer) {
- observer_list_.RemoveObserver(observer);
- }
-
- void NotifyOnDeviceInfoChanged();
- void NotifyOnCommandDefsChanged();
- void NotifyOnStateChanged();
-
- // Create default instance.
- static std::unique_ptr<CloudDelegate> CreateDefault(
- buffet::DeviceRegistrationInfo* device,
- buffet::CommandManager* command_manager,
- buffet::StateManager* state_manager);
-
- private:
- base::ObserverList<Observer> observer_list_;
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_CLOUD_DELEGATE_H_
diff --git a/buffet/privet/constants.cc b/buffet/privet/constants.cc
deleted file mode 100644
index e94b541..0000000
--- a/buffet/privet/constants.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/constants.h"
-
-namespace privetd {
-
-namespace errors {
-
-const char kDomain[] = "privetd";
-
-const char kInvalidClientCommitment[] = "invalidClientCommitment";
-const char kInvalidFormat[] = "invalidFormat";
-const char kMissingAuthorization[] = "missingAuthorization";
-const char kInvalidAuthorization[] = "invalidAuthorization";
-const char kInvalidAuthorizationScope[] = "invalidAuthorizationScope";
-const char kAuthorizationExpired[] = "authorizationExpired";
-const char kCommitmentMismatch[] = "commitmentMismatch";
-const char kUnknownSession[] = "unknownSession";
-const char kInvalidAuthCode[] = "invalidAuthCode";
-const char kInvalidAuthMode[] = "invalidAuthMode";
-const char kInvalidRequestedScope[] = "invalidRequestedScope";
-const char kAccessDenied[] = "accessDenied";
-const char kInvalidParams[] = "invalidParams";
-const char kSetupUnavailable[] = "setupUnavailable";
-const char kDeviceBusy[] = "deviceBusy";
-const char kInvalidState[] = "invalidState";
-const char kInvalidSsid[] = "invalidSsid";
-const char kInvalidPassphrase[] = "invalidPassphrase";
-const char kNotFound[] = "notFound";
-const char kNotImplemented[] = "notImplemented";
-
-} // namespace errors
-
-} // namespace privetd
diff --git a/buffet/privet/constants.h b/buffet/privet/constants.h
deleted file mode 100644
index c408ca1..0000000
--- a/buffet/privet/constants.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_CONSTANTS_H_
-#define BUFFET_PRIVET_CONSTANTS_H_
-
-namespace privetd {
-
-namespace errors {
-
-extern const char kDomain[];
-
-extern const char kInvalidClientCommitment[];
-extern const char kInvalidFormat[];
-extern const char kMissingAuthorization[];
-extern const char kInvalidAuthorization[];
-extern const char kInvalidAuthorizationScope[];
-extern const char kAuthorizationExpired[];
-extern const char kCommitmentMismatch[];
-extern const char kUnknownSession[];
-extern const char kInvalidAuthCode[];
-extern const char kInvalidAuthMode[];
-extern const char kInvalidRequestedScope[];
-extern const char kAccessDenied[];
-extern const char kInvalidParams[];
-extern const char kSetupUnavailable[];
-extern const char kDeviceBusy[];
-extern const char kInvalidState[];
-extern const char kInvalidSsid[];
-extern const char kInvalidPassphrase[];
-extern const char kNotFound[];
-extern const char kNotImplemented[];
-} // namespace errors
-
-// Time to reply on privet HTTP.
-const int kSetupDelaySeconds = 1;
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_CONSTANTS_H_
diff --git a/buffet/privet/device_delegate.cc b/buffet/privet/device_delegate.cc
deleted file mode 100644
index 8670696..0000000
--- a/buffet/privet/device_delegate.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/device_delegate.h"
-
-#include <base/files/file_util.h>
-#include <base/guid.h>
-
-#include "buffet/privet/constants.h"
-
-namespace privetd {
-
-namespace {
-
-class DeviceDelegateImpl : public DeviceDelegate {
- public:
- DeviceDelegateImpl() = default;
- ~DeviceDelegateImpl() override = default;
-
- std::pair<uint16_t, uint16_t> GetHttpEnpoint() const override {
- return std::make_pair(http_port_, http_port_);
- }
- std::pair<uint16_t, uint16_t> GetHttpsEnpoint() const override {
- return std::make_pair(https_port_, https_port_);
- }
- base::TimeDelta GetUptime() const override {
- return base::Time::Now() - start_time_;
- }
-
- void SetHttpPort(uint16_t port) override { http_port_ = port; }
-
- void SetHttpsPort(uint16_t port) override { https_port_ = port; }
-
- private:
- uint16_t http_port_{0};
- uint16_t https_port_{0};
- base::Time start_time_{base::Time::Now()};
-};
-
-} // namespace
-
-DeviceDelegate::DeviceDelegate() {
-}
-
-DeviceDelegate::~DeviceDelegate() {
-}
-
-// static
-std::unique_ptr<DeviceDelegate> DeviceDelegate::CreateDefault() {
- return std::unique_ptr<DeviceDelegate>(new DeviceDelegateImpl());
-}
-
-} // namespace privetd
diff --git a/buffet/privet/device_delegate.h b/buffet/privet/device_delegate.h
deleted file mode 100644
index 9888dfd..0000000
--- a/buffet/privet/device_delegate.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_DEVICE_DELEGATE_H_
-#define BUFFET_PRIVET_DEVICE_DELEGATE_H_
-
-#include <memory>
-#include <utility>
-
-#include <base/time/time.h>
-
-namespace privetd {
-
-// Interface to provide access to general information about device.
-class DeviceDelegate {
- public:
- DeviceDelegate();
- virtual ~DeviceDelegate();
-
- // Returns HTTP ports for Privet. The first one is the primary port,
- // the second is the port for a pooling updates requests. The second value
- // could be 0. In this case the first port would be use for regular and for
- // updates requests.
- virtual std::pair<uint16_t, uint16_t> GetHttpEnpoint() const = 0;
-
- // The same |GetHttpEnpoint| but for HTTPS.
- virtual std::pair<uint16_t, uint16_t> GetHttpsEnpoint() const = 0;
-
- // Returns device update.
- virtual base::TimeDelta GetUptime() const = 0;
-
- // Updates the HTTP port value.
- virtual void SetHttpPort(uint16_t port) = 0;
-
- // Updates the HTTPS port value.
- virtual void SetHttpsPort(uint16_t port) = 0;
-
- // Create default instance.
- static std::unique_ptr<DeviceDelegate> CreateDefault();
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_DEVICE_DELEGATE_H_
diff --git a/buffet/privet/identity_delegate.h b/buffet/privet/identity_delegate.h
deleted file mode 100644
index 5ab97d1..0000000
--- a/buffet/privet/identity_delegate.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_IDENTITY_DELEGATE_H_
-#define BUFFET_PRIVET_IDENTITY_DELEGATE_H_
-
-#include <string>
-
-namespace privetd {
-
-// Interface for an object that can identify ourselves.
-class IdentityDelegate {
- public:
- IdentityDelegate() = default;
- virtual ~IdentityDelegate() = default;
-
- // Returns a unique identifier for this device.
- virtual std::string GetId() const = 0;
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_IDENTITY_DELEGATE_H_
diff --git a/buffet/privet/mock_delegates.h b/buffet/privet/mock_delegates.h
deleted file mode 100644
index ff8c11b..0000000
--- a/buffet/privet/mock_delegates.h
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_MOCK_DELEGATES_H_
-#define BUFFET_PRIVET_MOCK_DELEGATES_H_
-
-#include <set>
-#include <string>
-#include <utility>
-
-#include <base/values.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/privet/cloud_delegate.h"
-#include "buffet/privet/device_delegate.h"
-#include "buffet/privet/identity_delegate.h"
-#include "buffet/privet/security_delegate.h"
-#include "buffet/privet/wifi_delegate.h"
-
-using testing::_;
-using testing::Return;
-using testing::ReturnRef;
-using testing::SetArgPointee;
-
-namespace privetd {
-
-ACTION_TEMPLATE(RunCallback,
- HAS_1_TEMPLATE_PARAMS(int, k),
- AND_0_VALUE_PARAMS()) {
- return std::get<k>(args).Run();
-}
-
-ACTION_TEMPLATE(RunCallback,
- HAS_1_TEMPLATE_PARAMS(int, k),
- AND_1_VALUE_PARAMS(p0)) {
- return std::get<k>(args).Run(p0);
-}
-
-class MockDeviceDelegate : public DeviceDelegate {
- using IntPair = std::pair<uint16_t, uint16_t>;
-
- public:
- MOCK_CONST_METHOD0(GetHttpEnpoint, IntPair());
- MOCK_CONST_METHOD0(GetHttpsEnpoint, IntPair());
- MOCK_CONST_METHOD0(GetUptime, base::TimeDelta());
- MOCK_METHOD1(SetHttpPort, void(uint16_t));
- MOCK_METHOD1(SetHttpsPort, void(uint16_t));
-
- MockDeviceDelegate() {
- EXPECT_CALL(*this, GetHttpEnpoint())
- .WillRepeatedly(Return(std::make_pair(0, 0)));
- EXPECT_CALL(*this, GetHttpsEnpoint())
- .WillRepeatedly(Return(std::make_pair(0, 0)));
- EXPECT_CALL(*this, GetUptime())
- .WillRepeatedly(Return(base::TimeDelta::FromHours(1)));
- }
-};
-
-class MockSecurityDelegate : public SecurityDelegate {
- public:
- MOCK_METHOD2(CreateAccessToken,
- std::string(const UserInfo&, const base::Time&));
- MOCK_CONST_METHOD2(ParseAccessToken,
- UserInfo(const std::string&, base::Time*));
- MOCK_CONST_METHOD0(GetPairingTypes, std::set<PairingType>());
- MOCK_CONST_METHOD0(GetCryptoTypes, std::set<CryptoType>());
- MOCK_CONST_METHOD1(IsValidPairingCode, bool(const std::string&));
- MOCK_METHOD5(StartPairing,
- bool(PairingType,
- CryptoType,
- std::string*,
- std::string*,
- chromeos::ErrorPtr*));
- MOCK_METHOD5(ConfirmPairing,
- bool(const std::string&,
- const std::string&,
- std::string*,
- std::string*,
- chromeos::ErrorPtr*));
- MOCK_METHOD2(CancelPairing, bool(const std::string&, chromeos::ErrorPtr*));
-
- MockSecurityDelegate() {
- EXPECT_CALL(*this, CreateAccessToken(_, _))
- .WillRepeatedly(Return("GuestAccessToken"));
-
- EXPECT_CALL(*this, ParseAccessToken(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()),
- Return(UserInfo{AuthScope::kViewer, 1234567})));
-
- EXPECT_CALL(*this, GetPairingTypes())
- .WillRepeatedly(Return(std::set<PairingType>{
- PairingType::kPinCode,
- PairingType::kEmbeddedCode,
- PairingType::kUltrasound32,
- PairingType::kAudible32,
- }));
-
- EXPECT_CALL(*this, GetCryptoTypes())
- .WillRepeatedly(Return(std::set<CryptoType>{
- CryptoType::kSpake_p224, CryptoType::kSpake_p256,
- }));
-
- EXPECT_CALL(*this, StartPairing(_, _, _, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>("testSession"),
- SetArgPointee<3>("testCommitment"),
- Return(true)));
-
- EXPECT_CALL(*this, ConfirmPairing(_, _, _, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<2>("testFingerprint"),
- SetArgPointee<3>("testSignature"), Return(true)));
- EXPECT_CALL(*this, CancelPairing(_, _)).WillRepeatedly(Return(true));
- }
-};
-
-class MockWifiDelegate : public WifiDelegate {
- public:
- MOCK_CONST_METHOD0(GetConnectionState, const ConnectionState&());
- MOCK_CONST_METHOD0(GetSetupState, const SetupState&());
- MOCK_METHOD3(ConfigureCredentials,
- bool(const std::string&,
- const std::string&,
- chromeos::ErrorPtr*));
- MOCK_CONST_METHOD0(GetCurrentlyConnectedSsid, std::string());
- MOCK_CONST_METHOD0(GetHostedSsid, std::string());
- MOCK_CONST_METHOD0(GetTypes, std::set<WifiType>());
-
- MockWifiDelegate() {
- EXPECT_CALL(*this, GetConnectionState())
- .WillRepeatedly(ReturnRef(connection_state_));
- EXPECT_CALL(*this, GetSetupState()).WillRepeatedly(ReturnRef(setup_state_));
- EXPECT_CALL(*this, GetCurrentlyConnectedSsid())
- .WillRepeatedly(Return("TestSsid"));
- EXPECT_CALL(*this, GetHostedSsid()).WillRepeatedly(Return(""));
- EXPECT_CALL(*this, GetTypes())
- .WillRepeatedly(Return(std::set<WifiType>{WifiType::kWifi24}));
- }
-
- ConnectionState connection_state_{ConnectionState::kOffline};
- SetupState setup_state_{SetupState::kNone};
-};
-
-class MockCloudDelegate : public CloudDelegate {
- public:
- MOCK_CONST_METHOD2(GetModelId, bool(std::string*, chromeos::ErrorPtr*));
- MOCK_CONST_METHOD2(GetName, bool(std::string*, chromeos::ErrorPtr*));
- MOCK_CONST_METHOD0(GetDescription, std::string());
- MOCK_CONST_METHOD0(GetLocation, std::string());
- MOCK_METHOD5(UpdateDeviceInfo,
- void(const std::string&,
- const std::string&,
- const std::string&,
- const base::Closure&,
- const ErrorCallback&));
- MOCK_CONST_METHOD0(GetOemName, std::string());
- MOCK_CONST_METHOD0(GetModelName, std::string());
- MOCK_CONST_METHOD0(GetServices, std::set<std::string>());
- MOCK_CONST_METHOD0(GetAnonymousMaxScope, AuthScope());
- MOCK_CONST_METHOD0(GetConnectionState, const ConnectionState&());
- MOCK_CONST_METHOD0(GetSetupState, const SetupState&());
- MOCK_METHOD3(Setup,
- bool(const std::string&,
- const std::string&,
- chromeos::ErrorPtr*));
- MOCK_CONST_METHOD0(GetCloudId, std::string());
- MOCK_CONST_METHOD0(GetState, const base::DictionaryValue&());
- MOCK_CONST_METHOD0(GetCommandDef, const base::DictionaryValue&());
- MOCK_METHOD4(AddCommand,
- void(const base::DictionaryValue&,
- const UserInfo&,
- const SuccessCallback&,
- const ErrorCallback&));
- MOCK_METHOD4(GetCommand,
- void(const std::string&,
- const UserInfo&,
- const SuccessCallback&,
- const ErrorCallback&));
- MOCK_METHOD4(CancelCommand,
- void(const std::string&,
- const UserInfo&,
- const SuccessCallback&,
- const ErrorCallback&));
- MOCK_METHOD3(ListCommands,
- void(const UserInfo&,
- const SuccessCallback&,
- const ErrorCallback&));
-
- MockCloudDelegate() {
- EXPECT_CALL(*this, GetModelId(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<0>("ABMID"), Return(true)));
- EXPECT_CALL(*this, GetName(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<0>("TestDevice"), Return(true)));
- EXPECT_CALL(*this, GetDescription()).WillRepeatedly(Return(""));
- EXPECT_CALL(*this, GetLocation()).WillRepeatedly(Return(""));
- EXPECT_CALL(*this, UpdateDeviceInfo(_, _, _, _, _))
- .WillRepeatedly(RunCallback<3>());
- EXPECT_CALL(*this, GetOemName()).WillRepeatedly(Return("Chromium"));
- EXPECT_CALL(*this, GetModelName()).WillRepeatedly(Return("Brillo"));
- EXPECT_CALL(*this, GetServices())
- .WillRepeatedly(Return(std::set<std::string>{}));
- EXPECT_CALL(*this, GetAnonymousMaxScope())
- .WillRepeatedly(Return(AuthScope::kUser));
- EXPECT_CALL(*this, GetConnectionState())
- .WillRepeatedly(ReturnRef(connection_state_));
- EXPECT_CALL(*this, GetSetupState()).WillRepeatedly(ReturnRef(setup_state_));
- EXPECT_CALL(*this, GetCloudId()).WillRepeatedly(Return("TestCloudId"));
- test_dict_.Set("test", new base::DictionaryValue);
- EXPECT_CALL(*this, GetCommandDef()).WillRepeatedly(ReturnRef(test_dict_));
- EXPECT_CALL(*this, GetState()).WillRepeatedly(ReturnRef(test_dict_));
- }
-
- ConnectionState connection_state_{ConnectionState::kOnline};
- SetupState setup_state_{SetupState::kNone};
- base::DictionaryValue test_dict_;
-};
-
-class MockIdentityDelegate : public IdentityDelegate {
- public:
- MOCK_CONST_METHOD0(GetId, std::string());
-
- MockIdentityDelegate() {
- EXPECT_CALL(*this, GetId()).WillRepeatedly(Return("TestId"));
- }
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_MOCK_DELEGATES_H_
diff --git a/buffet/privet/openssl_utils.cc b/buffet/privet/openssl_utils.cc
deleted file mode 100644
index bcaf422..0000000
--- a/buffet/privet/openssl_utils.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/openssl_utils.h"
-
-#include <algorithm>
-
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-
-#include <base/logging.h>
-
-namespace privetd {
-
-chromeos::Blob HmacSha256(const chromeos::SecureBlob& key,
- const chromeos::Blob& data) {
- chromeos::Blob mac(kSha256OutputSize);
- uint32_t len = 0;
- CHECK(HMAC(EVP_sha256(), key.data(), key.size(), data.data(), data.size(),
- mac.data(), &len));
- CHECK_EQ(len, kSha256OutputSize);
- return mac;
-}
-
-} // namespace privetd
diff --git a/buffet/privet/openssl_utils.h b/buffet/privet/openssl_utils.h
deleted file mode 100644
index 587b60c..0000000
--- a/buffet/privet/openssl_utils.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_OPENSSL_UTILS_H_
-#define BUFFET_PRIVET_OPENSSL_UTILS_H_
-
-#include <string>
-#include <vector>
-
-#include <chromeos/secure_blob.h>
-
-namespace privetd {
-
-const size_t kSha256OutputSize = 32;
-
-chromeos::Blob HmacSha256(const chromeos::SecureBlob& key,
- const chromeos::Blob& data);
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_OPENSSL_UTILS_H_
diff --git a/buffet/privet/peerd_client.cc b/buffet/privet/peerd_client.cc
deleted file mode 100644
index b052ab1..0000000
--- a/buffet/privet/peerd_client.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/peerd_client.h"
-
-#include <map>
-
-#include <base/message_loop/message_loop.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/privet/cloud_delegate.h"
-#include "buffet/privet/device_delegate.h"
-#include "buffet/privet/wifi_bootstrap_manager.h"
-#include "buffet/privet/wifi_ssid_generator.h"
-
-using chromeos::string_utils::Join;
-using org::chromium::peerd::PeerProxy;
-
-namespace privetd {
-
-namespace {
-
-// Commit changes only if no update request happened during the timeout.
-// Usually updates happen in batches, so we don't want to flood network with
-// updates relevant for a short amount of time.
-const int kCommitTimeoutSeconds = 1;
-
-// The name of the service we'll expose via peerd.
-const char kPrivetServiceId[] = "privet";
-const char kSelfPath[] = "/org/chromium/peerd/Self";
-
-void OnError(const std::string& operation, chromeos::Error* error) {
- LOG(ERROR) << operation << " failed:" << error->GetMessage();
-}
-
-} // namespace
-
-PeerdClient::PeerdClient(const scoped_refptr<dbus::Bus>& bus,
- const DeviceDelegate* device,
- const CloudDelegate* cloud,
- const WifiDelegate* wifi)
- : peerd_object_manager_proxy_{bus},
- device_{device},
- cloud_{cloud},
- wifi_{wifi} {
- CHECK(device_);
- CHECK(cloud_);
- peerd_object_manager_proxy_.SetManagerAddedCallback(
- base::Bind(&PeerdClient::OnPeerdOnline, weak_ptr_factory_.GetWeakPtr()));
- peerd_object_manager_proxy_.SetManagerRemovedCallback(
- base::Bind(&PeerdClient::OnPeerdOffline, weak_ptr_factory_.GetWeakPtr()));
- peerd_object_manager_proxy_.SetPeerAddedCallback(
- base::Bind(&PeerdClient::OnNewPeer, weak_ptr_factory_.GetWeakPtr()));
-}
-
-PeerdClient::~PeerdClient() {
- RemoveService();
-}
-
-std::string PeerdClient::GetId() const {
- return device_id_;
-}
-
-void PeerdClient::Update() {
- // Abort pending updates, and wait for more changes.
- restart_weak_ptr_factory_.InvalidateWeakPtrs();
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&PeerdClient::UpdateImpl,
- restart_weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(kCommitTimeoutSeconds));
-}
-
-void PeerdClient::OnNewPeer(PeerProxy* peer) {
- if (!peer || peer->GetObjectPath().value() != kSelfPath)
- return;
- peer->SetPropertyChangedCallback(base::Bind(
- &PeerdClient::OnPeerPropertyChanged, weak_ptr_factory_.GetWeakPtr()));
- OnPeerPropertyChanged(peer, PeerProxy::UUIDName());
-}
-
-void PeerdClient::OnPeerPropertyChanged(PeerProxy* peer,
- const std::string& property_name) {
- if (property_name != PeerProxy::UUIDName() ||
- peer->GetObjectPath().value() != kSelfPath)
- return;
- const std::string new_id{peer->uuid()};
- if (new_id != device_id_) {
- device_id_ = new_id;
- Update();
- }
-}
-
-void PeerdClient::OnPeerdOnline(
- org::chromium::peerd::ManagerProxy* manager_proxy) {
- peerd_manager_proxy_ = manager_proxy;
- VLOG(1) << "Peerd manager is online at '"
- << manager_proxy->GetObjectPath().value() << "'.";
- Update();
-}
-
-void PeerdClient::OnPeerdOffline(const dbus::ObjectPath& object_path) {
- peerd_manager_proxy_ = nullptr;
- VLOG(1) << "Peerd manager is now offline.";
-}
-
-void PeerdClient::ExposeService() {
- // Do nothing if peerd hasn't started yet.
- if (peerd_manager_proxy_ == nullptr)
- return;
-
- std::string name;
- std::string model_id;
- if (!cloud_->GetName(&name, nullptr) ||
- !cloud_->GetModelId(&model_id, nullptr)) {
- return;
- }
- DCHECK_EQ(model_id.size(), 5U);
-
- VLOG(1) << "Starting peerd advertising.";
- const uint16_t port = device_->GetHttpEnpoint().first;
- std::map<std::string, chromeos::Any> mdns_options{
- {"port", chromeos::Any{port}},
- };
- DCHECK_NE(port, 0);
-
- std::string services;
- if (!cloud_->GetServices().empty())
- services += "_";
- services += Join(",_", cloud_->GetServices());
-
- std::map<std::string, std::string> txt_record{
- {"txtvers", "3"},
- {"ty", name},
- {"services", services},
- {"id", GetId()},
- {"mmid", model_id},
- {"flags", WifiSsidGenerator{cloud_, wifi_}.GenerateFlags()},
- };
-
- if (!cloud_->GetCloudId().empty())
- txt_record.emplace("gcd_id", cloud_->GetCloudId());
-
- if (!cloud_->GetDescription().empty())
- txt_record.emplace("note", cloud_->GetDescription());
-
- peerd_manager_proxy_->ExposeServiceAsync(
- kPrivetServiceId, txt_record, {{"mdns", mdns_options}}, base::Closure(),
- base::Bind(&OnError, "ExposeService"));
-}
-
-void PeerdClient::RemoveService() {
- if (peerd_manager_proxy_ == nullptr)
- return;
-
- VLOG(1) << "Stopping peerd advertising.";
- peerd_manager_proxy_->RemoveExposedServiceAsync(
- kPrivetServiceId, base::Closure(), base::Bind(&OnError, "RemoveService"));
-}
-
-void PeerdClient::UpdateImpl() {
- if (device_->GetHttpEnpoint().first == 0)
- return RemoveService();
- ExposeService();
-}
-
-} // namespace privetd
diff --git a/buffet/privet/peerd_client.h b/buffet/privet/peerd_client.h
deleted file mode 100644
index ae3d306..0000000
--- a/buffet/privet/peerd_client.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_PEERD_CLIENT_H_
-#define BUFFET_PRIVET_PEERD_CLIENT_H_
-
-#include <memory>
-#include <string>
-
-#include <base/callback.h>
-#include <base/memory/ref_counted.h>
-
-#include "buffet/privet/identity_delegate.h"
-#include "peerd/dbus-proxies.h"
-
-namespace dbus {
-class Bus;
-} // namespace dbus
-
-namespace privetd {
-
-class CloudDelegate;
-class DeviceDelegate;
-class WifiDelegate;
-
-// Publishes prived service on mDns using peerd.
-class PeerdClient : public IdentityDelegate {
- public:
- PeerdClient(const scoped_refptr<dbus::Bus>& bus,
- const DeviceDelegate* device,
- const CloudDelegate* cloud,
- const WifiDelegate* wifi);
- ~PeerdClient();
-
- // Get the unique identifier for this device. Note that if peerd has
- // never been seen, this may be the empty string.
- std::string GetId() const override;
-
- // Updates published information. Removes service if HTTP is not alive.
- void Update();
-
- private:
- void OnPeerdOnline(org::chromium::peerd::ManagerProxy* manager_proxy);
- void OnPeerdOffline(const dbus::ObjectPath& object_path);
- void OnNewPeer(org::chromium::peerd::PeerProxy* peer_proxy);
- void OnPeerPropertyChanged(org::chromium::peerd::PeerProxy* peer_proxy,
- const std::string& property_name);
-
- void ExposeService();
- void RemoveService();
-
- void UpdateImpl();
-
- org::chromium::peerd::ObjectManagerProxy peerd_object_manager_proxy_;
- // |peerd_manager_proxy_| is owned by |peerd_object_manager_proxy_|.
- org::chromium::peerd::ManagerProxy* peerd_manager_proxy_{nullptr};
-
- const DeviceDelegate* device_{nullptr};
- const CloudDelegate* cloud_{nullptr};
- const WifiDelegate* wifi_{nullptr};
-
- // Cached value of the device ID that we got from peerd.
- std::string device_id_;
-
- base::WeakPtrFactory<PeerdClient> restart_weak_ptr_factory_{this};
- base::WeakPtrFactory<PeerdClient> weak_ptr_factory_{this};
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_PEERD_CLIENT_H_
diff --git a/buffet/privet/privet_handler.cc b/buffet/privet/privet_handler.cc
deleted file mode 100644
index 5c3d0c2..0000000
--- a/buffet/privet/privet_handler.cc
+++ /dev/null
@@ -1,948 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/privet_handler.h"
-
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-
-#include <base/bind.h>
-#include <base/location.h>
-#include <base/stl_util.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/stringprintf.h>
-#include <base/values.h>
-#include <chromeos/http/http_request.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/privet/cloud_delegate.h"
-#include "buffet/privet/constants.h"
-#include "buffet/privet/device_delegate.h"
-#include "buffet/privet/identity_delegate.h"
-#include "buffet/privet/security_delegate.h"
-#include "buffet/privet/wifi_delegate.h"
-
-namespace privetd {
-
-namespace {
-
-const char kInfoVersionKey[] = "version";
-const char kInfoVersionValue[] = "3.0";
-
-const char kNameKey[] = "name";
-const char kDescrptionKey[] = "description";
-const char kLocationKey[] = "location";
-
-const char kGcdKey[] = "gcd";
-const char kWifiKey[] = "wifi";
-const char kStatusKey[] = "status";
-const char kErrorKey[] = "error";
-const char kCryptoKey[] = "crypto";
-const char kStatusErrorValue[] = "error";
-
-const char kInfoIdKey[] = "id";
-const char kInfoServicesKey[] = "services";
-
-const char kInfoEndpointsKey[] = "endpoints";
-const char kInfoEndpointsHttpPortKey[] = "httpPort";
-const char kInfoEndpointsHttpUpdatePortKey[] = "httpUpdatesPort";
-const char kInfoEndpointsHttpsPortKey[] = "httpsPort";
-const char kInfoEndpointsHttpsUpdatePortKey[] = "httpsUpdatesPort";
-
-const char kInfoModelIdKey[] = "modelManifestId";
-const char kInfoModelManifestKey[] = "basicModelManifest";
-const char kInfoManifestUiDeviceKind[] = "uiDeviceKind";
-const char kInfoManifestOemName[] = "oemName";
-const char kInfoManifestModelName[] = "modelName";
-
-const char kInfoAuthenticationKey[] = "authentication";
-
-const char kInfoAuthAnonymousMaxScopeKey[] = "anonymousMaxScope";
-
-const char kInfoWifiCapabilitiesKey[] = "capabilities";
-const char kInfoWifiSsidKey[] = "ssid";
-const char kInfoWifiHostedSsidKey[] = "hostedSsid";
-
-const char kInfoUptimeKey[] = "uptime";
-
-const char kPairingKey[] = "pairing";
-const char kPairingSessionIdKey[] = "sessionId";
-const char kPairingDeviceCommitmentKey[] = "deviceCommitment";
-const char kPairingClientCommitmentKey[] = "clientCommitment";
-const char kPairingFingerprintKey[] = "certFingerprint";
-const char kPairingSignatureKey[] = "certSignature";
-
-const char kAuthTypeAnonymousValue[] = "anonymous";
-const char kAuthTypePairingValue[] = "pairing";
-
-const char kAuthModeKey[] = "mode";
-const char kAuthCodeKey[] = "authCode";
-const char kAuthRequestedScopeKey[] = "requestedScope";
-const char kAuthScopeAutoValue[] = "auto";
-
-const char kAuthAccessTokenKey[] = "accessToken";
-const char kAuthTokenTypeKey[] = "tokenType";
-const char kAuthExpiresInKey[] = "expiresIn";
-const char kAuthScopeKey[] = "scope";
-
-const char kAuthorizationHeaderPrefix[] = "Privet";
-
-const char kErrorCodeKey[] = "code";
-const char kErrorMessageKey[] = "message";
-const char kErrorDebugInfoKey[] = "debugInfo";
-
-const char kSetupStartSsidKey[] = "ssid";
-const char kSetupStartPassKey[] = "passphrase";
-const char kSetupStartTicketIdKey[] = "ticketId";
-const char kSetupStartUserKey[] = "user";
-
-const char kFingerprintKey[] = "fingerprint";
-const char kStateKey[] = "state";
-const char kCommandsKey[] = "commands";
-const char kCommandsIdKey[] = "id";
-
-const char kInvalidParamValueFormat[] = "Invalid parameter: '%s'='%s'";
-
-const int kAccessTokenExpirationSeconds = 3600;
-
-// Threshold to reduce probability of expiration because of clock difference
-// between device and client. Value is just a guess.
-const int kAccessTokenExpirationThresholdSeconds = 300;
-
-template <class Container>
-std::unique_ptr<base::ListValue> ToValue(const Container& list) {
- std::unique_ptr<base::ListValue> value_list(new base::ListValue());
- for (const std::string& val : list)
- value_list->AppendString(val);
- return value_list;
-}
-
-template <typename T>
-class EnumToStringMap final {
- public:
- static std::string FindNameById(T id) {
- for (const Map& m : kMap) {
- if (m.id == id) {
- CHECK(m.name);
- return m.name;
- }
- }
- NOTREACHED() << static_cast<int>(id) << " is not part of "
- << typeid(T).name();
- return std::string();
- }
-
- static bool FindIdByName(const std::string& name, T* id) {
- for (const Map& m : kMap) {
- if (m.name && m.name == name) {
- *id = m.id;
- return true;
- }
- }
- return false;
- }
-
- private:
- struct Map {
- const T id;
- const char* const name;
- };
- static const Map kMap[];
-};
-
-template <>
-const EnumToStringMap<ConnectionState::Status>::Map
- EnumToStringMap<ConnectionState::Status>::kMap[] = {
- {ConnectionState::kDisabled, "disabled"},
- {ConnectionState::kUnconfigured, "unconfigured"},
- {ConnectionState::kConnecting, "connecting"},
- {ConnectionState::kOnline, "online"},
- {ConnectionState::kOffline, "offline"},
-};
-
-template <>
-const EnumToStringMap<SetupState::Status>::Map
- EnumToStringMap<SetupState::Status>::kMap[] = {
- {SetupState::kNone, nullptr},
- {SetupState::kInProgress, "inProgress"},
- {SetupState::kSuccess, "success"},
-};
-
-template <>
-const EnumToStringMap<WifiType>::Map EnumToStringMap<WifiType>::kMap[] = {
- {WifiType::kWifi24, "2.4GHz"},
- {WifiType::kWifi50, "5.0GHz"},
-};
-
-template <>
-const EnumToStringMap<PairingType>::Map EnumToStringMap<PairingType>::kMap[] = {
- {PairingType::kPinCode, "pinCode"},
- {PairingType::kEmbeddedCode, "embeddedCode"},
- {PairingType::kUltrasound32, "ultrasound32"},
- {PairingType::kAudible32, "audible32"},
-};
-
-template <>
-const EnumToStringMap<CryptoType>::Map EnumToStringMap<CryptoType>::kMap[] = {
- {CryptoType::kNone, "none"},
- {CryptoType::kSpake_p224, "p224_spake2"},
- {CryptoType::kSpake_p256, "p256_spake2"},
-};
-
-template <>
-const EnumToStringMap<AuthScope>::Map EnumToStringMap<AuthScope>::kMap[] = {
- {AuthScope::kNone, "none"},
- {AuthScope::kViewer, "viewer"},
- {AuthScope::kUser, "user"},
- {AuthScope::kOwner, "owner"},
-};
-
-struct {
- const char* const reason;
- int code;
-} kReasonToCode[] = {
- {errors::kInvalidClientCommitment, chromeos::http::status_code::Forbidden},
- {errors::kInvalidFormat, chromeos::http::status_code::BadRequest},
- {errors::kMissingAuthorization, chromeos::http::status_code::Denied},
- {errors::kInvalidAuthorization, chromeos::http::status_code::Denied},
- {errors::kInvalidAuthorizationScope,
- chromeos::http::status_code::Forbidden},
- {errors::kAuthorizationExpired, chromeos::http::status_code::Forbidden},
- {errors::kCommitmentMismatch, chromeos::http::status_code::Forbidden},
- {errors::kUnknownSession, chromeos::http::status_code::NotFound},
- {errors::kInvalidAuthCode, chromeos::http::status_code::Forbidden},
- {errors::kInvalidAuthMode, chromeos::http::status_code::BadRequest},
- {errors::kInvalidRequestedScope, chromeos::http::status_code::BadRequest},
- {errors::kAccessDenied, chromeos::http::status_code::Forbidden},
- {errors::kInvalidParams, chromeos::http::status_code::BadRequest},
- {errors::kSetupUnavailable, chromeos::http::status_code::BadRequest},
- {errors::kDeviceBusy, chromeos::http::status_code::ServiceUnavailable},
- {errors::kInvalidState, chromeos::http::status_code::InternalServerError},
- {errors::kNotFound, chromeos::http::status_code::NotFound},
- {errors::kNotImplemented, chromeos::http::status_code::NotSupported},
-};
-
-template <typename T>
-std::string EnumToString(T id) {
- return EnumToStringMap<T>::FindNameById(id);
-}
-
-template <typename T>
-bool StringToEnum(const std::string& name, T* id) {
- return EnumToStringMap<T>::FindIdByName(name, id);
-}
-
-AuthScope AuthScopeFromString(const std::string& scope, AuthScope auto_scope) {
- if (scope == kAuthScopeAutoValue)
- return auto_scope;
- AuthScope scope_id = AuthScope::kNone;
- StringToEnum(scope, &scope_id);
- return scope_id;
-}
-
-std::string GetAuthTokenFromAuthHeader(const std::string& auth_header) {
- std::string name;
- std::string value;
- chromeos::string_utils::SplitAtFirst(auth_header, " ", &name, &value);
- return value;
-}
-
-std::unique_ptr<base::DictionaryValue> ErrorInfoToJson(
- const chromeos::Error& error) {
- std::unique_ptr<base::DictionaryValue> output{new base::DictionaryValue};
- output->SetString(kErrorMessageKey, error.GetMessage());
- output->SetString(kErrorCodeKey, error.GetCode());
- return output;
-}
-
-// Creates JSON similar to GCD server error format.
-std::unique_ptr<base::DictionaryValue> ErrorToJson(
- const chromeos::Error& error) {
- std::unique_ptr<base::DictionaryValue> output{ErrorInfoToJson(error)};
-
- // Optional debug information.
- std::unique_ptr<base::ListValue> errors{new base::ListValue};
- for (const chromeos::Error* it = &error; it; it = it->GetInnerError()) {
- std::unique_ptr<base::DictionaryValue> inner{ErrorInfoToJson(*it)};
- tracked_objects::Location location{it->GetLocation().function_name.c_str(),
- it->GetLocation().file_name.c_str(),
- it->GetLocation().line_number,
- nullptr};
- inner->SetString(kErrorDebugInfoKey, location.ToString());
- errors->Append(inner.release());
- }
- output->Set(kErrorDebugInfoKey, errors.release());
- return output;
-}
-
-template <class T>
-void SetState(const T& state, base::DictionaryValue* parent) {
- if (!state.error()) {
- parent->SetString(kStatusKey, EnumToString(state.status()));
- return;
- }
- parent->SetString(kStatusKey, kStatusErrorValue);
- parent->Set(kErrorKey, ErrorToJson(*state.error()).release());
-}
-
-void ReturnError(const chromeos::Error& error,
- const PrivetHandler::RequestCallback& callback) {
- int code = chromeos::http::status_code::InternalServerError;
- for (const auto& it : kReasonToCode) {
- if (error.HasError(errors::kDomain, it.reason)) {
- code = it.code;
- break;
- }
- }
- std::unique_ptr<base::DictionaryValue> output{new base::DictionaryValue};
- output->Set(kErrorKey, ErrorToJson(error).release());
- callback.Run(code, *output);
-}
-
-void OnCommandRequestSucceeded(const PrivetHandler::RequestCallback& callback,
- const base::DictionaryValue& output) {
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void OnCommandRequestFailed(const PrivetHandler::RequestCallback& callback,
- chromeos::Error* error) {
- if (error->HasError("gcd", "unknown_command")) {
- chromeos::ErrorPtr new_error = error->Clone();
- chromeos::Error::AddTo(&new_error, FROM_HERE, errors::kDomain,
- errors::kNotFound, "Unknown command ID");
- return ReturnError(*new_error, callback);
- }
- if (error->HasError("gcd", "access_denied")) {
- chromeos::ErrorPtr new_error = error->Clone();
- chromeos::Error::AddTo(&new_error, FROM_HERE, errors::kDomain,
- errors::kAccessDenied, error->GetMessage());
- return ReturnError(*new_error, callback);
- }
- return ReturnError(*error, callback);
-}
-
-std::string GetDeviceKind(const std::string& manifest_id) {
- CHECK_EQ(5u, manifest_id.size());
- std::string kind = manifest_id.substr(0, 2);
- if (kind == "AC")
- return "accessPoint";
- if (kind == "AK")
- return "aggregator";
- if (kind == "AM")
- return "camera";
- if (kind == "AB")
- return "developmentBoard";
- if (kind == "AE")
- return "printer";
- if (kind == "AF")
- return "scanner";
- if (kind == "AD")
- return "speaker";
- if (kind == "AL")
- return "storage";
- if (kind == "AJ")
- return "toy";
- if (kind == "AA")
- return "vendor";
- if (kind == "AN")
- return "video";
- LOG(FATAL) << "Invalid model id: " << manifest_id;
- return std::string();
-}
-
-std::unique_ptr<base::DictionaryValue> CreateManifestSection(
- const std::string& model_id,
- const CloudDelegate& cloud) {
- std::unique_ptr<base::DictionaryValue> manifest(new base::DictionaryValue());
- manifest->SetString(kInfoManifestUiDeviceKind, GetDeviceKind(model_id));
- manifest->SetString(kInfoManifestOemName, cloud.GetOemName());
- manifest->SetString(kInfoManifestModelName, cloud.GetModelName());
- return manifest;
-}
-
-std::unique_ptr<base::DictionaryValue> CreateEndpointsSection(
- const DeviceDelegate& device) {
- std::unique_ptr<base::DictionaryValue> endpoints(new base::DictionaryValue());
- auto http_endpoint = device.GetHttpEnpoint();
- endpoints->SetInteger(kInfoEndpointsHttpPortKey, http_endpoint.first);
- endpoints->SetInteger(kInfoEndpointsHttpUpdatePortKey, http_endpoint.second);
-
- auto https_endpoint = device.GetHttpsEnpoint();
- endpoints->SetInteger(kInfoEndpointsHttpsPortKey, https_endpoint.first);
- endpoints->SetInteger(kInfoEndpointsHttpsUpdatePortKey,
- https_endpoint.second);
-
- return endpoints;
-}
-
-std::unique_ptr<base::DictionaryValue> CreateInfoAuthSection(
- const SecurityDelegate& security,
- AuthScope anonymous_max_scope) {
- std::unique_ptr<base::DictionaryValue> auth(new base::DictionaryValue());
-
- auth->SetString(kInfoAuthAnonymousMaxScopeKey,
- EnumToString(anonymous_max_scope));
-
- std::unique_ptr<base::ListValue> pairing_types(new base::ListValue());
- for (PairingType type : security.GetPairingTypes())
- pairing_types->AppendString(EnumToString(type));
- auth->Set(kPairingKey, pairing_types.release());
-
- std::unique_ptr<base::ListValue> auth_types(new base::ListValue());
- auth_types->AppendString(kAuthTypeAnonymousValue);
- auth_types->AppendString(kAuthTypePairingValue);
-
- // TODO(vitalybuka): Implement cloud auth.
- // if (cloud.GetConnectionState().IsStatusEqual(ConnectionState::kOnline)) {
- // auth_types->AppendString(kAuthTypeCloudValue);
- // }
- auth->Set(kAuthModeKey, auth_types.release());
-
- std::unique_ptr<base::ListValue> crypto_types(new base::ListValue());
- for (CryptoType type : security.GetCryptoTypes())
- crypto_types->AppendString(EnumToString(type));
- auth->Set(kCryptoKey, crypto_types.release());
-
- return auth;
-}
-
-std::unique_ptr<base::DictionaryValue> CreateWifiSection(
- const WifiDelegate& wifi) {
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
-
- std::unique_ptr<base::ListValue> capabilities(new base::ListValue());
- for (WifiType type : wifi.GetTypes())
- capabilities->AppendString(EnumToString(type));
- result->Set(kInfoWifiCapabilitiesKey, capabilities.release());
-
- result->SetString(kInfoWifiSsidKey, wifi.GetCurrentlyConnectedSsid());
-
- std::string hosted_ssid = wifi.GetHostedSsid();
- const ConnectionState& state = wifi.GetConnectionState();
- if (!hosted_ssid.empty()) {
- DCHECK(!state.IsStatusEqual(ConnectionState::kDisabled));
- DCHECK(!state.IsStatusEqual(ConnectionState::kOnline));
- result->SetString(kInfoWifiHostedSsidKey, hosted_ssid);
- }
- SetState(state, result.get());
- return result;
-}
-
-std::unique_ptr<base::DictionaryValue> CreateGcdSection(
- const CloudDelegate& cloud) {
- std::unique_ptr<base::DictionaryValue> gcd(new base::DictionaryValue());
- gcd->SetString(kInfoIdKey, cloud.GetCloudId());
- SetState(cloud.GetConnectionState(), gcd.get());
- return gcd;
-}
-
-AuthScope GetAnonymousMaxScope(const CloudDelegate& cloud,
- const WifiDelegate* wifi) {
- if (wifi && !wifi->GetHostedSsid().empty())
- return AuthScope::kNone;
- return cloud.GetAnonymousMaxScope();
-}
-
-} // namespace
-
-PrivetHandler::PrivetHandler(CloudDelegate* cloud,
- DeviceDelegate* device,
- SecurityDelegate* security,
- WifiDelegate* wifi,
- IdentityDelegate* identity)
- : cloud_(cloud),
- device_(device),
- security_(security),
- wifi_(wifi),
- identity_(identity) {
- CHECK(cloud_);
- CHECK(device_);
- CHECK(security_);
- cloud_observer_.Add(cloud_);
-
- AddHandler("/privet/info", &PrivetHandler::HandleInfo, AuthScope::kNone);
- AddHandler("/privet/v3/pairing/start", &PrivetHandler::HandlePairingStart,
- AuthScope::kNone);
- AddHandler("/privet/v3/pairing/confirm", &PrivetHandler::HandlePairingConfirm,
- AuthScope::kNone);
- AddHandler("/privet/v3/pairing/cancel", &PrivetHandler::HandlePairingCancel,
- AuthScope::kNone);
- AddHandler("/privet/v3/auth", &PrivetHandler::HandleAuth, AuthScope::kNone);
- AddHandler("/privet/v3/setup/start", &PrivetHandler::HandleSetupStart,
- AuthScope::kOwner);
- AddHandler("/privet/v3/setup/status", &PrivetHandler::HandleSetupStatus,
- AuthScope::kOwner);
- AddHandler("/privet/v3/state", &PrivetHandler::HandleState,
- AuthScope::kViewer);
- AddHandler("/privet/v3/commandDefs", &PrivetHandler::HandleCommandDefs,
- AuthScope::kViewer);
- AddHandler("/privet/v3/commands/execute",
- &PrivetHandler::HandleCommandsExecute, AuthScope::kViewer);
- AddHandler("/privet/v3/commands/status", &PrivetHandler::HandleCommandsStatus,
- AuthScope::kViewer);
- AddHandler("/privet/v3/commands/cancel", &PrivetHandler::HandleCommandsCancel,
- AuthScope::kViewer);
- AddHandler("/privet/v3/commands/list", &PrivetHandler::HandleCommandsList,
- AuthScope::kViewer);
-}
-
-PrivetHandler::~PrivetHandler() {
-}
-
-void PrivetHandler::OnCommandDefsChanged() {
- ++command_defs_fingerprint_;
-}
-
-void PrivetHandler::OnStateChanged() {
- ++state_fingerprint_;
-}
-
-void PrivetHandler::HandleRequest(const std::string& api,
- const std::string& auth_header,
- const base::DictionaryValue* input,
- const RequestCallback& callback) {
- chromeos::ErrorPtr error;
- if (!input) {
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
- errors::kInvalidFormat, "Malformed JSON");
- return ReturnError(*error, callback);
- }
- auto handler = handlers_.find(api);
- if (handler == handlers_.end()) {
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
- errors::kNotFound, "Path not found");
- return ReturnError(*error, callback);
- }
- if (auth_header.empty()) {
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
- errors::kMissingAuthorization,
- "Authorization header must not be empty");
- return ReturnError(*error, callback);
- }
- std::string token = GetAuthTokenFromAuthHeader(auth_header);
- if (token.empty()) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidAuthorization,
- "Invalid authorization header: %s", auth_header.c_str());
- return ReturnError(*error, callback);
- }
- UserInfo user_info;
- if (token != kAuthTypeAnonymousValue) {
- base::Time time;
- user_info = security_->ParseAccessToken(token, &time);
- if (user_info.scope() == AuthScope::kNone) {
- chromeos::Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
- errors::kInvalidAuthorization,
- "Invalid access token: %s", token.c_str());
- return ReturnError(*error, callback);
- }
- time += base::TimeDelta::FromSeconds(kAccessTokenExpirationSeconds);
- time +=
- base::TimeDelta::FromSeconds(kAccessTokenExpirationThresholdSeconds);
- if (time < base::Time::Now()) {
- chromeos::Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
- errors::kAuthorizationExpired,
- "Token expired: %s", token.c_str());
- return ReturnError(*error, callback);
- }
- }
-
- if (handler->second.first > user_info.scope()) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidAuthorizationScope,
- "Scope '%s' does not allow '%s'",
- EnumToString(user_info.scope()).c_str(), api.c_str());
- return ReturnError(*error, callback);
- }
- (this->*handler->second.second)(*input, user_info, callback);
-}
-
-void PrivetHandler::AddHandler(const std::string& path,
- ApiHandler handler,
- AuthScope scope) {
- CHECK(handlers_.emplace(path, std::make_pair(scope, handler)).second);
-}
-
-void PrivetHandler::HandleInfo(const base::DictionaryValue&,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- base::DictionaryValue output;
-
- chromeos::ErrorPtr error;
-
- std::string name;
- std::string model_id;
- if (!cloud_->GetName(&name, &error) ||
- !cloud_->GetModelId(&model_id, &error)) {
- return ReturnError(*error, callback);
- }
-
- output.SetString(kInfoVersionKey, kInfoVersionValue);
- output.SetString(kInfoIdKey, identity_->GetId());
- output.SetString(kNameKey, name);
-
- std::string description{cloud_->GetDescription()};
- if (!description.empty())
- output.SetString(kDescrptionKey, description);
-
- std::string location{cloud_->GetLocation()};
- if (!location.empty())
- output.SetString(kLocationKey, location);
-
- output.SetString(kInfoModelIdKey, model_id);
- output.Set(kInfoModelManifestKey,
- CreateManifestSection(model_id, *cloud_).release());
- output.Set(kInfoServicesKey, ToValue(cloud_->GetServices()).release());
-
- output.Set(kInfoAuthenticationKey,
- CreateInfoAuthSection(
- *security_, GetAnonymousMaxScope(*cloud_, wifi_)).release());
-
- output.Set(kInfoEndpointsKey, CreateEndpointsSection(*device_).release());
-
- if (wifi_)
- output.Set(kWifiKey, CreateWifiSection(*wifi_).release());
-
- output.Set(kGcdKey, CreateGcdSection(*cloud_).release());
-
- output.SetInteger(kInfoUptimeKey, device_->GetUptime().InSeconds());
-
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandlePairingStart(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- chromeos::ErrorPtr error;
-
- std::string pairing_str;
- input.GetString(kPairingKey, &pairing_str);
-
- std::string crypto_str;
- input.GetString(kCryptoKey, &crypto_str);
-
- PairingType pairing;
- std::set<PairingType> modes = security_->GetPairingTypes();
- if (!StringToEnum(pairing_str, &pairing) || !ContainsKey(modes, pairing)) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidParams,
- kInvalidParamValueFormat, kPairingKey, pairing_str.c_str());
- return ReturnError(*error, callback);
- }
-
- CryptoType crypto;
- std::set<CryptoType> cryptos = security_->GetCryptoTypes();
- if (!StringToEnum(crypto_str, &crypto) || !ContainsKey(cryptos, crypto)) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidParams,
- kInvalidParamValueFormat, kCryptoKey, crypto_str.c_str());
- return ReturnError(*error, callback);
- }
-
- std::string id;
- std::string commitment;
- if (!security_->StartPairing(pairing, crypto, &id, &commitment, &error))
- return ReturnError(*error, callback);
-
- base::DictionaryValue output;
- output.SetString(kPairingSessionIdKey, id);
- output.SetString(kPairingDeviceCommitmentKey, commitment);
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandlePairingConfirm(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- std::string id;
- input.GetString(kPairingSessionIdKey, &id);
-
- std::string commitment;
- input.GetString(kPairingClientCommitmentKey, &commitment);
-
- std::string fingerprint;
- std::string signature;
- chromeos::ErrorPtr error;
- if (!security_->ConfirmPairing(id, commitment, &fingerprint, &signature,
- &error)) {
- return ReturnError(*error, callback);
- }
-
- base::DictionaryValue output;
- output.SetString(kPairingFingerprintKey, fingerprint);
- output.SetString(kPairingSignatureKey, signature);
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandlePairingCancel(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- std::string id;
- input.GetString(kPairingSessionIdKey, &id);
-
- chromeos::ErrorPtr error;
- if (!security_->CancelPairing(id, &error))
- return ReturnError(*error, callback);
-
- base::DictionaryValue output;
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandleAuth(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- chromeos::ErrorPtr error;
-
- std::string auth_code_type;
- input.GetString(kAuthModeKey, &auth_code_type);
-
- std::string auth_code;
- input.GetString(kAuthCodeKey, &auth_code);
-
- AuthScope max_auth_scope = AuthScope::kNone;
- if (auth_code_type == kAuthTypeAnonymousValue) {
- max_auth_scope = GetAnonymousMaxScope(*cloud_, wifi_);
- } else if (auth_code_type == kAuthTypePairingValue) {
- if (!security_->IsValidPairingCode(auth_code)) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidAuthCode,
- kInvalidParamValueFormat, kAuthCodeKey, auth_code.c_str());
- return ReturnError(*error, callback);
- }
- max_auth_scope = AuthScope::kOwner;
- } else {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidAuthMode,
- kInvalidParamValueFormat, kAuthModeKey, auth_code_type.c_str());
- return ReturnError(*error, callback);
- }
-
- std::string requested_scope;
- input.GetString(kAuthRequestedScopeKey, &requested_scope);
-
- AuthScope requested_auth_scope =
- AuthScopeFromString(requested_scope, max_auth_scope);
- if (requested_auth_scope == AuthScope::kNone) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidRequestedScope,
- kInvalidParamValueFormat, kAuthRequestedScopeKey,
- requested_scope.c_str());
- return ReturnError(*error, callback);
- }
-
- if (requested_auth_scope > max_auth_scope) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kAccessDenied,
- "Scope '%s' is not allowed for '%s'",
- EnumToString(requested_auth_scope).c_str(), auth_code.c_str());
- return ReturnError(*error, callback);
- }
-
- base::DictionaryValue output;
- output.SetString(
- kAuthAccessTokenKey,
- security_->CreateAccessToken(
- UserInfo{requested_auth_scope, ++last_user_id_}, base::Time::Now()));
- output.SetString(kAuthTokenTypeKey, kAuthorizationHeaderPrefix);
- output.SetInteger(kAuthExpiresInKey, kAccessTokenExpirationSeconds);
- output.SetString(kAuthScopeKey, EnumToString(requested_auth_scope));
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandleSetupStart(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- std::string name;
- chromeos::ErrorPtr error;
- if (!cloud_->GetName(&name, &error))
- return ReturnError(*error, callback);
- input.GetString(kNameKey, &name);
-
- std::string description{cloud_->GetDescription()};
- input.GetString(kDescrptionKey, &description);
-
- std::string location{cloud_->GetLocation()};
- input.GetString(kLocationKey, &location);
-
- std::string ssid;
- std::string passphrase;
- std::string ticket;
- std::string user;
-
- const base::DictionaryValue* wifi = nullptr;
- if (input.GetDictionary(kWifiKey, &wifi)) {
- if (!wifi_ || wifi_->GetTypes().empty()) {
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
- errors::kSetupUnavailable,
- "WiFi setup unavailible");
- return ReturnError(*error, callback);
- }
- wifi->GetString(kSetupStartSsidKey, &ssid);
- if (ssid.empty()) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidParams,
- kInvalidParamValueFormat, kSetupStartSsidKey, "");
- return ReturnError(*error, callback);
- }
- wifi->GetString(kSetupStartPassKey, &passphrase);
- }
-
- const base::DictionaryValue* registration = nullptr;
- if (input.GetDictionary(kGcdKey, ®istration)) {
- registration->GetString(kSetupStartTicketIdKey, &ticket);
- if (ticket.empty()) {
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidParams,
- kInvalidParamValueFormat, kSetupStartTicketIdKey, "");
- return ReturnError(*error, callback);
- }
- registration->GetString(kSetupStartUserKey, &user);
- }
-
- cloud_->UpdateDeviceInfo(name, description, location,
- base::Bind(&PrivetHandler::OnUpdateDeviceInfoDone,
- weak_ptr_factory_.GetWeakPtr(), ssid,
- passphrase, ticket, user, callback),
- base::Bind(&OnCommandRequestFailed, callback));
-}
-
-void PrivetHandler::OnUpdateDeviceInfoDone(
- const std::string& ssid,
- const std::string& passphrase,
- const std::string& ticket,
- const std::string& user,
- const RequestCallback& callback) const {
- chromeos::ErrorPtr error;
-
- if (!ssid.empty() && !wifi_->ConfigureCredentials(ssid, passphrase, &error))
- return ReturnError(*error, callback);
-
- if (!ticket.empty() && !cloud_->Setup(ticket, user, &error))
- return ReturnError(*error, callback);
-
- ReplyWithSetupStatus(callback);
-}
-
-void PrivetHandler::HandleSetupStatus(const base::DictionaryValue&,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- ReplyWithSetupStatus(callback);
-}
-
-void PrivetHandler::ReplyWithSetupStatus(
- const RequestCallback& callback) const {
- base::DictionaryValue output;
-
- const SetupState& state = cloud_->GetSetupState();
- if (!state.IsStatusEqual(SetupState::kNone)) {
- base::DictionaryValue* gcd = new base::DictionaryValue;
- output.Set(kGcdKey, gcd);
- SetState(state, gcd);
- if (state.IsStatusEqual(SetupState::kSuccess))
- gcd->SetString(kInfoIdKey, cloud_->GetCloudId());
- }
-
- if (wifi_) {
- const SetupState& state = wifi_->GetSetupState();
- if (!state.IsStatusEqual(SetupState::kNone)) {
- base::DictionaryValue* wifi = new base::DictionaryValue;
- output.Set(kWifiKey, wifi);
- SetState(state, wifi);
- if (state.IsStatusEqual(SetupState::kSuccess))
- wifi->SetString(kInfoWifiSsidKey, wifi_->GetCurrentlyConnectedSsid());
- }
- }
-
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandleState(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- base::DictionaryValue output;
- base::DictionaryValue* defs = cloud_->GetState().DeepCopy();
- output.Set(kStateKey, defs);
- output.SetString(kFingerprintKey, base::IntToString(state_fingerprint_));
-
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandleCommandDefs(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- base::DictionaryValue output;
- base::DictionaryValue* defs = cloud_->GetCommandDef().DeepCopy();
- output.Set(kCommandsKey, defs);
- output.SetString(kFingerprintKey,
- base::IntToString(command_defs_fingerprint_));
-
- callback.Run(chromeos::http::status_code::Ok, output);
-}
-
-void PrivetHandler::HandleCommandsExecute(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- cloud_->AddCommand(input, user_info,
- base::Bind(&OnCommandRequestSucceeded, callback),
- base::Bind(&OnCommandRequestFailed, callback));
-}
-
-void PrivetHandler::HandleCommandsStatus(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- std::string id;
- if (!input.GetString(kCommandsIdKey, &id)) {
- chromeos::ErrorPtr error;
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidParams,
- kInvalidParamValueFormat, kCommandsIdKey, id.c_str());
- return ReturnError(*error, callback);
- }
- cloud_->GetCommand(id, user_info,
- base::Bind(&OnCommandRequestSucceeded, callback),
- base::Bind(&OnCommandRequestFailed, callback));
-}
-
-void PrivetHandler::HandleCommandsList(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- cloud_->ListCommands(user_info,
- base::Bind(&OnCommandRequestSucceeded, callback),
- base::Bind(&OnCommandRequestFailed, callback));
-}
-
-void PrivetHandler::HandleCommandsCancel(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback) {
- std::string id;
- if (!input.GetString(kCommandsIdKey, &id)) {
- chromeos::ErrorPtr error;
- chromeos::Error::AddToPrintf(
- &error, FROM_HERE, errors::kDomain, errors::kInvalidParams,
- kInvalidParamValueFormat, kCommandsIdKey, id.c_str());
- return ReturnError(*error, callback);
- }
- cloud_->CancelCommand(id, user_info,
- base::Bind(&OnCommandRequestSucceeded, callback),
- base::Bind(&OnCommandRequestFailed, callback));
-}
-
-bool StringToPairingType(const std::string& mode, PairingType* id) {
- return StringToEnum(mode, id);
-}
-
-std::string PairingTypeToString(PairingType id) {
- return EnumToString(id);
-}
-
-bool StringToAuthScope(const std::string& scope, AuthScope* id) {
- return StringToEnum(scope, id);
-}
-
-std::string AuthScopeToString(AuthScope id) {
- return EnumToString(id);
-}
-
-} // namespace privetd
diff --git a/buffet/privet/privet_handler.h b/buffet/privet/privet_handler.h
deleted file mode 100644
index bb86c0a..0000000
--- a/buffet/privet/privet_handler.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_PRIVET_HANDLER_H_
-#define BUFFET_PRIVET_PRIVET_HANDLER_H_
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-#include <base/scoped_observer.h>
-
-#include "buffet/privet/cloud_delegate.h"
-
-namespace base {
-class Value;
-class DictionaryValue;
-} // namespace base
-
-namespace privetd {
-
-class DeviceDelegate;
-class IdentityDelegate;
-class SecurityDelegate;
-class WifiDelegate;
-
-enum class AuthScope;
-
-// Privet V3 HTTP/HTTPS requests handler.
-// API details at https://developers.google.com/cloud-devices/
-class PrivetHandler : public CloudDelegate::Observer {
- public:
- // Callback to handle requests asynchronously.
- // |status| is HTTP status code.
- // |output| is result returned in HTTP response. Contains result of
- // successfully request of information about error.
- using RequestCallback =
- base::Callback<void(int status, const base::DictionaryValue& output)>;
-
- PrivetHandler(CloudDelegate* cloud,
- DeviceDelegate* device,
- SecurityDelegate* pairing,
- WifiDelegate* wifi,
- IdentityDelegate* identity);
- ~PrivetHandler() override;
-
- void OnCommandDefsChanged() override;
- void OnStateChanged() override;
-
- // Handles HTTP/HTTPS Privet request.
- // |api| is the path from the HTTP request, e.g /privet/info.
- // |auth_header| is the Authentication header from HTTP request.
- // |input| is the the POST data from HTTP request. If nullptr, data format is
- // not valid JSON.
- // |callback| will be called exactly once during or after |HandleRequest|
- // call.
- void HandleRequest(const std::string& api,
- const std::string& auth_header,
- const base::DictionaryValue* input,
- const RequestCallback& callback);
-
- private:
- using ApiHandler = void (PrivetHandler::*)(const base::DictionaryValue&,
- const UserInfo&,
- const RequestCallback&);
-
- void AddHandler(const std::string& path, ApiHandler handler, AuthScope scope);
-
- void HandleInfo(const base::DictionaryValue&,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandlePairingStart(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandlePairingConfirm(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandlePairingCancel(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleAuth(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleSetupStart(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleSetupStatus(const base::DictionaryValue&,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleState(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleCommandDefs(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleCommandsExecute(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleCommandsStatus(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleCommandsList(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
- void HandleCommandsCancel(const base::DictionaryValue& input,
- const UserInfo& user_info,
- const RequestCallback& callback);
-
- void OnUpdateDeviceInfoDone(const std::string& ssid,
- const std::string& passphrase,
- const std::string& ticket,
- const std::string& user,
- const RequestCallback& callback) const;
- void ReplyWithSetupStatus(const RequestCallback& callback) const;
-
- CloudDelegate* cloud_ = nullptr;
- DeviceDelegate* device_ = nullptr;
- SecurityDelegate* security_ = nullptr;
- WifiDelegate* wifi_ = nullptr;
- IdentityDelegate* identity_ = nullptr;
-
- std::map<std::string, std::pair<AuthScope, ApiHandler>> handlers_;
-
- uint64_t last_user_id_{0};
- int state_fingerprint_{0};
- int command_defs_fingerprint_{0};
- ScopedObserver<CloudDelegate, CloudDelegate::Observer> cloud_observer_{this};
-
- base::WeakPtrFactory<PrivetHandler> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PrivetHandler);
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_PRIVET_HANDLER_H_
diff --git a/buffet/privet/privet_handler_unittest.cc b/buffet/privet/privet_handler_unittest.cc
deleted file mode 100644
index 2ae76d9..0000000
--- a/buffet/privet/privet_handler_unittest.cc
+++ /dev/null
@@ -1,726 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/privet_handler.h"
-
-#include <set>
-#include <string>
-#include <utility>
-
-#include <base/bind.h>
-#include <base/json/json_reader.h>
-#include <base/json/json_writer.h>
-#include <base/run_loop.h>
-#include <base/strings/string_util.h>
-#include <base/values.h>
-#include <chromeos/http/http_request.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/privet/constants.h"
-#include "buffet/privet/mock_delegates.h"
-
-using testing::_;
-using testing::DoAll;
-using testing::Invoke;
-using testing::Return;
-using testing::SetArgPointee;
-
-namespace privetd {
-
-namespace {
-
-void LoadTestJson(const std::string& test_json,
- base::DictionaryValue* dictionary) {
- std::string json = test_json;
- base::ReplaceChars(json, "'", "\"", &json);
- int error = 0;
- std::string message;
- std::unique_ptr<base::Value> value(
- base::JSONReader::ReadAndReturnError(json, base::JSON_PARSE_RFC, &error,
- &message)
- .release());
- EXPECT_TRUE(value.get()) << "\nError: " << message << "\n" << json;
- base::DictionaryValue* dictionary_ptr = nullptr;
- if (value->GetAsDictionary(&dictionary_ptr))
- dictionary->MergeDictionary(dictionary_ptr);
-}
-
-bool IsEqualValue(const base::Value& val1, const base::Value& val2) {
- return val1.Equals(&val2);
-}
-
-struct CodeWithReason {
- CodeWithReason(int code_in, const std::string& reason_in)
- : code(code_in), reason(reason_in) {}
- int code;
- std::string reason;
-};
-
-std::ostream& operator<<(std::ostream& stream, const CodeWithReason& error) {
- return stream << "{" << error.code << ", " << error.reason << "}";
-}
-
-bool IsEqualError(const CodeWithReason& expected,
- const base::DictionaryValue& dictionary) {
- std::string reason;
- int code = 0;
- return dictionary.GetInteger("error.http_status", &code) &&
- code == expected.code && dictionary.GetString("error.code", &reason) &&
- reason == expected.reason;
-}
-
-bool IsEqualDictionary(const base::DictionaryValue& dictionary1,
- const base::DictionaryValue& dictionary2) {
- base::DictionaryValue::Iterator it1(dictionary1);
- base::DictionaryValue::Iterator it2(dictionary2);
- for (; !it1.IsAtEnd() && !it2.IsAtEnd(); it1.Advance(), it2.Advance()) {
- // Output mismatched keys.
- EXPECT_EQ(it1.key(), it2.key());
- if (it1.key() != it2.key())
- return false;
-
- if (it1.key() == "error") {
- std::string code1;
- std::string code2;
- const char kCodeKey[] = "error.code";
- if (!dictionary1.GetString(kCodeKey, &code1) ||
- !dictionary2.GetString(kCodeKey, &code2) || code1 != code2) {
- return false;
- }
- continue;
- }
-
- const base::DictionaryValue* d1{nullptr};
- const base::DictionaryValue* d2{nullptr};
- if (it1.value().GetAsDictionary(&d1) && it2.value().GetAsDictionary(&d2)) {
- if (!IsEqualDictionary(*d1, *d2))
- return false;
- continue;
- }
-
- // Output mismatched values.
- EXPECT_PRED2(IsEqualValue, it1.value(), it2.value());
- if (!IsEqualValue(it1.value(), it2.value()))
- return false;
- }
-
- return it1.IsAtEnd() && it2.IsAtEnd();
-}
-
-bool IsEqualJson(const std::string& test_json,
- const base::DictionaryValue& dictionary) {
- base::DictionaryValue dictionary2;
- LoadTestJson(test_json, &dictionary2);
- return IsEqualDictionary(dictionary2, dictionary);
-}
-
-} // namespace
-
-class PrivetHandlerTest : public testing::Test {
- public:
- PrivetHandlerTest() {}
-
- protected:
- void SetUp() override {
- auth_header_ = "Privet anonymous";
- handler_.reset(
- new PrivetHandler(&cloud_, &device_, &security_, &wifi_, &identity_));
- }
-
- const base::DictionaryValue& HandleRequest(
- const std::string& api,
- const base::DictionaryValue* input) {
- output_.Clear();
- handler_->HandleRequest(api, auth_header_, input,
- base::Bind(&PrivetHandlerTest::HandlerCallback,
- base::Unretained(this)));
- base::RunLoop().RunUntilIdle();
- return output_;
- }
-
- const base::DictionaryValue& HandleRequest(const std::string& api,
- const std::string& json_input) {
- base::DictionaryValue dictionary;
- LoadTestJson(json_input, &dictionary);
- return HandleRequest(api, &dictionary);
- }
-
- void HandleUnknownRequest(const std::string& api) {
- output_.Clear();
- base::DictionaryValue dictionary;
- handler_->HandleRequest(api, auth_header_, &dictionary,
- base::Bind(&PrivetHandlerTest::HandlerNoFound));
- base::RunLoop().RunUntilIdle();
- }
-
- void SetNoWifiAndGcd() {
- handler_.reset(
- new PrivetHandler(&cloud_, &device_, &security_, nullptr, &identity_));
- EXPECT_CALL(cloud_, GetCloudId()).WillRepeatedly(Return(""));
- EXPECT_CALL(cloud_, GetConnectionState())
- .WillRepeatedly(ReturnRef(gcd_disabled_state_));
- auto set_error =
- [](const std::string&, const std::string&, chromeos::ErrorPtr* error) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- "setupUnavailable", "");
- };
- EXPECT_CALL(cloud_, Setup(_, _, _))
- .WillRepeatedly(DoAll(Invoke(set_error), Return(false)));
- }
-
- testing::StrictMock<MockCloudDelegate> cloud_;
- testing::StrictMock<MockDeviceDelegate> device_;
- testing::StrictMock<MockSecurityDelegate> security_;
- testing::StrictMock<MockWifiDelegate> wifi_;
- testing::StrictMock<MockIdentityDelegate> identity_;
- std::string auth_header_;
-
- private:
- void HandlerCallback(int status, const base::DictionaryValue& output) {
- output_.MergeDictionary(&output);
- if (!output_.HasKey("error")) {
- EXPECT_EQ(chromeos::http::status_code::Ok, status);
- return;
- }
- EXPECT_NE(chromeos::http::status_code::Ok, status);
- output_.SetInteger("error.http_status", status);
- }
-
- static void HandlerNoFound(int status, const base::DictionaryValue&) {
- EXPECT_EQ(status, 404);
- }
-
- base::MessageLoop message_loop_;
- std::unique_ptr<PrivetHandler> handler_;
- base::DictionaryValue output_;
- ConnectionState gcd_disabled_state_{ConnectionState::kDisabled};
-};
-
-TEST_F(PrivetHandlerTest, UnknownApi) {
- HandleUnknownRequest("/privet/foo");
-}
-
-TEST_F(PrivetHandlerTest, InvalidFormat) {
- auth_header_ = "";
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidFormat"),
- HandleRequest("/privet/info", nullptr));
-}
-
-TEST_F(PrivetHandlerTest, MissingAuth) {
- auth_header_ = "";
- EXPECT_PRED2(IsEqualError, CodeWithReason(401, "missingAuthorization"),
- HandleRequest("/privet/info", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, InvalidAuth) {
- auth_header_ = "foo";
- EXPECT_PRED2(IsEqualError, CodeWithReason(401, "invalidAuthorization"),
- HandleRequest("/privet/info", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, ExpiredAuth) {
- auth_header_ = "Privet 123";
- EXPECT_CALL(security_, ParseAccessToken(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time()),
- Return(UserInfo{AuthScope::kOwner, 1})));
- EXPECT_PRED2(IsEqualError, CodeWithReason(403, "authorizationExpired"),
- HandleRequest("/privet/info", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, InvalidAuthScope) {
- EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthorizationScope"),
- HandleRequest("/privet/v3/setup/start", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, InfoMinimal) {
- SetNoWifiAndGcd();
- EXPECT_CALL(security_, GetPairingTypes())
- .WillRepeatedly(Return(std::set<PairingType>{}));
- EXPECT_CALL(security_, GetCryptoTypes())
- .WillRepeatedly(Return(std::set<CryptoType>{}));
-
- const char kExpected[] = R"({
- 'version': '3.0',
- 'id': 'TestId',
- 'name': 'TestDevice',
- 'services': [],
- 'modelManifestId': "ABMID",
- 'basicModelManifest': {
- 'uiDeviceKind': 'developmentBoard',
- 'oemName': 'Chromium',
- 'modelName': 'Brillo'
- },
- 'endpoints': {
- 'httpPort': 0,
- 'httpUpdatesPort': 0,
- 'httpsPort': 0,
- 'httpsUpdatesPort': 0
- },
- 'authentication': {
- 'anonymousMaxScope': 'user',
- 'mode': [
- 'anonymous',
- 'pairing'
- ],
- 'pairing': [
- ],
- 'crypto': [
- ]
- },
- 'gcd': {
- 'id': '',
- 'status': 'disabled'
- },
- 'uptime': 3600
- })";
- EXPECT_PRED2(IsEqualJson, kExpected, HandleRequest("/privet/info", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, Info) {
- EXPECT_CALL(cloud_, GetDescription())
- .WillRepeatedly(Return("TestDescription"));
- EXPECT_CALL(cloud_, GetLocation()).WillRepeatedly(Return("TestLocation"));
- EXPECT_CALL(cloud_, GetServices())
- .WillRepeatedly(Return(std::set<std::string>{"service1", "service2"}));
- EXPECT_CALL(device_, GetHttpEnpoint())
- .WillRepeatedly(Return(std::make_pair(80, 10080)));
- EXPECT_CALL(device_, GetHttpsEnpoint())
- .WillRepeatedly(Return(std::make_pair(443, 10443)));
- EXPECT_CALL(wifi_, GetHostedSsid())
- .WillRepeatedly(Return("Test_device.BBABCLAprv"));
-
- const char kExpected[] = R"({
- 'version': '3.0',
- 'id': 'TestId',
- 'name': 'TestDevice',
- 'description': 'TestDescription',
- 'location': 'TestLocation',
- 'services': [
- "service1",
- "service2"
- ],
- 'modelManifestId': "ABMID",
- 'basicModelManifest': {
- 'uiDeviceKind': 'developmentBoard',
- 'oemName': 'Chromium',
- 'modelName': 'Brillo'
- },
- 'endpoints': {
- 'httpPort': 80,
- 'httpUpdatesPort': 10080,
- 'httpsPort': 443,
- 'httpsUpdatesPort': 10443
- },
- 'authentication': {
- 'anonymousMaxScope': 'none',
- 'mode': [
- 'anonymous',
- 'pairing'
- ],
- 'pairing': [
- 'pinCode',
- 'embeddedCode',
- 'ultrasound32',
- 'audible32'
- ],
- 'crypto': [
- 'p224_spake2',
- 'p256_spake2'
- ]
- },
- 'wifi': {
- 'capabilities': [
- '2.4GHz'
- ],
- 'ssid': 'TestSsid',
- 'hostedSsid': 'Test_device.BBABCLAprv',
- 'status': 'offline'
- },
- 'gcd': {
- 'id': 'TestCloudId',
- 'status': 'online'
- },
- 'uptime': 3600
- })";
- EXPECT_PRED2(IsEqualJson, kExpected, HandleRequest("/privet/info", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, PairingStartInvalidParams) {
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
- HandleRequest("/privet/v3/pairing/start",
- "{'pairing':'embeddedCode','crypto':'crypto'}"));
-
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
- HandleRequest("/privet/v3/pairing/start",
- "{'pairing':'code','crypto':'p256_spake2'}"));
-}
-
-TEST_F(PrivetHandlerTest, PairingStart) {
- EXPECT_PRED2(
- IsEqualJson,
- "{'deviceCommitment': 'testCommitment', 'sessionId': 'testSession'}",
- HandleRequest("/privet/v3/pairing/start",
- "{'pairing': 'embeddedCode', 'crypto': 'p256_spake2'}"));
-}
-
-TEST_F(PrivetHandlerTest, PairingConfirm) {
- EXPECT_PRED2(
- IsEqualJson,
- "{'certFingerprint':'testFingerprint','certSignature':'testSignature'}",
- HandleRequest(
- "/privet/v3/pairing/confirm",
- "{'sessionId':'testSession','clientCommitment':'testCommitment'}"));
-}
-
-TEST_F(PrivetHandlerTest, PairingCancel) {
- EXPECT_PRED2(IsEqualJson, "{}",
- HandleRequest("/privet/v3/pairing/cancel",
- "{'sessionId': 'testSession'}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthErrorNoType) {
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidAuthMode"),
- HandleRequest("/privet/v3/auth", "{}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthErrorInvalidType) {
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidAuthMode"),
- HandleRequest("/privet/v3/auth", "{'mode':'unknown'}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthErrorNoScope) {
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidRequestedScope"),
- HandleRequest("/privet/v3/auth", "{'mode':'anonymous'}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthErrorInvalidScope) {
- EXPECT_PRED2(
- IsEqualError, CodeWithReason(400, "invalidRequestedScope"),
- HandleRequest("/privet/v3/auth",
- "{'mode':'anonymous','requestedScope':'unknown'}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthErrorAccessDenied) {
- EXPECT_PRED2(IsEqualError, CodeWithReason(403, "accessDenied"),
- HandleRequest("/privet/v3/auth",
- "{'mode':'anonymous','requestedScope':'owner'}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthErrorInvalidAuthCode) {
- EXPECT_CALL(security_, IsValidPairingCode("testToken"))
- .WillRepeatedly(Return(false));
- const char kInput[] = R"({
- 'mode': 'pairing',
- 'requestedScope': 'user',
- 'authCode': 'testToken'
- })";
- EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthCode"),
- HandleRequest("/privet/v3/auth", kInput));
-}
-
-TEST_F(PrivetHandlerTest, AuthAnonymous) {
- const char kExpected[] = R"({
- 'accessToken': 'GuestAccessToken',
- 'expiresIn': 3600,
- 'scope': 'user',
- 'tokenType': 'Privet'
- })";
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/auth",
- "{'mode':'anonymous','requestedScope':'auto'}"));
-}
-
-TEST_F(PrivetHandlerTest, AuthPairing) {
- EXPECT_CALL(security_, IsValidPairingCode("testToken"))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(security_, CreateAccessToken(_, _))
- .WillRepeatedly(Return("OwnerAccessToken"));
- const char kInput[] = R"({
- 'mode': 'pairing',
- 'requestedScope': 'owner',
- 'authCode': 'testToken'
- })";
- const char kExpected[] = R"({
- 'accessToken': 'OwnerAccessToken',
- 'expiresIn': 3600,
- 'scope': 'owner',
- 'tokenType': 'Privet'
- })";
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/auth", kInput));
-}
-
-class PrivetHandlerSetupTest : public PrivetHandlerTest {
- public:
- void SetUp() override {
- PrivetHandlerTest::SetUp();
- auth_header_ = "Privet 123";
- EXPECT_CALL(security_, ParseAccessToken(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()),
- Return(UserInfo{AuthScope::kOwner, 1})));
- }
-};
-
-TEST_F(PrivetHandlerSetupTest, StatusEmpty) {
- SetNoWifiAndGcd();
- EXPECT_PRED2(IsEqualJson, "{}",
- HandleRequest("/privet/v3/setup/status", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, StatusWifi) {
- wifi_.setup_state_ = SetupState{SetupState::kSuccess};
-
- const char kExpected[] = R"({
- 'wifi': {
- 'ssid': 'TestSsid',
- 'status': 'success'
- }
- })";
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/setup/status", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, StatusWifiError) {
- chromeos::ErrorPtr error;
- chromeos::Error::AddTo(&error, FROM_HERE, "test", "invalidPassphrase", "");
- wifi_.setup_state_ = SetupState{std::move(error)};
-
- const char kExpected[] = R"({
- 'wifi': {
- 'status': 'error',
- 'error': {
- 'code': 'invalidPassphrase'
- }
- }
- })";
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/setup/status", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, StatusGcd) {
- cloud_.setup_state_ = SetupState{SetupState::kSuccess};
-
- const char kExpected[] = R"({
- 'gcd': {
- 'id': 'TestCloudId',
- 'status': 'success'
- }
- })";
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/setup/status", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, StatusGcdError) {
- chromeos::ErrorPtr error;
- chromeos::Error::AddTo(&error, FROM_HERE, "test", "invalidTicket", "");
- cloud_.setup_state_ = SetupState{std::move(error)};
-
- const char kExpected[] = R"({
- 'gcd': {
- 'status': 'error',
- 'error': {
- 'code': 'invalidTicket'
- }
- }
- })";
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/setup/status", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, SetupNameDescriptionLocation) {
- EXPECT_CALL(cloud_, UpdateDeviceInfo("testName", "testDescription",
- "testLocation", _, _)).Times(1);
- const char kInput[] = R"({
- 'name': 'testName',
- 'description': 'testDescription',
- 'location': 'testLocation'
- })";
- EXPECT_PRED2(IsEqualJson, "{}",
- HandleRequest("/privet/v3/setup/start", kInput));
-}
-
-TEST_F(PrivetHandlerSetupTest, InvalidParams) {
- const char kInputWifi[] = R"({
- 'wifi': {
- 'ssid': ''
- }
- })";
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
- HandleRequest("/privet/v3/setup/start", kInputWifi));
-
- const char kInputRegistration[] = R"({
- 'gcd': {
- 'ticketId': ''
- }
- })";
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
- HandleRequest("/privet/v3/setup/start", kInputRegistration));
-}
-
-TEST_F(PrivetHandlerSetupTest, WifiSetupUnavailable) {
- SetNoWifiAndGcd();
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "setupUnavailable"),
- HandleRequest("/privet/v3/setup/start", "{'wifi': {}}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, WifiSetup) {
- const char kInput[] = R"({
- 'wifi': {
- 'ssid': 'testSsid',
- 'passphrase': 'testPass'
- }
- })";
- auto set_error =
- [](const std::string&, const std::string&, chromeos::ErrorPtr* error) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain, "deviceBusy", "");
- };
- EXPECT_CALL(wifi_, ConfigureCredentials(_, _, _))
- .WillOnce(DoAll(Invoke(set_error), Return(false)));
- EXPECT_PRED2(IsEqualError, CodeWithReason(503, "deviceBusy"),
- HandleRequest("/privet/v3/setup/start", kInput));
-
- const char kExpected[] = R"({
- 'wifi': {
- 'status': 'inProgress'
- }
- })";
- wifi_.setup_state_ = SetupState{SetupState::kInProgress};
- EXPECT_CALL(wifi_, ConfigureCredentials("testSsid", "testPass", _))
- .WillOnce(Return(true));
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/setup/start", kInput));
-}
-
-TEST_F(PrivetHandlerSetupTest, GcdSetupUnavailable) {
- SetNoWifiAndGcd();
- const char kInput[] = R"({
- 'gcd': {
- 'ticketId': 'testTicket',
- 'user': 'testUser'
- }
- })";
-
- EXPECT_PRED2(IsEqualError, CodeWithReason(400, "setupUnavailable"),
- HandleRequest("/privet/v3/setup/start", kInput));
-}
-
-TEST_F(PrivetHandlerSetupTest, GcdSetup) {
- const char kInput[] = R"({
- 'gcd': {
- 'ticketId': 'testTicket',
- 'user': 'testUser'
- }
- })";
-
- auto set_error =
- [](const std::string&, const std::string&, chromeos::ErrorPtr* error) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain, "deviceBusy", "");
- };
- EXPECT_CALL(cloud_, Setup(_, _, _))
- .WillOnce(DoAll(Invoke(set_error), Return(false)));
- EXPECT_PRED2(IsEqualError, CodeWithReason(503, "deviceBusy"),
- HandleRequest("/privet/v3/setup/start", kInput));
-
- const char kExpected[] = R"({
- 'gcd': {
- 'status': 'inProgress'
- }
- })";
- cloud_.setup_state_ = SetupState{SetupState::kInProgress};
- EXPECT_CALL(cloud_, Setup("testTicket", "testUser", _))
- .WillOnce(Return(true));
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/setup/start", kInput));
-}
-
-TEST_F(PrivetHandlerSetupTest, State) {
- EXPECT_PRED2(IsEqualJson, "{'state': {'test': {}}, 'fingerprint': '0'}",
- HandleRequest("/privet/v3/state", "{}"));
-
- cloud_.NotifyOnStateChanged();
-
- EXPECT_PRED2(IsEqualJson, "{'state': {'test': {}}, 'fingerprint': '1'}",
- HandleRequest("/privet/v3/state", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, CommandsDefs) {
- EXPECT_PRED2(IsEqualJson, "{'commands': {'test':{}}, 'fingerprint': '0'}",
- HandleRequest("/privet/v3/commandDefs", "{}"));
-
- cloud_.NotifyOnCommandDefsChanged();
-
- EXPECT_PRED2(IsEqualJson, "{'commands': {'test':{}}, 'fingerprint': '1'}",
- HandleRequest("/privet/v3/commandDefs", "{}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, CommandsExecute) {
- const char kInput[] = "{'name': 'test'}";
- base::DictionaryValue command;
- LoadTestJson(kInput, &command);
- LoadTestJson("{'id':'5'}", &command);
- EXPECT_CALL(cloud_, AddCommand(_, _, _, _))
- .WillOnce(RunCallback<2, const base::DictionaryValue&>(command));
-
- EXPECT_PRED2(IsEqualJson, "{'name':'test', 'id':'5'}",
- HandleRequest("/privet/v3/commands/execute", kInput));
-}
-
-TEST_F(PrivetHandlerSetupTest, CommandsStatus) {
- const char kInput[] = "{'id': '5'}";
- base::DictionaryValue command;
- LoadTestJson(kInput, &command);
- LoadTestJson("{'name':'test'}", &command);
- EXPECT_CALL(cloud_, GetCommand(_, _, _, _))
- .WillOnce(RunCallback<2, const base::DictionaryValue&>(command));
-
- EXPECT_PRED2(IsEqualJson, "{'name':'test', 'id':'5'}",
- HandleRequest("/privet/v3/commands/status", kInput));
-
- chromeos::ErrorPtr error;
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain, "notFound", "");
- EXPECT_CALL(cloud_, GetCommand(_, _, _, _))
- .WillOnce(RunCallback<3>(error.get()));
-
- EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
- HandleRequest("/privet/v3/commands/status", "{'id': '15'}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, CommandsCancel) {
- const char kExpected[] = "{'id': '5', 'name':'test', 'state':'cancelled'}";
- base::DictionaryValue command;
- LoadTestJson(kExpected, &command);
- EXPECT_CALL(cloud_, CancelCommand(_, _, _, _))
- .WillOnce(RunCallback<2, const base::DictionaryValue&>(command));
-
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/commands/cancel", "{'id': '8'}"));
-
- chromeos::ErrorPtr error;
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain, "notFound", "");
- EXPECT_CALL(cloud_, CancelCommand(_, _, _, _))
- .WillOnce(RunCallback<3>(error.get()));
-
- EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
- HandleRequest("/privet/v3/commands/cancel", "{'id': '11'}"));
-}
-
-TEST_F(PrivetHandlerSetupTest, CommandsList) {
- const char kExpected[] = R"({
- 'commands' : [
- {'id':'5', 'state':'cancelled'},
- {'id':'15', 'state':'inProgress'}
- ]})";
-
- base::DictionaryValue commands;
- LoadTestJson(kExpected, &commands);
-
- EXPECT_CALL(cloud_, ListCommands(_, _, _))
- .WillOnce(RunCallback<1, const base::DictionaryValue&>(commands));
-
- EXPECT_PRED2(IsEqualJson, kExpected,
- HandleRequest("/privet/v3/commands/list", "{}"));
-}
-
-} // namespace privetd
diff --git a/buffet/privet/privet_manager.cc b/buffet/privet/privet_manager.cc
deleted file mode 100644
index bdea47a..0000000
--- a/buffet/privet/privet_manager.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/privet_manager.h"
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include <base/bind.h>
-#include <base/command_line.h>
-#include <base/json/json_reader.h>
-#include <base/memory/weak_ptr.h>
-#include <base/scoped_observer.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/values.h>
-#include <chromeos/daemons/dbus_daemon.h>
-#include <chromeos/flag_helper.h>
-#include <chromeos/http/http_request.h>
-#include <chromeos/key_value_store.h>
-#include <chromeos/mime_utils.h>
-#include <chromeos/strings/string_utils.h>
-#include <chromeos/syslog_logging.h>
-#include <libwebserv/protocol_handler.h>
-#include <libwebserv/request.h>
-#include <libwebserv/response.h>
-#include <libwebserv/server.h>
-
-#include "buffet/dbus_constants.h"
-#include "buffet/device_registration_info.h"
-#include "buffet/privet/ap_manager_client.h"
-#include "buffet/privet/cloud_delegate.h"
-#include "buffet/privet/constants.h"
-#include "buffet/privet/device_delegate.h"
-#include "buffet/privet/peerd_client.h"
-#include "buffet/privet/privet_handler.h"
-#include "buffet/privet/security_manager.h"
-#include "buffet/privet/shill_client.h"
-#include "buffet/privet/wifi_bootstrap_manager.h"
-
-namespace privetd {
-
-namespace {
-
-using chromeos::dbus_utils::AsyncEventSequencer;
-using libwebserv::ProtocolHandler;
-using libwebserv::Request;
-using libwebserv::Response;
-
-std::string GetFirstHeader(const Request& request, const std::string& name) {
- std::vector<std::string> headers = request.GetHeader(name);
- return headers.empty() ? std::string() : headers.front();
-}
-
-} // namespace
-
-Manager::Manager() {
-}
-
-Manager::~Manager() {
-}
-
-void Manager::Start(const Options& options,
- const scoped_refptr<dbus::Bus>& bus,
- ShillClient* shill_client,
- buffet::DeviceRegistrationInfo* device,
- buffet::CommandManager* command_manager,
- buffet::StateManager* state_manager,
- AsyncEventSequencer* sequencer) {
- disable_security_ = options.disable_security;
-
- device_ = DeviceDelegate::CreateDefault();
- cloud_ = CloudDelegate::CreateDefault(device, command_manager, state_manager);
- cloud_observer_.Add(cloud_.get());
- security_.reset(new SecurityManager(device->GetConfig().pairing_modes(),
- device->GetConfig().embedded_code_path(),
- disable_security_));
- shill_client->RegisterConnectivityListener(
- base::Bind(&Manager::OnConnectivityChanged, base::Unretained(this)));
- ap_manager_client_.reset(new ApManagerClient(bus));
-
- if (device->GetConfig().wifi_auto_setup_enabled()) {
- VLOG(1) << "Enabling WiFi bootstrapping.";
- wifi_bootstrap_manager_.reset(new WifiBootstrapManager(
- device->GetConfig().last_configured_ssid(), shill_client,
- ap_manager_client_.get(), cloud_.get()));
- wifi_bootstrap_manager_->Init();
- }
-
- peerd_client_.reset(new PeerdClient(bus, device_.get(), cloud_.get(),
- wifi_bootstrap_manager_.get()));
-
- privet_handler_.reset(
- new PrivetHandler(cloud_.get(), device_.get(), security_.get(),
- wifi_bootstrap_manager_.get(), peerd_client_.get()));
-
- web_server_.reset(new libwebserv::Server);
- web_server_->OnProtocolHandlerConnected(base::Bind(
- &Manager::OnProtocolHandlerConnected, weak_ptr_factory_.GetWeakPtr()));
- web_server_->OnProtocolHandlerDisconnected(base::Bind(
- &Manager::OnProtocolHandlerDisconnected, weak_ptr_factory_.GetWeakPtr()));
-
- web_server_->Connect(bus, buffet::dbus_constants::kServiceName,
- sequencer->GetHandler("Server::Connect failed.", true),
- base::Bind(&base::DoNothing),
- base::Bind(&base::DoNothing));
-
- web_server_->GetDefaultHttpHandler()->AddHandlerCallback(
- "/privet/", "",
- base::Bind(&Manager::PrivetRequestHandler, base::Unretained(this)));
- web_server_->GetDefaultHttpsHandler()->AddHandlerCallback(
- "/privet/", "",
- base::Bind(&Manager::PrivetRequestHandler, base::Unretained(this)));
- if (options.enable_ping) {
- web_server_->GetDefaultHttpHandler()->AddHandlerCallback(
- "/privet/ping", chromeos::http::request_type::kGet,
- base::Bind(&Manager::HelloWorldHandler, base::Unretained(this)));
- web_server_->GetDefaultHttpsHandler()->AddHandlerCallback(
- "/privet/ping", chromeos::http::request_type::kGet,
- base::Bind(&Manager::HelloWorldHandler, base::Unretained(this)));
- }
-}
-
-void Manager::OnShutdown() {
- web_server_->Disconnect();
-}
-
-void Manager::OnDeviceInfoChanged() {
- OnChanged();
-}
-
-void Manager::PrivetRequestHandler(std::unique_ptr<Request> request,
- std::unique_ptr<Response> response) {
- std::string auth_header =
- GetFirstHeader(*request, chromeos::http::request_header::kAuthorization);
- if (auth_header.empty() && disable_security_)
- auth_header = "Privet anonymous";
- std::string data(request->GetData().begin(), request->GetData().end());
- VLOG(3) << "Input: " << data;
-
- base::DictionaryValue empty;
- std::unique_ptr<base::Value> value;
- const base::DictionaryValue* dictionary = nullptr;
-
- if (data.empty()) {
- dictionary = ∅
- } else {
- std::string content_type = chromeos::mime::RemoveParameters(
- GetFirstHeader(*request, chromeos::http::request_header::kContentType));
- if (content_type == chromeos::mime::application::kJson) {
- value.reset(base::JSONReader::Read(data).release());
- if (value)
- value->GetAsDictionary(&dictionary);
- }
- }
-
- privet_handler_->HandleRequest(
- request->GetPath(), auth_header, dictionary,
- base::Bind(&Manager::PrivetResponseHandler, base::Unretained(this),
- base::Passed(&response)));
-}
-
-void Manager::PrivetResponseHandler(std::unique_ptr<Response> response,
- int status,
- const base::DictionaryValue& output) {
- VLOG(3) << "status: " << status << ", Output: " << output;
- response->ReplyWithJson(status, &output);
-}
-
-void Manager::HelloWorldHandler(std::unique_ptr<Request> request,
- std::unique_ptr<Response> response) {
- response->ReplyWithText(chromeos::http::status_code::Ok, "Hello, world!",
- chromeos::mime::text::kPlain);
-}
-
-void Manager::OnChanged() {
- if (peerd_client_)
- peerd_client_->Update();
-}
-
-void Manager::OnConnectivityChanged(bool online) {
- OnChanged();
-}
-
-void Manager::OnProtocolHandlerConnected(ProtocolHandler* protocol_handler) {
- if (protocol_handler->GetName() == ProtocolHandler::kHttp) {
- device_->SetHttpPort(*protocol_handler->GetPorts().begin());
- if (peerd_client_)
- peerd_client_->Update();
- } else if (protocol_handler->GetName() == ProtocolHandler::kHttps) {
- device_->SetHttpsPort(*protocol_handler->GetPorts().begin());
- security_->SetCertificateFingerprint(
- protocol_handler->GetCertificateFingerprint());
- }
-}
-
-void Manager::OnProtocolHandlerDisconnected(ProtocolHandler* protocol_handler) {
- if (protocol_handler->GetName() == ProtocolHandler::kHttp) {
- device_->SetHttpPort(0);
- if (peerd_client_)
- peerd_client_->Update();
- } else if (protocol_handler->GetName() == ProtocolHandler::kHttps) {
- device_->SetHttpsPort(0);
- security_->SetCertificateFingerprint({});
- }
-}
-
-} // namespace privetd
diff --git a/buffet/privet/privet_manager.h b/buffet/privet/privet_manager.h
deleted file mode 100644
index 2af19d1..0000000
--- a/buffet/privet/privet_manager.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_PRIVET_MANAGER_H_
-#define BUFFET_PRIVET_PRIVET_MANAGER_H_
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/memory/weak_ptr.h>
-#include <base/scoped_observer.h>
-
-#include "buffet/privet/cloud_delegate.h"
-
-namespace buffet {
-class CommandManager;
-class DeviceRegistrationInfo;
-class StateManager;
-}
-
-namespace chromeos {
-namespace dbus_utils {
-class AsyncEventSequencer;
-}
-}
-
-namespace libwebserv {
-class ProtocolHandler;
-class Request;
-class Response;
-class Server;
-}
-
-namespace privetd {
-
-class ApManagerClient;
-class CloudDelegate;
-class DaemonState;
-class DeviceDelegate;
-class PeerdClient;
-class PrivetHandler;
-class SecurityManager;
-class ShillClient;
-class WifiBootstrapManager;
-
-class Manager : public CloudDelegate::Observer {
- public:
- struct Options {
- bool disable_privet{false};
- bool disable_security{false};
- bool enable_ping{false};
- base::FilePath config_path;
- };
-
- Manager();
- ~Manager();
-
- void Start(const Options& options,
- const scoped_refptr<dbus::Bus>& bus,
- ShillClient* shill_client,
- buffet::DeviceRegistrationInfo* device,
- buffet::CommandManager* command_manager,
- buffet::StateManager* state_manager,
- chromeos::dbus_utils::AsyncEventSequencer* sequencer);
-
- void OnShutdown();
-
- void OnDeviceInfoChanged() override;
-
- privetd::WifiBootstrapManager* GetWifiBootstrapManager() {
- return wifi_bootstrap_manager_.get();
- }
-
- privetd::SecurityManager* GetSecurityManager() { return security_.get(); }
-
- private:
- void PrivetRequestHandler(std::unique_ptr<libwebserv::Request> request,
- std::unique_ptr<libwebserv::Response> response);
-
- void PrivetResponseHandler(std::unique_ptr<libwebserv::Response> response,
- int status,
- const base::DictionaryValue& output);
-
- void HelloWorldHandler(std::unique_ptr<libwebserv::Request> request,
- std::unique_ptr<libwebserv::Response> response);
-
- void OnChanged();
-
- void OnConnectivityChanged(bool online);
-
- void OnProtocolHandlerConnected(
- libwebserv::ProtocolHandler* protocol_handler);
-
- void OnProtocolHandlerDisconnected(
- libwebserv::ProtocolHandler* protocol_handler);
-
- bool disable_security_{false};
- std::unique_ptr<CloudDelegate> cloud_;
- std::unique_ptr<DeviceDelegate> device_;
- std::unique_ptr<SecurityManager> security_;
- std::unique_ptr<ApManagerClient> ap_manager_client_;
- std::unique_ptr<WifiBootstrapManager> wifi_bootstrap_manager_;
- std::unique_ptr<PeerdClient> peerd_client_;
- std::unique_ptr<PrivetHandler> privet_handler_;
- std::unique_ptr<libwebserv::Server> web_server_;
-
- ScopedObserver<CloudDelegate, CloudDelegate::Observer> cloud_observer_{this};
-
- base::WeakPtrFactory<Manager> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(Manager);
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_PRIVET_MANAGER_H_
diff --git a/buffet/privet/privet_types.h b/buffet/privet/privet_types.h
deleted file mode 100644
index c1e2ba0..0000000
--- a/buffet/privet/privet_types.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_PRIVET_TYPES_H_
-#define BUFFET_PRIVET_PRIVET_TYPES_H_
-
-#include <string>
-
-#include <chromeos/errors/error.h>
-
-namespace privetd {
-
-// Scopes in order of increasing privileges.
-enum class AuthScope {
- kNone,
- kViewer,
- kUser,
- kOwner,
-};
-
-class UserInfo {
- public:
- explicit UserInfo(AuthScope scope = AuthScope::kNone, uint64_t user_id = 0)
- : scope_{scope}, user_id_{scope == AuthScope::kNone ? 0 : user_id} {}
- AuthScope scope() const { return scope_; }
- uint64_t user_id() const { return user_id_; }
-
- private:
- AuthScope scope_;
- uint64_t user_id_;
-};
-
-class ConnectionState final {
- public:
- enum Status {
- kDisabled,
- kUnconfigured,
- kConnecting,
- kOnline,
- kOffline,
- };
-
- explicit ConnectionState(Status status) : status_(status) {}
- explicit ConnectionState(chromeos::ErrorPtr error)
- : status_(kOffline), error_(std::move(error)) {}
-
- Status status() const {
- CHECK(!error_);
- return status_;
- }
-
- bool IsStatusEqual(Status status) const {
- if (error_)
- return false;
- return status_ == status;
- }
-
- const chromeos::Error* error() const { return error_.get(); }
-
- private:
- Status status_;
- chromeos::ErrorPtr error_;
-};
-
-class SetupState final {
- public:
- enum Status {
- kNone,
- kInProgress,
- kSuccess,
- };
-
- explicit SetupState(Status status) : status_(status) {}
- explicit SetupState(chromeos::ErrorPtr error)
- : status_(kNone), error_(std::move(error)) {}
-
- Status status() const {
- CHECK(!error_);
- return status_;
- }
-
- bool IsStatusEqual(Status status) const {
- if (error_)
- return false;
- return status_ == status;
- }
-
- const chromeos::Error* error() const { return error_.get(); }
-
- private:
- Status status_;
- chromeos::ErrorPtr error_;
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_PRIVET_TYPES_H_
diff --git a/buffet/privet/security_delegate.h b/buffet/privet/security_delegate.h
deleted file mode 100644
index f69ffb2..0000000
--- a/buffet/privet/security_delegate.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_SECURITY_DELEGATE_H_
-#define BUFFET_PRIVET_SECURITY_DELEGATE_H_
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include <base/time/time.h>
-#include <chromeos/secure_blob.h>
-
-#include "buffet/privet/privet_types.h"
-
-namespace privetd {
-
-enum class PairingType {
- kPinCode,
- kEmbeddedCode,
- kUltrasound32,
- kAudible32,
-};
-
-enum class CryptoType {
- kNone,
- kSpake_p224,
- kSpake_p256,
-};
-
-// Interface to provide Security related logic for |PrivetHandler|.
-class SecurityDelegate {
- public:
- virtual ~SecurityDelegate() = default;
-
- // Creates access token for the given scope, user id and |time|.
- virtual std::string CreateAccessToken(const UserInfo& user_info,
- const base::Time& time) = 0;
-
- // Validates |token| and returns scope and user id parsed from that.
- virtual UserInfo ParseAccessToken(const std::string& token,
- base::Time* time) const = 0;
-
- // Returns list of pairing methods by device.
- virtual std::set<PairingType> GetPairingTypes() const = 0;
-
- // Returns list of crypto methods supported by devices.
- virtual std::set<CryptoType> GetCryptoTypes() const = 0;
-
- // Returns true if |auth_code| provided by client is valid. Client should
- // obtain |auth_code| during pairing process.
- virtual bool IsValidPairingCode(const std::string& auth_code) const = 0;
-
- virtual bool StartPairing(PairingType mode,
- CryptoType crypto,
- std::string* session_id,
- std::string* device_commitment,
- chromeos::ErrorPtr* error) = 0;
-
- virtual bool ConfirmPairing(const std::string& session_id,
- const std::string& client_commitment,
- std::string* fingerprint,
- std::string* signature,
- chromeos::ErrorPtr* error) = 0;
-
- virtual bool CancelPairing(const std::string& session_id,
- chromeos::ErrorPtr* error) = 0;
-};
-
-bool StringToPairingType(const std::string& mode, PairingType* id);
-std::string PairingTypeToString(PairingType id);
-
-bool StringToAuthScope(const std::string& scope, AuthScope* id);
-std::string AuthScopeToString(AuthScope id);
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_SECURITY_DELEGATE_H_
diff --git a/buffet/privet/security_manager.cc b/buffet/privet/security_manager.cc
deleted file mode 100644
index fd94d78..0000000
--- a/buffet/privet/security_manager.cc
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/security_manager.h"
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <set>
-
-#include <base/bind.h>
-#include <base/guid.h>
-#include <base/logging.h>
-#include <base/message_loop/message_loop.h>
-#include <base/rand_util.h>
-#include <base/stl_util.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/stringprintf.h>
-#include <base/time/time.h>
-#include <chromeos/data_encoding.h>
-#include <chromeos/key_value_store.h>
-#include <chromeos/strings/string_utils.h>
-#include <crypto/p224_spake.h>
-
-#include "buffet/privet/constants.h"
-#include "buffet/privet/openssl_utils.h"
-
-namespace privetd {
-
-namespace {
-
-const char kTokenDelimeter[] = ":";
-const int kSessionExpirationTimeMinutes = 5;
-const int kPairingExpirationTimeMinutes = 5;
-const int kMaxAllowedPairingAttemts = 3;
-const int kPairingBlockingTimeMinutes = 1;
-
-const char kEmbeddedCode[] = "embedded_code";
-
-// Returns "scope:id:time".
-std::string CreateTokenData(const UserInfo& user_info, const base::Time& time) {
- return base::IntToString(static_cast<int>(user_info.scope())) +
- kTokenDelimeter + base::Uint64ToString(user_info.user_id()) +
- kTokenDelimeter + base::Int64ToString(time.ToTimeT());
-}
-
-// Splits string of "scope:id:time" format.
-UserInfo SplitTokenData(const std::string& token, base::Time* time) {
- const UserInfo kNone;
- auto parts = chromeos::string_utils::Split(token, kTokenDelimeter);
- if (parts.size() != 3)
- return kNone;
- int scope = 0;
- if (!base::StringToInt(parts[0], &scope) ||
- scope < static_cast<int>(AuthScope::kNone) ||
- scope > static_cast<int>(AuthScope::kOwner)) {
- return kNone;
- }
-
- uint64_t id{0};
- if (!base::StringToUint64(parts[1], &id))
- return kNone;
-
- int64_t timestamp{0};
- if (!base::StringToInt64(parts[2], ×tamp))
- return kNone;
- *time = base::Time::FromTimeT(timestamp);
- return UserInfo{static_cast<AuthScope>(scope), id};
-}
-
-std::string LoadEmbeddedCode(const base::FilePath& path) {
- std::string code;
- chromeos::KeyValueStore store;
- if (store.Load(path))
- store.GetString(kEmbeddedCode, &code);
- return code;
-}
-
-class Spakep224Exchanger : public SecurityManager::KeyExchanger {
- public:
- explicit Spakep224Exchanger(const std::string& password)
- : spake_(crypto::P224EncryptedKeyExchange::kPeerTypeServer, password) {}
- ~Spakep224Exchanger() override = default;
-
- // SecurityManager::KeyExchanger methods.
- const std::string& GetMessage() override { return spake_.GetNextMessage(); }
-
- bool ProcessMessage(const std::string& message,
- chromeos::ErrorPtr* error) override {
- switch (spake_.ProcessMessage(message)) {
- case crypto::P224EncryptedKeyExchange::kResultPending:
- return true;
- case crypto::P224EncryptedKeyExchange::kResultFailed:
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kInvalidClientCommitment,
- spake_.error());
- return false;
- default:
- LOG(FATAL) << "SecurityManager uses only one round trip";
- }
- return false;
- }
-
- const std::string& GetKey() const override {
- return spake_.GetUnverifiedKey();
- }
-
- private:
- crypto::P224EncryptedKeyExchange spake_;
-};
-
-class UnsecureKeyExchanger : public SecurityManager::KeyExchanger {
- public:
- explicit UnsecureKeyExchanger(const std::string& password)
- : password_(password) {}
- ~UnsecureKeyExchanger() override = default;
-
- // SecurityManager::KeyExchanger methods.
- const std::string& GetMessage() override { return password_; }
-
- bool ProcessMessage(const std::string& message,
- chromeos::ErrorPtr* error) override {
- return true;
- }
-
- const std::string& GetKey() const override { return password_; }
-
- private:
- std::string password_;
-};
-
-} // namespace
-
-SecurityManager::SecurityManager(const std::set<PairingType>& pairing_modes,
- const base::FilePath& embedded_code_path,
- bool disable_security)
- : is_security_disabled_(disable_security),
- pairing_modes_(pairing_modes),
- embedded_code_path_(embedded_code_path),
- secret_(kSha256OutputSize) {
- base::RandBytes(secret_.data(), kSha256OutputSize);
-
- CHECK_EQ(embedded_code_path_.empty(),
- std::find(pairing_modes_.begin(), pairing_modes_.end(),
- PairingType::kEmbeddedCode) == pairing_modes_.end());
-}
-
-SecurityManager::~SecurityManager() {
- while (!pending_sessions_.empty())
- ClosePendingSession(pending_sessions_.begin()->first);
-}
-
-// Returns "base64([hmac]scope:id:time)".
-std::string SecurityManager::CreateAccessToken(const UserInfo& user_info,
- const base::Time& time) {
- chromeos::SecureBlob data(CreateTokenData(user_info, time));
- chromeos::Blob hash(HmacSha256(secret_, data));
- return chromeos::data_encoding::Base64Encode(chromeos::SecureBlob::Combine(
- chromeos::SecureBlob(hash.begin(), hash.end()), data));
-}
-
-// Parses "base64([hmac]scope:id:time)".
-UserInfo SecurityManager::ParseAccessToken(const std::string& token,
- base::Time* time) const {
- chromeos::Blob decoded;
- if (!chromeos::data_encoding::Base64Decode(token, &decoded) ||
- decoded.size() <= kSha256OutputSize) {
- return UserInfo{};
- }
- chromeos::SecureBlob data(decoded.begin() + kSha256OutputSize, decoded.end());
- decoded.resize(kSha256OutputSize);
- if (decoded != HmacSha256(secret_, data))
- return UserInfo{};
- return SplitTokenData(data.to_string(), time);
-}
-
-std::set<PairingType> SecurityManager::GetPairingTypes() const {
- return pairing_modes_;
-}
-
-std::set<CryptoType> SecurityManager::GetCryptoTypes() const {
- std::set<CryptoType> result{CryptoType::kSpake_p224};
- if (is_security_disabled_)
- result.insert(CryptoType::kNone);
- return result;
-}
-
-bool SecurityManager::IsValidPairingCode(const std::string& auth_code) const {
- if (is_security_disabled_)
- return true;
- chromeos::Blob auth_decoded;
- if (!chromeos::data_encoding::Base64Decode(auth_code, &auth_decoded))
- return false;
- for (const auto& session : confirmed_sessions_) {
- if (auth_decoded ==
- HmacSha256(chromeos::SecureBlob{session.second->GetKey()},
- chromeos::SecureBlob{session.first})) {
- pairing_attemts_ = 0;
- block_pairing_until_ = base::Time{};
- return true;
- }
- }
- LOG(ERROR) << "Attempt to authenticate with invalide code.";
- return false;
-}
-
-bool SecurityManager::StartPairing(PairingType mode,
- CryptoType crypto,
- std::string* session_id,
- std::string* device_commitment,
- chromeos::ErrorPtr* error) {
- if (!CheckIfPairingAllowed(error))
- return false;
-
- if (std::find(pairing_modes_.begin(), pairing_modes_.end(), mode) ==
- pairing_modes_.end()) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kInvalidParams,
- "Pairing mode is not enabled");
- return false;
- }
-
- std::string code;
- switch (mode) {
- case PairingType::kEmbeddedCode:
- CHECK(!embedded_code_path_.empty());
-
- if (embedded_code_.empty())
- embedded_code_ = LoadEmbeddedCode(embedded_code_path_);
-
- if (embedded_code_.empty()) { // File is not created yet.
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kDeviceBusy,
- "Embedded code is not ready");
- return false;
- }
-
- code = embedded_code_;
- break;
- case PairingType::kUltrasound32:
- case PairingType::kAudible32: {
- code = base::RandBytesAsString(4);
- break;
- }
- case PairingType::kPinCode:
- code = base::StringPrintf("%04i", base::RandInt(0, 9999));
- break;
- default:
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kInvalidParams,
- "Unsupported pairing mode");
- return false;
- }
-
- std::unique_ptr<KeyExchanger> spake;
- switch (crypto) {
- case CryptoType::kSpake_p224:
- spake.reset(new Spakep224Exchanger(code));
- break;
- case CryptoType::kNone:
- if (is_security_disabled_) {
- spake.reset(new UnsecureKeyExchanger(code));
- break;
- }
- // Fall through...
- default:
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kInvalidParams, "Unsupported crypto");
- return false;
- }
-
- // Allow only a single session at a time for now.
- while (!pending_sessions_.empty())
- ClosePendingSession(pending_sessions_.begin()->first);
-
- std::string session;
- do {
- session = base::GenerateGUID();
- } while (confirmed_sessions_.find(session) != confirmed_sessions_.end() ||
- pending_sessions_.find(session) != pending_sessions_.end());
- std::string commitment = spake->GetMessage();
- pending_sessions_.emplace(session, std::move(spake));
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&SecurityManager::ClosePendingSession),
- weak_ptr_factory_.GetWeakPtr(), session),
- base::TimeDelta::FromMinutes(kPairingExpirationTimeMinutes));
-
- *session_id = session;
- *device_commitment = chromeos::data_encoding::Base64Encode(commitment);
- LOG(INFO) << "Pairing code for session " << *session_id << " is " << code;
- // TODO(vitalybuka): Handle case when device can't start multiple pairing
- // simultaneously and implement throttling to avoid brute force attack.
- if (!on_start_.is_null()) {
- on_start_.Run(session, mode,
- chromeos::string_utils::GetStringAsBytes(code));
- }
-
- return true;
-}
-
-bool SecurityManager::ConfirmPairing(const std::string& session_id,
- const std::string& client_commitment,
- std::string* fingerprint,
- std::string* signature,
- chromeos::ErrorPtr* error) {
- auto session = pending_sessions_.find(session_id);
- if (session == pending_sessions_.end()) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::kDomain, errors::kUnknownSession,
- "Unknown session id: '%s'", session_id.c_str());
- return false;
- }
- CHECK(!certificate_fingerprint_.empty());
-
- chromeos::Blob commitment;
- if (!chromeos::data_encoding::Base64Decode(client_commitment, &commitment)) {
- ClosePendingSession(session_id);
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::kDomain, errors::kInvalidFormat,
- "Invalid commitment string: '%s'", client_commitment.c_str());
- return false;
- }
-
- if (!session->second->ProcessMessage(
- std::string(commitment.begin(), commitment.end()), error)) {
- ClosePendingSession(session_id);
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kCommitmentMismatch,
- "Pairing code or crypto implementation mismatch");
- return false;
- }
-
- std::string key = session->second->GetKey();
- VLOG(3) << "KEY " << base::HexEncode(key.data(), key.size());
-
- *fingerprint =
- chromeos::data_encoding::Base64Encode(certificate_fingerprint_);
- chromeos::Blob cert_hmac =
- HmacSha256(chromeos::SecureBlob(session->second->GetKey()),
- certificate_fingerprint_);
- *signature = chromeos::data_encoding::Base64Encode(cert_hmac);
- confirmed_sessions_.emplace(session->first, std::move(session->second));
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&SecurityManager::CloseConfirmedSession),
- weak_ptr_factory_.GetWeakPtr(), session_id),
- base::TimeDelta::FromMinutes(kSessionExpirationTimeMinutes));
- ClosePendingSession(session_id);
- return true;
-}
-
-bool SecurityManager::CancelPairing(const std::string& session_id,
- chromeos::ErrorPtr* error) {
- bool confirmed = CloseConfirmedSession(session_id);
- bool pending = ClosePendingSession(session_id);
- if (pending) {
- CHECK_GE(pairing_attemts_, 1);
- --pairing_attemts_;
- }
- CHECK(!confirmed || !pending);
- if (confirmed || pending)
- return true;
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::kDomain,
- errors::kUnknownSession,
- "Unknown session id: '%s'", session_id.c_str());
- return false;
-}
-
-void SecurityManager::RegisterPairingListeners(
- const PairingStartListener& on_start,
- const PairingEndListener& on_end) {
- CHECK(on_start_.is_null() && on_end_.is_null());
- on_start_ = on_start;
- on_end_ = on_end;
-}
-
-bool SecurityManager::CheckIfPairingAllowed(chromeos::ErrorPtr* error) {
- if (is_security_disabled_)
- return true;
-
- if (block_pairing_until_ > base::Time::Now()) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
- errors::kDeviceBusy, "Too many pairing attempts");
- return false;
- }
-
- if (++pairing_attemts_ >= kMaxAllowedPairingAttemts) {
- LOG(INFO) << "Pairing blocked for" << kPairingBlockingTimeMinutes
- << "minutes.";
- block_pairing_until_ = base::Time::Now();
- block_pairing_until_ +=
- base::TimeDelta::FromMinutes(kPairingBlockingTimeMinutes);
- }
-
- return true;
-}
-
-bool SecurityManager::ClosePendingSession(const std::string& session_id) {
- // The most common source of these session_id values is the map containing
- // the sessions, which we're about to clear out. Make a local copy.
- const std::string safe_session_id{session_id};
- const size_t num_erased = pending_sessions_.erase(safe_session_id);
- if (num_erased > 0 && !on_end_.is_null())
- on_end_.Run(safe_session_id);
- return num_erased != 0;
-}
-
-bool SecurityManager::CloseConfirmedSession(const std::string& session_id) {
- return confirmed_sessions_.erase(session_id) != 0;
-}
-
-} // namespace privetd
diff --git a/buffet/privet/security_manager.h b/buffet/privet/security_manager.h
deleted file mode 100644
index 04a942e..0000000
--- a/buffet/privet/security_manager.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_SECURITY_MANAGER_H_
-#define BUFFET_PRIVET_SECURITY_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/files/file_path.h>
-#include <base/memory/weak_ptr.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/secure_blob.h>
-
-#include "buffet/privet/security_delegate.h"
-
-namespace crypto {
-class P224EncryptedKeyExchange;
-} // namespace crypto
-
-namespace privetd {
-
-class SecurityManager : public SecurityDelegate {
- public:
- using PairingStartListener =
- base::Callback<void(const std::string& session_id,
- PairingType pairing_type,
- const std::vector<uint8_t>& code)>;
- using PairingEndListener =
- base::Callback<void(const std::string& session_id)>;
-
- class KeyExchanger {
- public:
- virtual ~KeyExchanger() = default;
-
- virtual const std::string& GetMessage() = 0;
- virtual bool ProcessMessage(const std::string& message,
- chromeos::ErrorPtr* error) = 0;
- virtual const std::string& GetKey() const = 0;
- };
-
- SecurityManager(const std::set<PairingType>& pairing_modes,
- const base::FilePath& embedded_code_path,
- bool disable_security = false);
- ~SecurityManager() override;
-
- // SecurityDelegate methods
- std::string CreateAccessToken(const UserInfo& user_info,
- const base::Time& time) override;
- UserInfo ParseAccessToken(const std::string& token,
- base::Time* time) const override;
- std::set<PairingType> GetPairingTypes() const override;
- std::set<CryptoType> GetCryptoTypes() const override;
- bool IsValidPairingCode(const std::string& auth_code) const override;
-
- bool StartPairing(PairingType mode,
- CryptoType crypto,
- std::string* session_id,
- std::string* device_commitment,
- chromeos::ErrorPtr* error) override;
-
- bool ConfirmPairing(const std::string& session_id,
- const std::string& client_commitment,
- std::string* fingerprint,
- std::string* signature,
- chromeos::ErrorPtr* error) override;
- bool CancelPairing(const std::string& session_id,
- chromeos::ErrorPtr* error) override;
-
- void RegisterPairingListeners(const PairingStartListener& on_start,
- const PairingEndListener& on_end);
-
- void SetCertificateFingerprint(const chromeos::Blob& fingerprint) {
- certificate_fingerprint_ = fingerprint;
- }
-
- private:
- FRIEND_TEST_ALL_PREFIXES(SecurityManagerTest, ThrottlePairing);
- // Allows limited number of new sessions without successful authorization.
- bool CheckIfPairingAllowed(chromeos::ErrorPtr* error);
- bool ClosePendingSession(const std::string& session_id);
- bool CloseConfirmedSession(const std::string& session_id);
-
- // If true allows unencrypted pairing and accepts any access code.
- bool is_security_disabled_{false};
- std::set<PairingType> pairing_modes_;
- const base::FilePath embedded_code_path_;
- std::string embedded_code_;
- std::map<std::string, std::unique_ptr<KeyExchanger>> pending_sessions_;
- std::map<std::string, std::unique_ptr<KeyExchanger>> confirmed_sessions_;
- mutable int pairing_attemts_{0};
- mutable base::Time block_pairing_until_;
- chromeos::SecureBlob secret_;
- chromeos::Blob certificate_fingerprint_;
- PairingStartListener on_start_;
- PairingEndListener on_end_;
-
- base::WeakPtrFactory<SecurityManager> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(SecurityManager);
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_SECURITY_MANAGER_H_
diff --git a/buffet/privet/security_manager_unittest.cc b/buffet/privet/security_manager_unittest.cc
deleted file mode 100644
index 32b7463..0000000
--- a/buffet/privet/security_manager_unittest.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/security_manager.h"
-
-#include <algorithm>
-#include <cctype>
-#include <functional>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/message_loop/message_loop.h>
-#include <base/rand_util.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
-#include <chromeos/data_encoding.h>
-#include <chromeos/key_value_store.h>
-#include <chromeos/strings/string_utils.h>
-#include <crypto/p224_spake.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/privet/openssl_utils.h"
-
-using testing::Eq;
-using testing::_;
-
-namespace privetd {
-
-namespace {
-
-bool IsBase64Char(char c) {
- return isalnum(c) || (c == '+') || (c == '/') || (c == '=');
-}
-
-bool IsBase64(const std::string& text) {
- return !text.empty() &&
- !std::any_of(text.begin(), text.end(),
- std::not1(std::ref(IsBase64Char)));
-}
-
-class MockPairingCallbacks {
- public:
- MOCK_METHOD3(OnPairingStart,
- void(const std::string& session_id,
- PairingType pairing_type,
- const std::vector<uint8_t>& code));
- MOCK_METHOD1(OnPairingEnd, void(const std::string& session_id));
-};
-
-base::FilePath GetTempFilePath() {
- base::FilePath file_path;
- EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
- return file_path;
-}
-
-} // namespace
-
-class SecurityManagerTest : public testing::Test {
- public:
- void SetUp() override {
- chromeos::Blob fingerprint;
- fingerprint.resize(256 / 8);
- base::RandBytes(fingerprint.data(), fingerprint.size());
- security_.SetCertificateFingerprint(fingerprint);
-
- chromeos::KeyValueStore store;
- store.SetString("embedded_code", "1234");
- EXPECT_TRUE(store.Save(embedded_code_path_));
- }
-
- void TearDown() override { base::DeleteFile(embedded_code_path_, false); }
-
- protected:
- void PairAndAuthenticate(std::string* fingerprint, std::string* signature) {
- std::string session_id;
- std::string device_commitment_base64;
-
- EXPECT_TRUE(security_.StartPairing(PairingType::kEmbeddedCode,
- CryptoType::kSpake_p224, &session_id,
- &device_commitment_base64, nullptr));
- EXPECT_FALSE(session_id.empty());
- EXPECT_FALSE(device_commitment_base64.empty());
-
- crypto::P224EncryptedKeyExchange spake{
- crypto::P224EncryptedKeyExchange::kPeerTypeClient, "1234"};
-
- std::string client_commitment_base64{
- chromeos::data_encoding::Base64Encode(spake.GetNextMessage())};
-
- EXPECT_TRUE(security_.ConfirmPairing(session_id, client_commitment_base64,
- fingerprint, signature, nullptr));
- EXPECT_TRUE(IsBase64(*fingerprint));
- EXPECT_TRUE(IsBase64(*signature));
-
- chromeos::Blob device_commitment;
- ASSERT_TRUE(chromeos::data_encoding::Base64Decode(device_commitment_base64,
- &device_commitment));
- spake.ProcessMessage(
- chromeos::string_utils::GetBytesAsString(device_commitment));
-
- chromeos::Blob auth_code{
- HmacSha256(chromeos::SecureBlob{spake.GetUnverifiedKey()},
- chromeos::SecureBlob{session_id})};
-
- std::string auth_code_base64{
- chromeos::data_encoding::Base64Encode(auth_code)};
-
- EXPECT_TRUE(security_.IsValidPairingCode(auth_code_base64));
- }
-
- const base::Time time_ = base::Time::FromTimeT(1410000000);
- base::MessageLoop message_loop_;
- base::FilePath embedded_code_path_{GetTempFilePath()};
- SecurityManager security_{{PairingType::kEmbeddedCode}, embedded_code_path_};
-};
-
-TEST_F(SecurityManagerTest, IsBase64) {
- EXPECT_TRUE(IsBase64(
- security_.CreateAccessToken(UserInfo{AuthScope::kUser, 7}, time_)));
-}
-
-TEST_F(SecurityManagerTest, CreateSameToken) {
- EXPECT_EQ(
- security_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555}, time_),
- security_.CreateAccessToken(UserInfo{AuthScope::kViewer, 555}, time_));
-}
-
-TEST_F(SecurityManagerTest, CreateTokenDifferentScope) {
- EXPECT_NE(
- security_.CreateAccessToken(UserInfo{AuthScope::kViewer, 456}, time_),
- security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}, time_));
-}
-
-TEST_F(SecurityManagerTest, CreateTokenDifferentUser) {
- EXPECT_NE(
- security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 456}, time_),
- security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 789}, time_));
-}
-
-TEST_F(SecurityManagerTest, CreateTokenDifferentTime) {
- EXPECT_NE(
- security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567}, time_),
- security_.CreateAccessToken(UserInfo{AuthScope::kOwner, 567},
- base::Time::FromTimeT(1400000000)));
-}
-
-TEST_F(SecurityManagerTest, CreateTokenDifferentInstance) {
- EXPECT_NE(security_.CreateAccessToken(UserInfo{AuthScope::kUser, 123}, time_),
- SecurityManager({}, base::FilePath{})
- .CreateAccessToken(UserInfo{AuthScope::kUser, 123}, time_));
-}
-
-TEST_F(SecurityManagerTest, ParseAccessToken) {
- // Multiple attempts with random secrets.
- for (size_t i = 0; i < 1000; ++i) {
- SecurityManager security{{}, base::FilePath{}};
-
- std::string token =
- security.CreateAccessToken(UserInfo{AuthScope::kUser, 5}, time_);
- base::Time time2;
- EXPECT_EQ(AuthScope::kUser,
- security.ParseAccessToken(token, &time2).scope());
- EXPECT_EQ(5u, security.ParseAccessToken(token, &time2).user_id());
- // Token timestamp resolution is one second.
- EXPECT_GE(1, std::abs((time_ - time2).InSeconds()));
- }
-}
-
-TEST_F(SecurityManagerTest, PairingNoSession) {
- std::string fingerprint;
- std::string signature;
- chromeos::ErrorPtr error;
- ASSERT_FALSE(
- security_.ConfirmPairing("123", "345", &fingerprint, &signature, &error));
- EXPECT_EQ("unknownSession", error->GetCode());
-}
-
-TEST_F(SecurityManagerTest, Pairing) {
- std::vector<std::pair<std::string, std::string> > fingerprints(2);
- for (auto& it : fingerprints) {
- PairAndAuthenticate(&it.first, &it.second);
- }
-
- // Same certificate.
- EXPECT_EQ(fingerprints.front().first, fingerprints.back().first);
-
- // Signed with different secret.
- EXPECT_NE(fingerprints.front().second, fingerprints.back().second);
-}
-
-TEST_F(SecurityManagerTest, NotifiesListenersOfSessionStartAndEnd) {
- testing::StrictMock<MockPairingCallbacks> callbacks;
- security_.RegisterPairingListeners(
- base::Bind(&MockPairingCallbacks::OnPairingStart,
- base::Unretained(&callbacks)),
- base::Bind(&MockPairingCallbacks::OnPairingEnd,
- base::Unretained(&callbacks)));
- for (auto commitment_suffix :
- std::vector<std::string>{"", "invalid_commitment"}) {
- // StartPairing should notify us that a new session has begun.
- std::string session_id;
- std::string device_commitment;
- EXPECT_CALL(callbacks, OnPairingStart(_, PairingType::kEmbeddedCode, _));
- EXPECT_TRUE(security_.StartPairing(PairingType::kEmbeddedCode,
- CryptoType::kSpake_p224, &session_id,
- &device_commitment, nullptr));
- EXPECT_FALSE(session_id.empty());
- EXPECT_FALSE(device_commitment.empty());
- testing::Mock::VerifyAndClearExpectations(&callbacks);
-
- // ConfirmPairing should notify us that the session has ended.
- EXPECT_CALL(callbacks, OnPairingEnd(Eq(session_id)));
- crypto::P224EncryptedKeyExchange spake{
- crypto::P224EncryptedKeyExchange::kPeerTypeServer, "1234"};
- std::string client_commitment =
- chromeos::data_encoding::Base64Encode(spake.GetNextMessage());
- std::string fingerprint, signature;
- // Regardless of whether the commitment is valid or not, we should get a
- // callback indicating that the pairing session is gone.
- security_.ConfirmPairing(session_id, client_commitment + commitment_suffix,
- &fingerprint, &signature, nullptr);
- testing::Mock::VerifyAndClearExpectations(&callbacks);
- }
-}
-
-TEST_F(SecurityManagerTest, CancelPairing) {
- testing::StrictMock<MockPairingCallbacks> callbacks;
- security_.RegisterPairingListeners(
- base::Bind(&MockPairingCallbacks::OnPairingStart,
- base::Unretained(&callbacks)),
- base::Bind(&MockPairingCallbacks::OnPairingEnd,
- base::Unretained(&callbacks)));
- std::string session_id;
- std::string device_commitment;
- EXPECT_CALL(callbacks, OnPairingStart(_, PairingType::kEmbeddedCode, _));
- EXPECT_TRUE(security_.StartPairing(PairingType::kEmbeddedCode,
- CryptoType::kSpake_p224, &session_id,
- &device_commitment, nullptr));
- EXPECT_CALL(callbacks, OnPairingEnd(Eq(session_id)));
- EXPECT_TRUE(security_.CancelPairing(session_id, nullptr));
-}
-
-TEST_F(SecurityManagerTest, ThrottlePairing) {
- auto pair = [this]() {
- std::string session_id;
- std::string device_commitment;
- chromeos::ErrorPtr error;
- bool result = security_.StartPairing(PairingType::kEmbeddedCode,
- CryptoType::kSpake_p224, &session_id,
- &device_commitment, &error);
- EXPECT_TRUE(result || error->GetCode() == "deviceBusy");
- return result;
- };
-
- EXPECT_TRUE(pair());
- EXPECT_TRUE(pair());
- EXPECT_TRUE(pair());
- EXPECT_FALSE(pair());
- EXPECT_GT(security_.block_pairing_until_, base::Time::Now());
- EXPECT_LE(security_.block_pairing_until_,
- base::Time::Now() + base::TimeDelta::FromMinutes(15));
-
- // Wait timeout.
- security_.block_pairing_until_ =
- base::Time::Now() - base::TimeDelta::FromMinutes(1);
-
- // Allow exactly one attempt.
- EXPECT_TRUE(pair());
- EXPECT_FALSE(pair());
-
- // Wait timeout.
- security_.block_pairing_until_ =
- base::Time::Now() - base::TimeDelta::FromMinutes(1);
-
- // Completely unblock by successfully pairing.
- std::string fingerprint;
- std::string signature;
- PairAndAuthenticate(&fingerprint, &signature);
-
- // Now we have 3 attempts again.
- EXPECT_TRUE(pair());
- EXPECT_TRUE(pair());
- EXPECT_TRUE(pair());
- EXPECT_FALSE(pair());
-}
-
-TEST_F(SecurityManagerTest, DontBlockForCanceledSessions) {
- for (int i = 0; i < 20; ++i) {
- std::string session_id;
- std::string device_commitment;
- EXPECT_TRUE(security_.StartPairing(PairingType::kEmbeddedCode,
- CryptoType::kSpake_p224, &session_id,
- &device_commitment, nullptr));
- EXPECT_TRUE(security_.CancelPairing(session_id, nullptr));
- }
-}
-
-TEST_F(SecurityManagerTest, EmbeddedCodeNotReady) {
- std::string session_id;
- std::string device_commitment;
- base::DeleteFile(embedded_code_path_, false);
- chromeos::ErrorPtr error;
- ASSERT_FALSE(security_.StartPairing(PairingType::kEmbeddedCode,
- CryptoType::kSpake_p224, &session_id,
- &device_commitment, &error));
- EXPECT_EQ("deviceBusy", error->GetCode());
-}
-
-} // namespace privetd
diff --git a/buffet/privet/shill_client.cc b/buffet/privet/shill_client.cc
deleted file mode 100644
index 48d0cef..0000000
--- a/buffet/privet/shill_client.cc
+++ /dev/null
@@ -1,503 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/shill_client.h"
-
-#include <set>
-
-#include <base/message_loop/message_loop.h>
-#include <base/stl_util.h>
-#include <chromeos/any.h>
-#include <chromeos/dbus/service_constants.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/errors/error_codes.h>
-
-using chromeos::Any;
-using chromeos::VariantDictionary;
-using dbus::ObjectPath;
-using org::chromium::flimflam::DeviceProxy;
-using org::chromium::flimflam::ServiceProxy;
-using std::map;
-using std::set;
-using std::string;
-using std::vector;
-
-namespace privetd {
-
-namespace {
-
-void IgnoreDetachEvent() {
-}
-
-bool GetStateForService(ServiceProxy* service, string* state) {
- CHECK(service) << "|service| was nullptr in GetStateForService()";
- VariantDictionary properties;
- if (!service->GetProperties(&properties, nullptr)) {
- LOG(WARNING) << "Failed to read properties from service.";
- return false;
- }
- auto property_it = properties.find(shill::kStateProperty);
- if (property_it == properties.end()) {
- LOG(WARNING) << "No state found in service properties.";
- return false;
- }
- string new_state = property_it->second.TryGet<string>();
- if (new_state.empty()) {
- LOG(WARNING) << "Invalid state value.";
- return false;
- }
- *state = new_state;
- return true;
-}
-
-ServiceState ShillServiceStateToServiceState(const string& state) {
- // TODO(wiley) What does "unconfigured" mean in a world with multiple sets
- // of WiFi credentials?
- // TODO(wiley) Detect disabled devices, update state appropriately.
- if ((state.compare(shill::kStateReady) == 0) ||
- (state.compare(shill::kStatePortal) == 0) ||
- (state.compare(shill::kStateOnline) == 0)) {
- return ServiceState::kConnected;
- }
- if ((state.compare(shill::kStateAssociation) == 0) ||
- (state.compare(shill::kStateConfiguration) == 0)) {
- return ServiceState::kConnecting;
- }
- if ((state.compare(shill::kStateFailure) == 0) ||
- (state.compare(shill::kStateActivationFailure) == 0)) {
- // TODO(wiley) Get error information off the service object.
- return ServiceState::kFailure;
- }
- if ((state.compare(shill::kStateIdle) == 0) ||
- (state.compare(shill::kStateOffline) == 0) ||
- (state.compare(shill::kStateDisconnect) == 0)) {
- return ServiceState::kOffline;
- }
- LOG(WARNING) << "Unknown state found: '" << state << "'";
- return ServiceState::kOffline;
-}
-
-} // namespace
-
-std::string ServiceStateToString(ServiceState state) {
- switch (state) {
- case ServiceState::kOffline:
- return "offline";
- case ServiceState::kFailure:
- return "failure";
- case ServiceState::kConnecting:
- return "connecting";
- case ServiceState::kConnected:
- return "connected";
- }
- LOG(ERROR) << "Unknown ServiceState value!";
- return "unknown";
-}
-
-ShillClient::ShillClient(const scoped_refptr<dbus::Bus>& bus,
- const set<string>& device_whitelist)
- : bus_{bus},
- manager_proxy_{bus_, ObjectPath{"/"}},
- device_whitelist_{device_whitelist} {
- manager_proxy_.RegisterPropertyChangedSignalHandler(
- base::Bind(&ShillClient::OnManagerPropertyChange,
- weak_factory_.GetWeakPtr()),
- base::Bind(&ShillClient::OnManagerPropertyChangeRegistration,
- weak_factory_.GetWeakPtr()));
- auto owner_changed_cb = base::Bind(&ShillClient::OnShillServiceOwnerChange,
- weak_factory_.GetWeakPtr());
- bus_->GetObjectProxy(shill::kFlimflamServiceName, ObjectPath{"/"})
- ->SetNameOwnerChangedCallback(owner_changed_cb);
-}
-
-void ShillClient::Init() {
- VLOG(2) << "ShillClient::Init();";
- CleanupConnectingService(false);
- devices_.clear();
- connectivity_state_ = ServiceState::kOffline;
- VariantDictionary properties;
- if (!manager_proxy_.GetProperties(&properties, nullptr)) {
- LOG(ERROR) << "Unable to get properties from Manager, waiting for "
- "Manager to come back online.";
- return;
- }
- auto it = properties.find(shill::kDevicesProperty);
- CHECK(it != properties.end()) << "shill should always publish a device list.";
- OnManagerPropertyChange(shill::kDevicesProperty, it->second);
-}
-
-bool ShillClient::ConnectToService(const string& ssid,
- const string& passphrase,
- const base::Closure& on_success,
- chromeos::ErrorPtr* error) {
- CleanupConnectingService(false);
- VariantDictionary service_properties;
- service_properties[shill::kTypeProperty] = Any{string{shill::kTypeWifi}};
- service_properties[shill::kSSIDProperty] = Any{ssid};
- service_properties[shill::kPassphraseProperty] = Any{passphrase};
- service_properties[shill::kSecurityProperty] = Any{
- string{passphrase.empty() ? shill::kSecurityNone : shill::kSecurityPsk}};
- service_properties[shill::kSaveCredentialsProperty] = Any{true};
- service_properties[shill::kAutoConnectProperty] = Any{true};
- ObjectPath service_path;
- if (!manager_proxy_.ConfigureService(service_properties, &service_path,
- error)) {
- return false;
- }
- if (!manager_proxy_.RequestScan(shill::kTypeWifi, error)) {
- return false;
- }
- connecting_service_.reset(new ServiceProxy{bus_, service_path});
- on_connect_success_.Reset(on_success);
- connecting_service_->RegisterPropertyChangedSignalHandler(
- base::Bind(&ShillClient::OnServicePropertyChange,
- weak_factory_.GetWeakPtr(), service_path),
- base::Bind(&ShillClient::OnServicePropertyChangeRegistration,
- weak_factory_.GetWeakPtr(), service_path));
- return true;
-}
-
-ServiceState ShillClient::GetConnectionState() const {
- return connectivity_state_;
-}
-
-bool ShillClient::AmOnline() const {
- return connectivity_state_ == ServiceState::kConnected;
-}
-
-void ShillClient::RegisterConnectivityListener(
- const ConnectivityListener& listener) {
- connectivity_listeners_.push_back(listener);
-}
-
-bool ShillClient::IsMonitoredDevice(DeviceProxy* device) {
- if (device_whitelist_.empty()) {
- return true;
- }
- VariantDictionary device_properties;
- if (!device->GetProperties(&device_properties, nullptr)) {
- LOG(ERROR) << "Devices without properties aren't whitelisted.";
- return false;
- }
- auto it = device_properties.find(shill::kInterfaceProperty);
- if (it == device_properties.end()) {
- LOG(ERROR) << "Failed to find interface property in device properties.";
- return false;
- }
- return ContainsKey(device_whitelist_, it->second.TryGet<string>());
-}
-
-void ShillClient::OnShillServiceOwnerChange(const string& old_owner,
- const string& new_owner) {
- VLOG(1) << "Shill service owner name changed to '" << new_owner << "'";
- if (new_owner.empty()) {
- CleanupConnectingService(false);
- devices_.clear();
- connectivity_state_ = ServiceState::kOffline;
- } else {
- Init(); // New service owner means shill reset!
- }
-}
-
-void ShillClient::OnManagerPropertyChangeRegistration(const string& interface,
- const string& signal_name,
- bool success) {
- VLOG(3) << "Registered ManagerPropertyChange handler.";
- CHECK(success) << "privetd requires Manager signals.";
- VariantDictionary properties;
- if (!manager_proxy_.GetProperties(&properties, nullptr)) {
- LOG(ERROR) << "Unable to get properties from Manager, waiting for "
- "Manager to come back online.";
- return;
- }
- auto it = properties.find(shill::kDevicesProperty);
- CHECK(it != properties.end()) << "Shill should always publish a device list.";
- OnManagerPropertyChange(shill::kDevicesProperty, it->second);
-}
-
-void ShillClient::OnManagerPropertyChange(const string& property_name,
- const Any& property_value) {
- if (property_name != shill::kDevicesProperty) {
- return;
- }
- VLOG(3) << "Manager's device list has changed.";
- // We're going to remove every device we haven't seen in the update.
- set<ObjectPath> device_paths_to_remove;
- for (const auto& kv : devices_) {
- device_paths_to_remove.insert(kv.first);
- }
- for (const auto& device_path : property_value.TryGet<vector<ObjectPath>>()) {
- if (!device_path.IsValid()) {
- LOG(ERROR) << "Ignoring invalid device path in Manager's device list.";
- return;
- }
- auto it = devices_.find(device_path);
- if (it != devices_.end()) {
- // Found an existing proxy. Since the whitelist never changes,
- // this still a valid device.
- device_paths_to_remove.erase(device_path);
- continue;
- }
- std::unique_ptr<DeviceProxy> device{new DeviceProxy{bus_, device_path}};
- if (!IsMonitoredDevice(device.get())) {
- continue;
- }
- device->RegisterPropertyChangedSignalHandler(
- base::Bind(&ShillClient::OnDevicePropertyChange,
- weak_factory_.GetWeakPtr(), device_path),
- base::Bind(&ShillClient::OnDevicePropertyChangeRegistration,
- weak_factory_.GetWeakPtr(), device_path));
- VLOG(3) << "Creating device proxy at " << device_path.value();
- devices_[device_path].device = std::move(device);
- }
- // Clean up devices/services related to removed devices.
- if (!device_paths_to_remove.empty()) {
- for (const ObjectPath& device_path : device_paths_to_remove) {
- devices_.erase(device_path);
- }
- UpdateConnectivityState();
- }
-}
-
-void ShillClient::OnDevicePropertyChangeRegistration(
- const ObjectPath& device_path,
- const string& interface,
- const string& signal_name,
- bool success) {
- VLOG(3) << "Registered DevicePropertyChange handler.";
- auto it = devices_.find(device_path);
- if (it == devices_.end()) {
- return;
- }
- CHECK(success) << "Failed to subscribe to Device property changes.";
- DeviceProxy* device = it->second.device.get();
- VariantDictionary properties;
- if (!device->GetProperties(&properties, nullptr)) {
- LOG(WARNING) << "Failed to get device properties?";
- return;
- }
- auto prop_it = properties.find(shill::kSelectedServiceProperty);
- if (prop_it == properties.end()) {
- LOG(WARNING) << "Failed to get device's selected service?";
- return;
- }
- OnDevicePropertyChange(device_path, shill::kSelectedServiceProperty,
- prop_it->second);
-}
-
-void ShillClient::OnDevicePropertyChange(const ObjectPath& device_path,
- const string& property_name,
- const Any& property_value) {
- // We only care about selected services anyway.
- if (property_name != shill::kSelectedServiceProperty) {
- return;
- }
- // If the device isn't our list of whitelisted devices, ignore it.
- auto it = devices_.find(device_path);
- if (it == devices_.end()) {
- return;
- }
- DeviceState& device_state = it->second;
- ObjectPath service_path{property_value.TryGet<ObjectPath>()};
- if (!service_path.IsValid()) {
- LOG(ERROR) << "Device at " << device_path.value()
- << " selected invalid service path.";
- return;
- }
- VLOG(3) << "Device at " << it->first.value() << " has selected service at "
- << service_path.value();
- bool removed_old_service{false};
- if (device_state.selected_service) {
- if (device_state.selected_service->GetObjectPath() == service_path) {
- return; // Spurious update?
- }
- device_state.selected_service.reset();
- device_state.service_state = ServiceState::kOffline;
- removed_old_service = true;
- }
- std::shared_ptr<ServiceProxy> new_service;
- const bool reuse_connecting_service =
- service_path.value() != "/" && connecting_service_ &&
- connecting_service_->GetObjectPath() == service_path;
- if (reuse_connecting_service) {
- new_service = connecting_service_;
- // When we reuse the connecting service, we need to make sure that our
- // cached state is correct. Normally, we do this by relying reading the
- // state when our signal handlers finish registering, but this may have
- // happened long in the past for the connecting service.
- string state;
- if (GetStateForService(new_service.get(), &state)) {
- device_state.service_state = ShillServiceStateToServiceState(state);
- } else {
- LOG(WARNING) << "Failed to read properties from existing service "
- "on selection.";
- }
- } else if (service_path.value() != "/") {
- // The device has selected a new service we haven't see before.
- new_service.reset(new ServiceProxy{bus_, service_path});
- new_service->RegisterPropertyChangedSignalHandler(
- base::Bind(&ShillClient::OnServicePropertyChange,
- weak_factory_.GetWeakPtr(), service_path),
- base::Bind(&ShillClient::OnServicePropertyChangeRegistration,
- weak_factory_.GetWeakPtr(), service_path));
- }
- device_state.selected_service = new_service;
- if (reuse_connecting_service || removed_old_service) {
- UpdateConnectivityState();
- }
-}
-
-void ShillClient::OnServicePropertyChangeRegistration(const ObjectPath& path,
- const string& interface,
- const string& signal_name,
- bool success) {
- VLOG(3) << "OnServicePropertyChangeRegistration(" << path.value() << ");";
- ServiceProxy* service{nullptr};
- if (connecting_service_ && connecting_service_->GetObjectPath() == path) {
- // Note that the connecting service might also be a selected service.
- service = connecting_service_.get();
- if (!success) {
- CleanupConnectingService(false);
- }
- } else {
- for (const auto& kv : devices_) {
- if (kv.second.selected_service &&
- kv.second.selected_service->GetObjectPath() == path) {
- service = kv.second.selected_service.get();
- break;
- }
- }
- }
- if (service == nullptr || !success) {
- return; // A failure or success for a proxy we no longer care about.
- }
- VariantDictionary properties;
- if (!service->GetProperties(&properties, nullptr)) {
- return;
- }
- // Give ourselves property changed signals for the initial property
- // values.
- auto it = properties.find(shill::kStateProperty);
- if (it != properties.end()) {
- OnServicePropertyChange(path, shill::kStateProperty, it->second);
- }
- it = properties.find(shill::kSignalStrengthProperty);
- if (it != properties.end()) {
- OnServicePropertyChange(path, shill::kSignalStrengthProperty, it->second);
- }
-}
-
-void ShillClient::OnServicePropertyChange(const ObjectPath& service_path,
- const string& property_name,
- const Any& property_value) {
- VLOG(3) << "ServicePropertyChange(" << service_path.value() << ", "
- << property_name << ", ...);";
- if (property_name == shill::kStateProperty) {
- const string state{property_value.TryGet<string>()};
- if (state.empty()) {
- VLOG(3) << "Invalid service state update.";
- return;
- }
- VLOG(3) << "New service state=" << state;
- OnStateChangeForSelectedService(service_path, state);
- OnStateChangeForConnectingService(service_path, state);
- } else if (property_name == shill::kSignalStrengthProperty) {
- OnStrengthChangeForConnectingService(service_path,
- property_value.TryGet<uint8_t>());
- }
-}
-
-void ShillClient::OnStateChangeForConnectingService(
- const ObjectPath& service_path,
- const string& state) {
- if (!connecting_service_ ||
- connecting_service_->GetObjectPath() != service_path ||
- ShillServiceStateToServiceState(state) != ServiceState::kConnected) {
- return;
- }
- connecting_service_reset_pending_ = true;
- on_connect_success_.callback().Run();
- CleanupConnectingService(true);
-}
-
-void ShillClient::OnStrengthChangeForConnectingService(
- const ObjectPath& service_path,
- uint8_t signal_strength) {
- if (!connecting_service_ ||
- connecting_service_->GetObjectPath() != service_path ||
- signal_strength <= 0 || have_called_connect_) {
- return;
- }
- VLOG(1) << "Connecting service has signal. Calling Connect().";
- have_called_connect_ = true;
- // Failures here indicate that we've already connected,
- // or are connecting, or some other very unexciting thing.
- // Ignore all that, and rely on state changes to detect
- // connectivity.
- connecting_service_->Connect(nullptr);
-}
-
-void ShillClient::OnStateChangeForSelectedService(
- const ObjectPath& service_path,
- const string& state) {
- // Find the device/service pair responsible for this update
- VLOG(3) << "State for potentially selected service " << service_path.value()
- << " have changed to " << state;
- for (auto& kv : devices_) {
- if (kv.second.selected_service &&
- kv.second.selected_service->GetObjectPath() == service_path) {
- VLOG(3) << "Updated cached connection state for selected service.";
- kv.second.service_state = ShillServiceStateToServiceState(state);
- UpdateConnectivityState();
- return;
- }
- }
-}
-
-void ShillClient::UpdateConnectivityState() {
- // Update the connectivity state of the device by picking the
- // state of the currently most connected selected service.
- ServiceState new_connectivity_state{ServiceState::kOffline};
- for (const auto& kv : devices_) {
- if (kv.second.service_state > new_connectivity_state) {
- new_connectivity_state = kv.second.service_state;
- }
- }
- VLOG(1) << "Connectivity changed: "
- << ServiceStateToString(connectivity_state_) << " -> "
- << ServiceStateToString(new_connectivity_state);
- // Notify listeners even if state changed to the same value. Listeners may
- // want to handle this event.
- connectivity_state_ = new_connectivity_state;
- // We may call UpdateConnectivityState whenever we mutate a data structure
- // such that our connectivity status could change. However, we don't want
- // to allow people to call into ShillClient while some other operation is
- // underway. Therefore, call our callbacks later, when we're in a good
- // state.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&ShillClient::NotifyConnectivityListeners,
- weak_factory_.GetWeakPtr(), AmOnline()));
-}
-
-void ShillClient::NotifyConnectivityListeners(bool am_online) {
- VLOG(3) << "Notifying connectivity listeners that online=" << am_online;
- for (const auto& listener : connectivity_listeners_) {
- listener.Run(am_online);
- }
-}
-
-void ShillClient::CleanupConnectingService(bool check_for_reset_pending) {
- if (check_for_reset_pending && !connecting_service_reset_pending_) {
- return; // Must have called connect before we got here.
- }
- if (connecting_service_) {
- connecting_service_->ReleaseObjectProxy(base::Bind(&IgnoreDetachEvent));
- connecting_service_.reset();
- }
- on_connect_success_.Cancel();
- have_called_connect_ = false;
- connecting_service_reset_pending_ = false;
-}
-
-} // namespace privetd
diff --git a/buffet/privet/shill_client.h b/buffet/privet/shill_client.h
deleted file mode 100644
index 6839b15..0000000
--- a/buffet/privet/shill_client.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_SHILL_CLIENT_H_
-#define BUFFET_PRIVET_SHILL_CLIENT_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/cancelable_callback.h>
-#include <base/macros.h>
-#include <base/memory/ref_counted.h>
-#include <base/memory/weak_ptr.h>
-#include <dbus/bus.h>
-
-#include "shill/dbus-proxies.h"
-
-namespace privetd {
-
-enum class ServiceState {
- kOffline = 0,
- kFailure,
- kConnecting,
- kConnected,
-};
-
-std::string ServiceStateToString(ServiceState state);
-
-class ShillClient final {
- public:
- // A callback that interested parties can register to be notified of
- // transitions from online to offline and vice versa. The boolean
- // parameter will be true if we're online, and false if we're offline.
- using ConnectivityListener = base::Callback<void(bool)>;
-
- ShillClient(const scoped_refptr<dbus::Bus>& bus,
- const std::set<std::string>& device_whitelist);
- ~ShillClient() = default;
-
- void Init();
- void RegisterConnectivityListener(const ConnectivityListener& listener);
- // Causes shill to attempt to connect to the given network with the given
- // passphrase. This is accomplished by:
- // 1) Configuring a service through the Manager with the SSID and passphrase.
- // 2) Calling Connect() on the service.
- // 2) Monitoring the returned Service object until we reach an online state,
- // an error state, or another call to ConnectToService() occurs.
- // Returns false on immediate failures with some descriptive codes in |error|.
- bool ConnectToService(const std::string& ssid,
- const std::string& passphrase,
- const base::Closure& on_success,
- chromeos::ErrorPtr* error);
- ServiceState GetConnectionState() const;
- bool AmOnline() const;
-
- private:
- struct DeviceState {
- std::unique_ptr<org::chromium::flimflam::DeviceProxy> device;
- // ServiceProxy objects are shared because the connecting service will
- // also be the selected service for a device, but is not always the selected
- // service (for instance, in the period between configuring a WiFi service
- // with credentials, and when Connect() is called.)
- std::shared_ptr<org::chromium::flimflam::ServiceProxy> selected_service;
- ServiceState service_state{ServiceState::kOffline};
- };
-
- bool IsMonitoredDevice(org::chromium::flimflam::DeviceProxy* device);
- void OnShillServiceOwnerChange(const std::string& old_owner,
- const std::string& new_owner);
- void OnManagerPropertyChangeRegistration(const std::string& interface,
- const std::string& signal_name,
- bool success);
- void OnManagerPropertyChange(const std::string& property_name,
- const chromeos::Any& property_value);
- void OnDevicePropertyChangeRegistration(const dbus::ObjectPath& device_path,
- const std::string& interface,
- const std::string& signal_name,
- bool success);
- void OnDevicePropertyChange(const dbus::ObjectPath& device_path,
- const std::string& property_name,
- const chromeos::Any& property_value);
- void OnServicePropertyChangeRegistration(const dbus::ObjectPath& path,
- const std::string& interface,
- const std::string& signal_name,
- bool success);
- void OnServicePropertyChange(const dbus::ObjectPath& service_path,
- const std::string& property_name,
- const chromeos::Any& property_value);
-
- void OnStateChangeForConnectingService(const dbus::ObjectPath& service_path,
- const std::string& state);
- void OnStrengthChangeForConnectingService(
- const dbus::ObjectPath& service_path,
- uint8_t signal_strength);
- void OnStateChangeForSelectedService(const dbus::ObjectPath& service_path,
- const std::string& state);
- void UpdateConnectivityState();
- void NotifyConnectivityListeners(bool am_online);
- // Clean up state related to a connecting service. If
- // |check_for_reset_pending| is set, then we'll check to see if we've called
- // ConnectToService() in the time since a task to call this function was
- // posted.
- void CleanupConnectingService(bool check_for_reset_pending);
-
- const scoped_refptr<dbus::Bus> bus_;
- org::chromium::flimflam::ManagerProxy manager_proxy_;
- // There is logic that assumes we will never change this device list
- // in OnManagerPropertyChange. Do not be tempted to remove this const.
- const std::set<std::string> device_whitelist_;
- std::vector<ConnectivityListener> connectivity_listeners_;
-
- // State for tracking where we are in our attempts to connect to a service.
- bool connecting_service_reset_pending_{false};
- bool have_called_connect_{false};
- std::shared_ptr<org::chromium::flimflam::ServiceProxy> connecting_service_;
- base::CancelableClosure on_connect_success_;
-
- // State for tracking our online connectivity.
- std::map<dbus::ObjectPath, DeviceState> devices_;
- ServiceState connectivity_state_{ServiceState::kOffline};
-
- base::WeakPtrFactory<ShillClient> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ShillClient);
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_SHILL_CLIENT_H_
diff --git a/buffet/privet/wifi_bootstrap_manager.cc b/buffet/privet/wifi_bootstrap_manager.cc
deleted file mode 100644
index 975717c..0000000
--- a/buffet/privet/wifi_bootstrap_manager.cc
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/wifi_bootstrap_manager.h"
-
-#include <base/logging.h>
-#include <base/memory/weak_ptr.h>
-#include <base/message_loop/message_loop.h>
-#include <chromeos/bind_lambda.h>
-#include <chromeos/key_value_store.h>
-
-#include "buffet/privet/ap_manager_client.h"
-#include "buffet/privet/constants.h"
-#include "buffet/privet/shill_client.h"
-
-namespace privetd {
-
-namespace {
-const int kConnectTimeoutSeconds = 60;
-const int kBootstrapTimeoutSeconds = 600;
-const int kMonitorTimeoutSeconds = 120;
-}
-
-WifiBootstrapManager::WifiBootstrapManager(
- const std::string& last_configured_ssid,
- ShillClient* shill_client,
- ApManagerClient* ap_manager_client,
- CloudDelegate* gcd)
- : shill_client_{shill_client},
- ap_manager_client_{ap_manager_client},
- ssid_generator_{gcd, this},
- last_configured_ssid_{last_configured_ssid} {
- cloud_observer_.Add(gcd);
-}
-
-void WifiBootstrapManager::Init() {
- CHECK(!is_initialized_);
- std::string ssid = ssid_generator_.GenerateSsid();
- if (ssid.empty())
- return; // Delay initialization until ssid_generator_ is ready.
- UpdateConnectionState();
- shill_client_->RegisterConnectivityListener(
- base::Bind(&WifiBootstrapManager::OnConnectivityChange,
- lifetime_weak_factory_.GetWeakPtr()));
- if (last_configured_ssid_.empty()) {
- StartBootstrapping();
- } else {
- StartMonitoring();
- }
- is_initialized_ = true;
-}
-
-void WifiBootstrapManager::RegisterStateListener(
- const StateListener& listener) {
- // Notify about current state.
- listener.Run(state_);
- state_listeners_.push_back(listener);
-}
-
-void WifiBootstrapManager::StartBootstrapping() {
- if (shill_client_->AmOnline()) {
- // If one of the devices we monitor for connectivity is online, we need not
- // start an AP. For most devices, this is a situation which happens in
- // testing when we have an ethernet connection. If you need to always
- // start an AP to bootstrap WiFi credentials, then add your WiFi interface
- // to the device whitelist.
- StartMonitoring();
- return;
- }
-
- UpdateState(kBootstrapping);
- if (!last_configured_ssid_.empty()) {
- // If we have been configured before, we'd like to periodically take down
- // our AP and find out if we can connect again. Many kinds of failures are
- // transient, and having an AP up prohibits us from connecting as a client.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&WifiBootstrapManager::OnBootstrapTimeout,
- tasks_weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(kBootstrapTimeoutSeconds));
- }
- // TODO(vitalybuka): Add SSID probing.
- std::string ssid = ssid_generator_.GenerateSsid();
- CHECK(!ssid.empty());
- ap_manager_client_->Start(ssid);
-}
-
-void WifiBootstrapManager::EndBootstrapping() {
- ap_manager_client_->Stop();
-}
-
-void WifiBootstrapManager::StartConnecting(const std::string& ssid,
- const std::string& passphrase) {
- VLOG(1) << "WiFi is attempting to connect. (ssid=" << ssid
- << ", pass=" << passphrase << ").";
- UpdateState(kConnecting);
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&WifiBootstrapManager::OnConnectTimeout,
- tasks_weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(kConnectTimeoutSeconds));
- shill_client_->ConnectToService(
- ssid, passphrase, base::Bind(&WifiBootstrapManager::OnConnectSuccess,
- tasks_weak_factory_.GetWeakPtr(), ssid),
- nullptr);
-}
-
-void WifiBootstrapManager::EndConnecting() {
-}
-
-void WifiBootstrapManager::StartMonitoring() {
- VLOG(1) << "Monitoring connectivity.";
- // We already have a callback in place with |shill_client_| to update our
- // connectivity state. See OnConnectivityChange().
- UpdateState(kMonitoring);
-}
-
-void WifiBootstrapManager::EndMonitoring() {
-}
-
-void WifiBootstrapManager::UpdateState(State new_state) {
- VLOG(3) << "Switching state from " << state_ << " to " << new_state;
- // Abort irrelevant tasks.
- tasks_weak_factory_.InvalidateWeakPtrs();
-
- switch (state_) {
- case kDisabled:
- break;
- case kBootstrapping:
- EndBootstrapping();
- break;
- case kMonitoring:
- EndMonitoring();
- break;
- case kConnecting:
- EndConnecting();
- break;
- }
-
- if (new_state != state_) {
- state_ = new_state;
- // Post with weak ptr to avoid notification after this object destroyed.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&WifiBootstrapManager::NotifyStateListeners,
- lifetime_weak_factory_.GetWeakPtr(), new_state));
- } else {
- VLOG(3) << "Not notifying listeners of state change, "
- << "because the states are the same.";
- }
-}
-
-void WifiBootstrapManager::NotifyStateListeners(State new_state) const {
- for (const StateListener& listener : state_listeners_)
- listener.Run(new_state);
-}
-
-const ConnectionState& WifiBootstrapManager::GetConnectionState() const {
- return connection_state_;
-}
-
-const SetupState& WifiBootstrapManager::GetSetupState() const {
- return setup_state_;
-}
-
-bool WifiBootstrapManager::ConfigureCredentials(const std::string& ssid,
- const std::string& passphrase,
- chromeos::ErrorPtr* error) {
- setup_state_ = SetupState{SetupState::kInProgress};
- // TODO(vitalybuka): Find more reliable way to finish request or move delay
- // into PrivetHandler as it's very HTTP specific.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&WifiBootstrapManager::StartConnecting,
- tasks_weak_factory_.GetWeakPtr(), ssid, passphrase),
- base::TimeDelta::FromSeconds(kSetupDelaySeconds));
- return true;
-}
-
-std::string WifiBootstrapManager::GetCurrentlyConnectedSsid() const {
- // TODO(vitalybuka): Get from shill, if possible.
- return last_configured_ssid_;
-}
-
-std::string WifiBootstrapManager::GetHostedSsid() const {
- return ap_manager_client_->GetSsid();
-}
-
-std::set<WifiType> WifiBootstrapManager::GetTypes() const {
- // TODO(wiley) This should do some system work to figure this out.
- return {WifiType::kWifi24};
-}
-
-void WifiBootstrapManager::OnDeviceInfoChanged() {
- // Initialization was delayed until buffet is ready.
- if (!is_initialized_)
- Init();
-}
-
-void WifiBootstrapManager::OnConnectSuccess(const std::string& ssid) {
- VLOG(1) << "Wifi was connected successfully";
- last_configured_ssid_ = ssid;
- setup_state_ = SetupState{SetupState::kSuccess};
- StartMonitoring();
-}
-
-void WifiBootstrapManager::OnBootstrapTimeout() {
- VLOG(1) << "Bootstrapping has timed out.";
- StartMonitoring();
-}
-
-void WifiBootstrapManager::OnConnectTimeout() {
- VLOG(1) << "Wifi timed out while connecting";
- chromeos::ErrorPtr error;
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
- errors::kInvalidState,
- "Failed to connect to provided network");
- setup_state_ = SetupState{std::move(error)};
- StartBootstrapping();
-}
-
-void WifiBootstrapManager::OnConnectivityChange(bool is_connected) {
- VLOG(3) << "ConnectivityChanged: " << is_connected;
- UpdateConnectionState();
-
- if (state_ == kBootstrapping) {
- StartMonitoring();
- return;
- }
- if (state_ == kMonitoring) {
- if (is_connected) {
- tasks_weak_factory_.InvalidateWeakPtrs();
- } else {
- // Tasks queue may have more than one OnMonitorTimeout enqueued. The
- // first one could be executed as it would change the state and abort the
- // rest.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&WifiBootstrapManager::OnMonitorTimeout,
- tasks_weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(kMonitorTimeoutSeconds));
- }
- }
-}
-
-void WifiBootstrapManager::OnMonitorTimeout() {
- VLOG(1) << "Spent too long offline. Entering bootstrap mode.";
- // TODO(wiley) Retrieve relevant errors from shill.
- StartBootstrapping();
-}
-
-void WifiBootstrapManager::UpdateConnectionState() {
- connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- if (last_configured_ssid_.empty())
- return;
- ServiceState service_state{shill_client_->GetConnectionState()};
- switch (service_state) {
- case ServiceState::kOffline:
- connection_state_ = ConnectionState{ConnectionState::kOffline};
- return;
- case ServiceState::kFailure: {
- // TODO(wiley) Pull error information from somewhere.
- chromeos::ErrorPtr error;
- chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
- errors::kInvalidState, "Unknown WiFi error");
- connection_state_ = ConnectionState{std::move(error)};
- return;
- }
- case ServiceState::kConnecting:
- connection_state_ = ConnectionState{ConnectionState::kConnecting};
- return;
- case ServiceState::kConnected:
- connection_state_ = ConnectionState{ConnectionState::kOnline};
- return;
- }
- chromeos::ErrorPtr error;
- chromeos::Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
- errors::kInvalidState,
- "Unknown state returned from ShillClient: %s",
- ServiceStateToString(service_state).c_str());
- connection_state_ = ConnectionState{std::move(error)};
-}
-
-} // namespace privetd
diff --git a/buffet/privet/wifi_bootstrap_manager.h b/buffet/privet/wifi_bootstrap_manager.h
deleted file mode 100644
index 5f0a4b5..0000000
--- a/buffet/privet/wifi_bootstrap_manager.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_WIFI_BOOTSTRAP_MANAGER_H_
-#define BUFFET_PRIVET_WIFI_BOOTSTRAP_MANAGER_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-#include <base/scoped_observer.h>
-
-#include "buffet/privet/cloud_delegate.h"
-#include "buffet/privet/privet_types.h"
-#include "buffet/privet/wifi_delegate.h"
-#include "buffet/privet/wifi_ssid_generator.h"
-
-namespace privetd {
-
-class ApManagerClient;
-class CloudDelegate;
-class DeviceDelegate;
-class ShillClient;
-
-class WifiBootstrapManager : public WifiDelegate,
- public CloudDelegate::Observer {
- public:
- enum State {
- kDisabled,
- kBootstrapping,
- kMonitoring,
- kConnecting,
- };
-
- using StateListener = base::Callback<void(State)>;
-
- WifiBootstrapManager(const std::string& last_configured_ssid,
- ShillClient* shill_client,
- ApManagerClient* ap_manager_client,
- CloudDelegate* gcd);
- ~WifiBootstrapManager() override = default;
- virtual void Init();
- void RegisterStateListener(const StateListener& listener);
-
- // Overrides from WifiDelegate.
- const ConnectionState& GetConnectionState() const override;
- const SetupState& GetSetupState() const override;
- bool ConfigureCredentials(const std::string& ssid,
- const std::string& passphrase,
- chromeos::ErrorPtr* error) override;
- std::string GetCurrentlyConnectedSsid() const override;
- std::string GetHostedSsid() const override;
- std::set<WifiType> GetTypes() const override;
-
- // Overrides from CloudDelegate::Observer.
- void OnDeviceInfoChanged() override;
-
- private:
- // These Start* tasks:
- // 1) Do state appropriate work for entering the indicated state.
- // 2) Update the state variable to reflect that we're in a new state
- // 3) Call StateListeners to notify that we've transitioned.
- // These End* tasks perform cleanup on leaving indicated state.
- void StartBootstrapping();
- void EndBootstrapping();
-
- void StartConnecting(const std::string& ssid, const std::string& passphrase);
- void EndConnecting();
-
- void StartMonitoring();
- void EndMonitoring();
-
- // Update the current state, post tasks to notify listeners accordingly to
- // the MessageLoop.
- void UpdateState(State new_state);
- void NotifyStateListeners(State new_state) const;
-
- // If we've been bootstrapped successfully before, and we're bootstrapping
- // again because we slipped offline for a sufficiently longtime, we want
- // to return to monitoring mode periodically in case our connectivity issues
- // were temporary.
- void OnBootstrapTimeout();
- void OnConnectTimeout();
- void OnConnectSuccess(const std::string& ssid);
- void OnConnectivityChange(bool is_connected);
- void OnMonitorTimeout();
- void UpdateConnectionState();
-
- // Initialization could be delayed if ssid_generator_ is not ready.
- bool is_initialized_{false};
- State state_{kDisabled};
- // Setup state is the temporal state of the most recent bootstrapping attempt.
- // It is not persisted to disk.
- SetupState setup_state_{SetupState::kNone};
- ConnectionState connection_state_{ConnectionState::kDisabled};
- ShillClient* shill_client_;
- ApManagerClient* ap_manager_client_;
- WifiSsidGenerator ssid_generator_;
-
- std::vector<StateListener> state_listeners_;
- bool currently_online_{false};
- std::string last_configured_ssid_;
-
- ScopedObserver<CloudDelegate, CloudDelegate::Observer> cloud_observer_{this};
-
- // Helps to reset irrelevant tasks switching state.
- base::WeakPtrFactory<WifiBootstrapManager> tasks_weak_factory_{this};
-
- base::WeakPtrFactory<WifiBootstrapManager> lifetime_weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(WifiBootstrapManager);
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_WIFI_BOOTSTRAP_MANAGER_H_
diff --git a/buffet/privet/wifi_delegate.h b/buffet/privet/wifi_delegate.h
deleted file mode 100644
index f350652..0000000
--- a/buffet/privet/wifi_delegate.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_WIFI_DELEGATE_H_
-#define BUFFET_PRIVET_WIFI_DELEGATE_H_
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include "buffet/privet/privet_types.h"
-
-namespace privetd {
-
-enum class WifiType {
- kWifi24,
- kWifi50,
-};
-
-// Interface to provide WiFi functionality for PrivetHandler.
-class WifiDelegate {
- public:
- WifiDelegate() = default;
- virtual ~WifiDelegate() = default;
-
- // Returns status of the WiFi connection.
- virtual const ConnectionState& GetConnectionState() const = 0;
-
- // Returns status of the last WiFi setup.
- virtual const SetupState& GetSetupState() const = 0;
-
- // Starts WiFi setup. Device should try to connect to provided SSID and
- // password and store them on success. Result of setup should be available
- // using GetSetupState().
- // Final setup state can be retrieved with GetSetupState().
- virtual bool ConfigureCredentials(const std::string& ssid,
- const std::string& password,
- chromeos::ErrorPtr* error) = 0;
-
- // Returns SSID of the currently configured WiFi network. Empty string, if
- // WiFi has not been configured yet.
- virtual std::string GetCurrentlyConnectedSsid() const = 0;
-
- // Returns SSID of the WiFi network hosted by this device. Empty if device is
- // not in setup or P2P modes.
- virtual std::string GetHostedSsid() const = 0;
-
- // Returns list of supported WiFi types. Currently it's just frequencies.
- virtual std::set<WifiType> GetTypes() const = 0;
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_WIFI_DELEGATE_H_
diff --git a/buffet/privet/wifi_ssid_generator.cc b/buffet/privet/wifi_ssid_generator.cc
deleted file mode 100644
index 0fa0c7c..0000000
--- a/buffet/privet/wifi_ssid_generator.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/wifi_ssid_generator.h"
-
-#include <bitset>
-
-#include <base/bind.h>
-#include <base/rand_util.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/stringprintf.h>
-
-#include "buffet/privet/cloud_delegate.h"
-#include "buffet/privet/device_delegate.h"
-#include "buffet/privet/wifi_delegate.h"
-
-namespace privetd {
-
-namespace {
-
-const int kDeviceNameSize = 20;
-// [DeviceName+Idx <= 20].[modelID == 5][flags == 2]prv
-const char kSsidFormat[] = "%s %s.%5.5s%2.2sprv";
-
-const char base64chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-bool IsSetupNeeded(const ConnectionState& state) {
- if (state.error())
- return true;
- switch (state.status()) {
- case ConnectionState::kUnconfigured:
- return true;
- case ConnectionState::kDisabled:
- case ConnectionState::kConnecting:
- case ConnectionState::kOnline:
- case ConnectionState::kOffline:
- return false;
- }
- CHECK(false);
- return false;
-}
-
-} // namespace
-
-WifiSsidGenerator::WifiSsidGenerator(const CloudDelegate* cloud,
- const WifiDelegate* wifi)
- : gcd_(cloud), wifi_(wifi), get_random_(base::Bind(&base::RandInt, 0, 99)) {
- CHECK(gcd_);
-}
-
-std::string WifiSsidGenerator::GenerateFlags() const {
- std::bitset<6> flags1;
- // Device needs WiFi configuration.
- flags1[0] = wifi_ && IsSetupNeeded(wifi_->GetConnectionState());
- // Device needs GCD registration.
- flags1[1] = IsSetupNeeded(gcd_->GetConnectionState());
-
- std::bitset<6> flags2;
- // Device is discoverable over WiFi.
- flags2[0] = true;
-
- std::string result{2, base64chars[0]};
- result[0] = base64chars[flags1.to_ulong()];
- result[1] = base64chars[flags2.to_ulong()];
- return result;
-}
-
-std::string WifiSsidGenerator::GenerateSsid() const {
- std::string name;
- std::string model_id;
- if (!gcd_ || !gcd_->GetName(&name, nullptr) ||
- !gcd_->GetModelId(&model_id, nullptr)) {
- return std::string();
- }
- std::string idx{base::IntToString(get_random_.Run())};
- name = name.substr(0, kDeviceNameSize - idx.size() - 1);
- CHECK_EQ(5u, model_id.size());
-
- std::string result =
- base::StringPrintf(kSsidFormat, name.c_str(), idx.c_str(),
- model_id.c_str(), GenerateFlags().c_str());
- CHECK_EQ(result[result.size() - 11], '.');
- return result;
-}
-
-void WifiSsidGenerator::SetRandomForTests(int n) {
- get_random_ = base::Bind(&base::RandInt, n, n);
-}
-
-} // namespace privetd
diff --git a/buffet/privet/wifi_ssid_generator.h b/buffet/privet/wifi_ssid_generator.h
deleted file mode 100644
index 33e9628..0000000
--- a/buffet/privet/wifi_ssid_generator.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_PRIVET_WIFI_SSID_GENERATOR_H_
-#define BUFFET_PRIVET_WIFI_SSID_GENERATOR_H_
-
-#include <string>
-
-#include <base/callback.h>
-
-namespace privetd {
-
-class CloudDelegate;
-class WifiDelegate;
-
-class WifiSsidGenerator final {
- public:
- WifiSsidGenerator(const CloudDelegate* gcd, const WifiDelegate* wifi);
- ~WifiSsidGenerator() = default;
-
- std::string GenerateFlags() const;
-
- // Can return empty string if CloudDelegate is not ready.
- std::string GenerateSsid() const;
-
- private:
- friend class WifiSsidGeneratorTest;
-
- // Sets object to use |n| instead of random number for SSID generation.
- void SetRandomForTests(int n);
-
- const CloudDelegate* gcd_{nullptr};
- const WifiDelegate* wifi_{nullptr};
-
- base::Callback<int(void)> get_random_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiSsidGenerator);
-};
-
-} // namespace privetd
-
-#endif // BUFFET_PRIVET_WIFI_SSID_GENERATOR_H_
diff --git a/buffet/privet/wifi_ssid_generator_unittest.cc b/buffet/privet/wifi_ssid_generator_unittest.cc
deleted file mode 100644
index 16c4475..0000000
--- a/buffet/privet/wifi_ssid_generator_unittest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/privet/wifi_ssid_generator.h"
-
-#include <base/strings/utf_string_conversions.h>
-#include <gtest/gtest.h>
-
-#include "buffet/privet/mock_delegates.h"
-#include "buffet/privet/openssl_utils.h"
-
-namespace privetd {
-
-class WifiSsidGeneratorTest : public testing::Test {
- protected:
- void SetRandomForTests(int n) { ssid_generator_.SetRandomForTests(n); }
-
- testing::StrictMock<MockCloudDelegate> gcd_;
- testing::StrictMock<MockWifiDelegate> wifi_;
-
- WifiSsidGenerator ssid_generator_{&gcd_, &wifi_};
-};
-
-TEST_F(WifiSsidGeneratorTest, GenerateFlags) {
- EXPECT_EQ(ssid_generator_.GenerateFlags().size(), 2);
-
- wifi_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- gcd_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- EXPECT_EQ("DB", ssid_generator_.GenerateFlags());
-
- wifi_.connection_state_ = ConnectionState{ConnectionState::kOnline};
- EXPECT_EQ("CB", ssid_generator_.GenerateFlags());
-
- gcd_.connection_state_ = ConnectionState{ConnectionState::kOffline};
- EXPECT_EQ("AB", ssid_generator_.GenerateFlags());
-
- wifi_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- EXPECT_EQ("BB", ssid_generator_.GenerateFlags());
-}
-
-TEST_F(WifiSsidGeneratorTest, GenerateSsid31orLess) {
- EXPECT_LE(ssid_generator_.GenerateSsid().size(), 31);
-}
-
-TEST_F(WifiSsidGeneratorTest, GenerateSsidValue) {
- SetRandomForTests(47);
- EXPECT_EQ("TestDevice 47.ABMIDABprv", ssid_generator_.GenerateSsid());
-
- SetRandomForTests(9);
- EXPECT_EQ("TestDevice 9.ABMIDABprv", ssid_generator_.GenerateSsid());
-}
-
-TEST_F(WifiSsidGeneratorTest, GenerateSsidLongName) {
- SetRandomForTests(99);
- EXPECT_CALL(gcd_, GetName(_, _))
- .WillRepeatedly(
- DoAll(SetArgPointee<0>("Very Long Device Name"), Return(true)));
- EXPECT_EQ("Very Long Device 99.ABMIDABprv", ssid_generator_.GenerateSsid());
-}
-
-TEST_F(WifiSsidGeneratorTest, GenerateSsidNoName) {
- SetRandomForTests(99);
- EXPECT_CALL(gcd_, GetName(_, _)).WillRepeatedly(Return(false));
- EXPECT_EQ("", ssid_generator_.GenerateSsid());
-}
-
-} // namespace privetd
diff --git a/buffet/registration_status.cc b/buffet/registration_status.cc
deleted file mode 100644
index 653715c..0000000
--- a/buffet/registration_status.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/registration_status.h"
-
-#include <base/logging.h>
-
-namespace buffet {
-
-std::string StatusToString(RegistrationStatus status) {
- switch (status) {
- case RegistrationStatus::kUnconfigured:
- return "unconfigured";
- case RegistrationStatus::kConnecting:
- return "connecting";
- case RegistrationStatus::kConnected:
- return "connected";
- case RegistrationStatus::kInvalidCredentials:
- return "invalid_credentials";
- }
- CHECK(0) << "Unknown status";
- return "unknown";
-}
-
-} // namespace buffet
diff --git a/buffet/registration_status.h b/buffet/registration_status.h
deleted file mode 100644
index 6b75f4d..0000000
--- a/buffet/registration_status.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_REGISTRATION_STATUS_H_
-#define BUFFET_REGISTRATION_STATUS_H_
-
-#include <string>
-
-namespace buffet {
-
-// See the DBus interface XML file for complete descriptions of these states.
-enum class RegistrationStatus {
- kUnconfigured, // We have no credentials.
- kConnecting, // We have credentials but not yet connected.
- kConnected, // We're registered and connected to the cloud.
- kInvalidCredentials, // Our registration has been revoked.
-};
-
-std::string StatusToString(RegistrationStatus status);
-
-} // namespace buffet
-
-#endif // BUFFET_REGISTRATION_STATUS_H_
diff --git a/buffet/states/error_codes.cc b/buffet/states/error_codes.cc
deleted file mode 100644
index 3faea7e..0000000
--- a/buffet/states/error_codes.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/states/error_codes.h"
-
-namespace buffet {
-namespace errors {
-namespace state {
-
-const char kDomain[] = "buffet_state";
-
-const char kPackageNameMissing[] = "package_name_missing";
-const char kPropertyNameMissing[] = "property_name_missing";
-const char kPropertyNotDefined[] = "property_not_defined";
-const char kPropertyRedefinition[] = "property_redefinition";
-
-} // namespace state
-} // namespace errors
-} // namespace buffet
diff --git a/buffet/states/error_codes.h b/buffet/states/error_codes.h
deleted file mode 100644
index 2298741..0000000
--- a/buffet/states/error_codes.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STATES_ERROR_CODES_H_
-#define BUFFET_STATES_ERROR_CODES_H_
-
-namespace buffet {
-namespace errors {
-namespace state {
-
-// Error domain for state definitions.
-extern const char kDomain[];
-
-// State-specific error codes.
-extern const char kPackageNameMissing[];
-extern const char kPropertyNameMissing[];
-extern const char kPropertyNotDefined[];
-extern const char kPropertyRedefinition[];
-
-} // namespace state
-} // namespace errors
-} // namespace buffet
-
-#endif // BUFFET_STATES_ERROR_CODES_H_
diff --git a/buffet/states/mock_state_change_queue_interface.h b/buffet/states/mock_state_change_queue_interface.h
deleted file mode 100644
index 127e01d..0000000
--- a/buffet/states/mock_state_change_queue_interface.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STATES_MOCK_STATE_CHANGE_QUEUE_INTERFACE_H_
-#define BUFFET_STATES_MOCK_STATE_CHANGE_QUEUE_INTERFACE_H_
-
-#include <vector>
-
-#include <gmock/gmock.h>
-
-#include "buffet/states/state_change_queue_interface.h"
-
-namespace buffet {
-
-class MockStateChangeQueueInterface : public StateChangeQueueInterface {
- public:
- MOCK_CONST_METHOD0(IsEmpty, bool());
- MOCK_METHOD2(NotifyPropertiesUpdated,
- bool(base::Time timestamp,
- native_types::Object changed_properties));
- MOCK_METHOD0(GetAndClearRecordedStateChanges, std::vector<StateChange>());
- MOCK_CONST_METHOD0(GetLastStateChangeId, UpdateID());
- MOCK_METHOD1(MockAddOnStateUpdatedCallback,
- base::CallbackList<void(UpdateID)>::Subscription*(
- const base::Callback<void(UpdateID)>&));
- MOCK_METHOD1(NotifyStateUpdatedOnServer, void(UpdateID));
-
- private:
- Token AddOnStateUpdatedCallback(
- const base::Callback<void(UpdateID)>& callback) override {
- return Token{MockAddOnStateUpdatedCallback(callback)};
- }
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STATES_MOCK_STATE_CHANGE_QUEUE_INTERFACE_H_
diff --git a/buffet/states/state_change_queue.cc b/buffet/states/state_change_queue.cc
deleted file mode 100644
index 00ec41a..0000000
--- a/buffet/states/state_change_queue.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/states/state_change_queue.h"
-
-#include <base/logging.h>
-
-namespace buffet {
-
-StateChangeQueue::StateChangeQueue(size_t max_queue_size)
- : max_queue_size_(max_queue_size) {
- CHECK_GT(max_queue_size_, 0U) << "Max queue size must not be zero";
-}
-
-bool StateChangeQueue::NotifyPropertiesUpdated(
- base::Time timestamp,
- native_types::Object changed_properties) {
- DCHECK(thread_checker_.CalledOnValidThread());
- auto it = state_changes_.lower_bound(timestamp);
- if (it == state_changes_.end() || it->first != timestamp) {
- // This timestamp doesn't exist. Insert a new element.
- state_changes_.emplace_hint(it, timestamp, std::move(changed_properties));
- } else {
- // Merge the old property set and the new one.
- // For properties that exist in both old and new property sets, keep the
- // new values.
- changed_properties.insert(it->second.begin(), it->second.end());
- it->second = std::move(changed_properties);
- }
- while (state_changes_.size() > max_queue_size_) {
- // Queue is full.
- // Merge the two oldest records into one. The merge strategy is:
- // - Move non-existent properties from element [old] to [new].
- // - If both [old] and [new] specify the same property,
- // keep the value of [new].
- // - Keep the timestamp of [new].
- auto element_old = state_changes_.begin();
- auto element_new = std::next(element_old);
- // This will skip elements that exist in both [old] and [new].
- element_new->second.insert(element_old->second.begin(),
- element_old->second.end());
- state_changes_.erase(element_old);
- }
- ++last_change_id_;
- return true;
-}
-
-std::vector<StateChange> StateChangeQueue::GetAndClearRecordedStateChanges() {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::vector<StateChange> changes;
- changes.reserve(state_changes_.size());
- for (const auto& pair : state_changes_) {
- changes.emplace_back(pair.first, std::move(pair.second));
- }
- state_changes_.clear();
- return changes;
-}
-
-StateChangeQueueInterface::Token StateChangeQueue::AddOnStateUpdatedCallback(
- const base::Callback<void(UpdateID)>& callback) {
- if (state_changes_.empty())
- callback.Run(last_change_id_);
- return Token{callbacks_.Add(callback).release()};
-}
-
-void StateChangeQueue::NotifyStateUpdatedOnServer(UpdateID update_id) {
- callbacks_.Notify(update_id);
-}
-
-} // namespace buffet
diff --git a/buffet/states/state_change_queue.h b/buffet/states/state_change_queue.h
deleted file mode 100644
index 26ea9cd..0000000
--- a/buffet/states/state_change_queue.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STATES_STATE_CHANGE_QUEUE_H_
-#define BUFFET_STATES_STATE_CHANGE_QUEUE_H_
-
-#include <map>
-#include <vector>
-
-#include <base/macros.h>
-#include <base/threading/thread_checker.h>
-
-#include "buffet/states/state_change_queue_interface.h"
-
-namespace buffet {
-
-// An object to record and retrieve device state change notification events.
-class StateChangeQueue : public StateChangeQueueInterface {
- public:
- explicit StateChangeQueue(size_t max_queue_size);
-
- // Overrides from StateChangeQueueInterface.
- bool IsEmpty() const override { return state_changes_.empty(); }
- bool NotifyPropertiesUpdated(
- base::Time timestamp,
- native_types::Object changed_properties) override;
- std::vector<StateChange> GetAndClearRecordedStateChanges() override;
- UpdateID GetLastStateChangeId() const override { return last_change_id_; }
- Token AddOnStateUpdatedCallback(
- const base::Callback<void(UpdateID)>& callback) override;
- void NotifyStateUpdatedOnServer(UpdateID update_id) override;
-
- private:
- // To make sure we do not call NotifyPropertiesUpdated() and
- // GetAndClearRecordedStateChanges() on different threads, |thread_checker_|
- // is here to help us with verifying the single-threaded operation.
- base::ThreadChecker thread_checker_;
-
- // Maximum queue size. If it is full, the oldest state update records are
- // merged together until the queue size is within the size limit.
- const size_t max_queue_size_;
-
- // Accumulated list of device state change notifications.
- std::map<base::Time, native_types::Object> state_changes_;
-
- // An ID of last state change update. Each NotifyPropertiesUpdated()
- // invocation increments this value by 1.
- UpdateID last_change_id_{0};
-
- // Callback list for state change queue even sinks.
- base::CallbackList<void(UpdateID)> callbacks_;
-
- DISALLOW_COPY_AND_ASSIGN(StateChangeQueue);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STATES_STATE_CHANGE_QUEUE_H_
diff --git a/buffet/states/state_change_queue_interface.h b/buffet/states/state_change_queue_interface.h
deleted file mode 100644
index 2f11e6b..0000000
--- a/buffet/states/state_change_queue_interface.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STATES_STATE_CHANGE_QUEUE_INTERFACE_H_
-#define BUFFET_STATES_STATE_CHANGE_QUEUE_INTERFACE_H_
-
-#include <vector>
-
-#include <base/callback_list.h>
-#include <base/time/time.h>
-#include <chromeos/variant_dictionary.h>
-
-#include "buffet/commands/schema_utils.h"
-
-namespace buffet {
-
-// A simple notification record event to track device state changes.
-// The |timestamp| records the time of the state change.
-// |changed_properties| contains a property set with the new property values
-// which were updated at the time the event was recorded.
-struct StateChange {
- StateChange(base::Time time, native_types::Object properties)
- : timestamp{time}, changed_properties{std::move(properties)} {}
- base::Time timestamp;
- native_types::Object changed_properties;
-};
-
-// An abstract interface to StateChangeQueue to record and retrieve state
-// change notification events.
-class StateChangeQueueInterface {
- public:
- using UpdateID = uint64_t;
- using Token =
- std::unique_ptr<base::CallbackList<void(UpdateID)>::Subscription>;
-
- // Returns true if the state change notification queue is empty.
- virtual bool IsEmpty() const = 0;
-
- // Called by StateManager when device state properties are updated.
- virtual bool NotifyPropertiesUpdated(
- base::Time timestamp,
- native_types::Object changed_properties) = 0;
-
- // Returns the recorded state changes since last time this method was called.
- virtual std::vector<StateChange> GetAndClearRecordedStateChanges() = 0;
-
- // Returns an ID of last state change update. Each NotifyPropertiesUpdated()
- // invocation increments this value by 1.
- virtual UpdateID GetLastStateChangeId() const = 0;
-
- // Subscribes for device state update notifications from cloud server.
- // The |callback| will be called every time a state patch with given ID is
- // successfully received and processed by GCD server.
- // Returns a subscription token. As soon as this token is destroyed, the
- // respective callback is removed from the callback list.
- virtual Token AddOnStateUpdatedCallback(
- const base::Callback<void(UpdateID)>& callback) WARN_UNUSED_RESULT = 0;
-
- virtual void NotifyStateUpdatedOnServer(UpdateID update_id) = 0;
-
- protected:
- // No one should attempt do destroy the queue through the interface.
- virtual ~StateChangeQueueInterface() {}
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STATES_STATE_CHANGE_QUEUE_INTERFACE_H_
diff --git a/buffet/states/state_change_queue_unittest.cc b/buffet/states/state_change_queue_unittest.cc
deleted file mode 100644
index 091e5c3..0000000
--- a/buffet/states/state_change_queue_unittest.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#include "buffet/states/state_change_queue.h"
-
-#include <chromeos/bind_lambda.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/unittest_utils.h"
-
-namespace buffet {
-
-class StateChangeQueueTest : public ::testing::Test {
- public:
- void SetUp() override {
- queue_.reset(new StateChangeQueue(100));
- }
-
- void TearDown() override {
- queue_.reset();
- }
-
- std::unique_ptr<StateChangeQueue> queue_;
-};
-
-TEST_F(StateChangeQueueTest, Empty) {
- EXPECT_TRUE(queue_->IsEmpty());
- EXPECT_EQ(0, queue_->GetLastStateChangeId());
- EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
-}
-
-TEST_F(StateChangeQueueTest, UpdateOne) {
- StateChange change{
- base::Time::Now(),
- native_types::Object{{"prop.name", unittests::make_int_prop_value(23)}}
- };
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(change.timestamp,
- change.changed_properties));
- EXPECT_FALSE(queue_->IsEmpty());
- EXPECT_EQ(1, queue_->GetLastStateChangeId());
- auto changes = queue_->GetAndClearRecordedStateChanges();
- EXPECT_EQ(1, queue_->GetLastStateChangeId());
- ASSERT_EQ(1, changes.size());
- EXPECT_EQ(change.timestamp, changes.front().timestamp);
- EXPECT_EQ(change.changed_properties, changes.front().changed_properties);
- EXPECT_TRUE(queue_->IsEmpty());
- EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
-}
-
-TEST_F(StateChangeQueueTest, UpdateMany) {
- StateChange change1{
- base::Time::Now(),
- native_types::Object{{"prop.name1", unittests::make_int_prop_value(23)}}
- };
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(change1.timestamp,
- change1.changed_properties));
- StateChange change2{
- base::Time::Now(),
- native_types::Object{
- {"prop.name1", unittests::make_int_prop_value(17)},
- {"prop.name2", unittests::make_double_prop_value(1.0)},
- {"prop.name3", unittests::make_bool_prop_value(false)},
- }
- };
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(change2.timestamp,
- change2.changed_properties));
- EXPECT_EQ(2, queue_->GetLastStateChangeId());
- EXPECT_FALSE(queue_->IsEmpty());
- auto changes = queue_->GetAndClearRecordedStateChanges();
- ASSERT_EQ(2, changes.size());
- EXPECT_EQ(change1.timestamp, changes[0].timestamp);
- EXPECT_EQ(change1.changed_properties, changes[0].changed_properties);
- EXPECT_EQ(change2.timestamp, changes[1].timestamp);
- EXPECT_EQ(change2.changed_properties, changes[1].changed_properties);
- EXPECT_TRUE(queue_->IsEmpty());
- EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
-}
-
-TEST_F(StateChangeQueueTest, GroupByTimestamp) {
- base::Time timestamp = base::Time::Now();
- base::TimeDelta time_delta = base::TimeDelta::FromMinutes(1);
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- timestamp,
- native_types::Object{{"prop.name1", unittests::make_int_prop_value(1)}}));
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- timestamp,
- native_types::Object{{"prop.name2", unittests::make_int_prop_value(2)}}));
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- timestamp,
- native_types::Object{{"prop.name1", unittests::make_int_prop_value(3)}}));
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- timestamp + time_delta,
- native_types::Object{{"prop.name1", unittests::make_int_prop_value(4)}}));
-
- auto changes = queue_->GetAndClearRecordedStateChanges();
- EXPECT_EQ(4, queue_->GetLastStateChangeId());
- ASSERT_EQ(2, changes.size());
-
- native_types::Object expected1{
- {"prop.name1", unittests::make_int_prop_value(3)},
- {"prop.name2", unittests::make_int_prop_value(2)},
- };
- native_types::Object expected2{
- {"prop.name1", unittests::make_int_prop_value(4)},
- };
- EXPECT_EQ(timestamp, changes[0].timestamp);
- EXPECT_EQ(expected1, changes[0].changed_properties);
- EXPECT_EQ(timestamp + time_delta, changes[1].timestamp);
- EXPECT_EQ(expected2, changes[1].changed_properties);
-}
-
-TEST_F(StateChangeQueueTest, MaxQueueSize) {
- queue_.reset(new StateChangeQueue(2));
- base::Time start_time = base::Time::Now();
- base::TimeDelta time_delta1 = base::TimeDelta::FromMinutes(1);
- base::TimeDelta time_delta2 = base::TimeDelta::FromMinutes(3);
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- start_time,
- native_types::Object{
- {"prop.name1", unittests::make_int_prop_value(1)},
- {"prop.name2", unittests::make_int_prop_value(2)},
- }));
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- start_time + time_delta1,
- native_types::Object{
- {"prop.name1", unittests::make_int_prop_value(3)},
- {"prop.name3", unittests::make_int_prop_value(4)},
- }));
-
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- start_time + time_delta2,
- native_types::Object{
- {"prop.name10", unittests::make_int_prop_value(10)},
- {"prop.name11", unittests::make_int_prop_value(11)},
- }));
-
- EXPECT_EQ(3, queue_->GetLastStateChangeId());
- auto changes = queue_->GetAndClearRecordedStateChanges();
- ASSERT_EQ(2, changes.size());
-
- native_types::Object expected1{
- {"prop.name1", unittests::make_int_prop_value(3)},
- {"prop.name2", unittests::make_int_prop_value(2)},
- {"prop.name3", unittests::make_int_prop_value(4)},
- };
- EXPECT_EQ(start_time + time_delta1, changes[0].timestamp);
- EXPECT_EQ(expected1, changes[0].changed_properties);
-
- native_types::Object expected2{
- {"prop.name10", unittests::make_int_prop_value(10)},
- {"prop.name11", unittests::make_int_prop_value(11)},
- };
- EXPECT_EQ(start_time + time_delta2, changes[1].timestamp);
- EXPECT_EQ(expected2, changes[1].changed_properties);
-}
-
-TEST_F(StateChangeQueueTest, ImmediateStateChangeNotification) {
- // When queue is empty, registering a new callback will trigger it.
- bool called = false;
- auto callback = [&called](StateChangeQueueInterface::UpdateID id) {
- called = true;
- };
- queue_->AddOnStateUpdatedCallback(base::Bind(callback));
- EXPECT_TRUE(called);
-}
-
-TEST_F(StateChangeQueueTest, DelayedStateChangeNotification) {
- // When queue is not empty, registering a new callback will not trigger it.
- ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
- base::Time::Now(),
- native_types::Object{
- {"prop.name1", unittests::make_int_prop_value(1)},
- {"prop.name2", unittests::make_int_prop_value(2)},
- }));
-
- auto callback = [](StateChangeQueueInterface::UpdateID id) {
- FAIL() << "This should not be called";
- };
- queue_->AddOnStateUpdatedCallback(base::Bind(callback));
-}
-
-} // namespace buffet
diff --git a/buffet/states/state_manager.cc b/buffet/states/state_manager.cc
deleted file mode 100644
index 2ce78c1..0000000
--- a/buffet/states/state_manager.cc
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/states/state_manager.h"
-
-#include <base/files/file_enumerator.h>
-#include <base/files/file_path.h>
-#include <base/logging.h>
-#include <base/values.h>
-#include <chromeos/errors/error_codes.h>
-#include <chromeos/key_value_store.h>
-#include <chromeos/strings/string_utils.h>
-
-#include "buffet/states/error_codes.h"
-#include "buffet/states/state_change_queue_interface.h"
-#include "buffet/utils.h"
-
-namespace buffet {
-
-namespace {
-
-const char kBaseStateFirmwareVersion[] = "base.firmwareVersion";
-
-} // namespace
-
-
-StateManager::StateManager(StateChangeQueueInterface* state_change_queue)
- : state_change_queue_(state_change_queue) {
- CHECK(state_change_queue_) << "State change queue not specified";
-}
-
-void StateManager::AddOnChangedCallback(const base::Closure& callback) {
- on_changed_.push_back(callback);
- callback.Run(); // Force to read current state.
-}
-
-void StateManager::Startup() {
- LOG(INFO) << "Initializing StateManager.";
-
- // Load standard device state definition.
- base::FilePath base_state_file("/etc/buffet/base_state.schema.json");
- LOG(INFO) << "Loading standard state definition from "
- << base_state_file.value();
- CHECK(LoadBaseStateDefinition(base_state_file, nullptr))
- << "Failed to load the standard state definition file.";
-
- // Load component-specific device state definitions.
- base::FilePath device_state_dir("/etc/buffet/states");
- base::FileEnumerator enumerator(device_state_dir, false,
- base::FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.schema.json"));
- base::FilePath json_file_path = enumerator.Next();
- while (!json_file_path.empty()) {
- LOG(INFO) << "Loading state definition from " << json_file_path.value();
- CHECK(LoadStateDefinition(json_file_path, nullptr))
- << "Failed to load the state definition file.";
- json_file_path = enumerator.Next();
- }
-
- // Load standard device state defaults.
- base::FilePath base_state_defaults("/etc/buffet/base_state.defaults.json");
- LOG(INFO) << "Loading base state defaults from "
- << base_state_defaults.value();
- CHECK(LoadStateDefaults(base_state_defaults, nullptr))
- << "Failed to load the base state defaults.";
-
- // Load component-specific device state defaults.
- base::FileEnumerator enumerator2(device_state_dir, false,
- base::FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.defaults.json"));
- json_file_path = enumerator2.Next();
- while (!json_file_path.empty()) {
- LOG(INFO) << "Loading state defaults from " << json_file_path.value();
- CHECK(LoadStateDefaults(json_file_path, nullptr))
- << "Failed to load the state defaults.";
- json_file_path = enumerator2.Next();
- }
-
- // Populate state fields that belong to the system.
- base::FilePath lsb_release_path("/etc/lsb-release");
- chromeos::KeyValueStore lsb_release_store;
- std::string firmware_version;
- if (lsb_release_store.Load(lsb_release_path)) {
- if (!lsb_release_store.GetString("CHROMEOS_RELEASE_VERSION",
- &firmware_version))
- LOG(ERROR) << "Missing key for firmware version in version file.";
-
- } else {
- LOG(ERROR) << "Failed to read file for firmwareVersion.";
- }
- CHECK(SetPropertyValue(kBaseStateFirmwareVersion,
- firmware_version,
- base::Time::Now(),
- nullptr));
-
- for (const auto& cb : on_changed_)
- cb.Run();
-}
-
-std::unique_ptr<base::DictionaryValue> StateManager::GetStateValuesAsJson(
- chromeos::ErrorPtr* error) const {
- std::unique_ptr<base::DictionaryValue> dict{new base::DictionaryValue};
- for (const auto& pair : packages_) {
- auto pkg_value = pair.second->GetValuesAsJson(error);
- if (!pkg_value) {
- dict.reset();
- break;
- }
- dict->SetWithoutPathExpansion(pair.first, pkg_value.release());
- }
- return dict;
-}
-
-bool StateManager::SetProperties(
- const chromeos::VariantDictionary& property_set,
- chromeos::ErrorPtr* error) {
- base::Time timestamp = base::Time::Now();
- bool all_success = true;
- for (const auto& pair : property_set) {
- if (!SetPropertyValue(pair.first, pair.second, timestamp, error)) {
- // Remember that an error occurred but keep going and update the rest of
- // the properties if possible.
- all_success = false;
- }
- }
- for (const auto& cb : on_changed_)
- cb.Run();
- return all_success;
-}
-
-bool StateManager::SetPropertyValue(const std::string& full_property_name,
- const chromeos::Any& value,
- const base::Time& timestamp,
- chromeos::ErrorPtr* error) {
- std::string package_name;
- std::string property_name;
- bool split = chromeos::string_utils::SplitAtFirst(
- full_property_name, ".", &package_name, &property_name);
- if (full_property_name.empty() || (split && property_name.empty())) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPropertyNameMissing,
- "Property name is missing");
- return false;
- }
- if (!split || package_name.empty()) {
- chromeos::Error::AddTo(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPackageNameMissing,
- "Package name is missing in the property name");
- return false;
- }
- StatePackage* package = FindPackage(package_name);
- if (package == nullptr) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPropertyNotDefined,
- "Unknown state property package '%s'",
- package_name.c_str());
- return false;
- }
- if (!package->SetPropertyValue(property_name, value, error))
- return false;
-
- native_types::Object prop_set{{full_property_name,
- package->GetProperty(property_name)}};
- state_change_queue_->NotifyPropertiesUpdated(timestamp, prop_set);
- return true;
-}
-
-std::pair<StateChangeQueueInterface::UpdateID, std::vector<StateChange>>
-StateManager::GetAndClearRecordedStateChanges() {
- return std::make_pair(state_change_queue_->GetLastStateChangeId(),
- state_change_queue_->GetAndClearRecordedStateChanges());
-}
-
-void StateManager::NotifyStateUpdatedOnServer(
- StateChangeQueueInterface::UpdateID id) {
- state_change_queue_->NotifyStateUpdatedOnServer(id);
-}
-
-bool StateManager::LoadStateDefinition(const base::DictionaryValue& json,
- const std::string& category,
- chromeos::ErrorPtr* error) {
- base::DictionaryValue::Iterator iter(json);
- while (!iter.IsAtEnd()) {
- std::string package_name = iter.key();
- if (package_name.empty()) {
- chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainBuffet,
- kInvalidPackageError,
- "State package name is empty");
- return false;
- }
- const base::DictionaryValue* package_dict = nullptr;
- if (!iter.value().GetAsDictionary(&package_dict)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- chromeos::errors::json::kDomain,
- chromeos::errors::json::kObjectExpected,
- "State package '%s' must be an object",
- package_name.c_str());
- return false;
- }
- StatePackage* package = FindOrCreatePackage(package_name);
- CHECK(package) << "Unable to create state package " << package_name;
- if (!package->AddSchemaFromJson(package_dict, error))
- return false;
- iter.Advance();
- }
- if (category != kDefaultCategory)
- categories_.insert(category);
-
- return true;
-}
-
-bool StateManager::LoadStateDefinition(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const base::DictionaryValue> json =
- LoadJsonDict(json_file_path, error);
- if (!json)
- return false;
- std::string category = json_file_path.BaseName().RemoveExtension().value();
- if (category == kDefaultCategory) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomainBuffet,
- kInvalidCategoryError,
- "Invalid state category specified in '%s'",
- json_file_path.value().c_str());
- return false;
- }
-
- if (!LoadStateDefinition(*json, category, error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomainBuffet,
- kFileReadError,
- "Failed to load file '%s'",
- json_file_path.value().c_str());
- return false;
- }
- return true;
-}
-
-bool StateManager::LoadBaseStateDefinition(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const base::DictionaryValue> json =
- LoadJsonDict(json_file_path, error);
- if (!json)
- return false;
- if (!LoadStateDefinition(*json, kDefaultCategory, error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomainBuffet,
- kFileReadError,
- "Failed to load file '%s'",
- json_file_path.value().c_str());
- return false;
- }
- return true;
-}
-
-bool StateManager::LoadStateDefaults(const base::DictionaryValue& json,
- chromeos::ErrorPtr* error) {
- base::DictionaryValue::Iterator iter(json);
- while (!iter.IsAtEnd()) {
- std::string package_name = iter.key();
- if (package_name.empty()) {
- chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainBuffet,
- kInvalidPackageError,
- "State package name is empty");
- return false;
- }
- const base::DictionaryValue* package_dict = nullptr;
- if (!iter.value().GetAsDictionary(&package_dict)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- chromeos::errors::json::kDomain,
- chromeos::errors::json::kObjectExpected,
- "State package '%s' must be an object",
- package_name.c_str());
- return false;
- }
- StatePackage* package = FindPackage(package_name);
- if (package == nullptr) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, chromeos::errors::json::kDomain,
- chromeos::errors::json::kObjectExpected,
- "Providing values for undefined state package '%s'",
- package_name.c_str());
- return false;
- }
- if (!package->AddValuesFromJson(package_dict, error))
- return false;
- iter.Advance();
- }
- return true;
-}
-
-bool StateManager::LoadStateDefaults(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const base::DictionaryValue> json =
- LoadJsonDict(json_file_path, error);
- if (!json)
- return false;
- if (!LoadStateDefaults(*json, error)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomainBuffet,
- kFileReadError,
- "Failed to load file '%s'",
- json_file_path.value().c_str());
- return false;
- }
- return true;
-}
-
-StatePackage* StateManager::FindPackage(const std::string& package_name) {
- auto it = packages_.find(package_name);
- return (it != packages_.end()) ? it->second.get() : nullptr;
-}
-
-StatePackage* StateManager::FindOrCreatePackage(
- const std::string& package_name) {
- StatePackage* package = FindPackage(package_name);
- if (package == nullptr) {
- std::unique_ptr<StatePackage> new_package{new StatePackage(package_name)};
- package = packages_.emplace(package_name,
- std::move(new_package)).first->second.get();
- }
- return package;
-}
-
-} // namespace buffet
diff --git a/buffet/states/state_manager.h b/buffet/states/state_manager.h
deleted file mode 100644
index 914daeb..0000000
--- a/buffet/states/state_manager.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STATES_STATE_MANAGER_H_
-#define BUFFET_STATES_STATE_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/macros.h>
-#include <chromeos/errors/error.h>
-#include <chromeos/variant_dictionary.h>
-
-#include "buffet/states/state_change_queue_interface.h"
-#include "buffet/states/state_package.h"
-
-namespace base {
-class DictionaryValue;
-class FilePath;
-class Time;
-} // namespace base
-
-namespace buffet {
-
-// StateManager is the class that aggregates the device state fragments
-// provided by device daemons and makes the aggregate device state available
-// to the GCD cloud server and local clients.
-class StateManager final {
- public:
- explicit StateManager(StateChangeQueueInterface* state_change_queue);
-
- void AddOnChangedCallback(const base::Closure& callback);
-
- // Initializes the state manager and load device state fragments.
- // Called by Buffet daemon at startup.
- void Startup();
-
- // Returns aggregated state properties across all registered packages as
- // a JSON object that can be used to send the device state to the GCD server.
- std::unique_ptr<base::DictionaryValue> GetStateValuesAsJson(
- chromeos::ErrorPtr* error) const;
-
- // Updates a multiple property values.
- bool SetProperties(const chromeos::VariantDictionary& property_set,
- chromeos::ErrorPtr* error);
-
- // Returns all the categories the state properties are registered from.
- // As with GCD command handling, the category normally represent a device
- // service (daemon) that is responsible for a set of properties.
- const std::set<std::string>& GetCategories() const {
- return categories_;
- }
-
- // Returns the recorded state changes since last time this method has been
- // called.
- std::pair<StateChangeQueueInterface::UpdateID, std::vector<StateChange>>
- GetAndClearRecordedStateChanges();
-
- // Called to notify that the state patch with |id| has been successfully sent
- // to the server and processed.
- void NotifyStateUpdatedOnServer(StateChangeQueueInterface::UpdateID id);
-
- StateChangeQueueInterface* GetStateChangeQueue() const {
- return state_change_queue_;
- }
-
- private:
- friend class BaseApiHandlerTest;
- friend class StateManagerTest;
-
- // Updates a single property value. |full_property_name| must be the full
- // name of the property to update in format "package.property".
- bool SetPropertyValue(const std::string& full_property_name,
- const chromeos::Any& value,
- const base::Time& timestamp,
- chromeos::ErrorPtr* error);
-
- // Loads a device state fragment from a JSON object. |category| represents
- // a device daemon providing the state fragment or empty string for the
- // base state fragment.
- bool LoadStateDefinition(const base::DictionaryValue& json,
- const std::string& category,
- chromeos::ErrorPtr* error);
-
- // Loads a device state fragment JSON file. The file name (without extension)
- // is used as the state fragment category.
- bool LoadStateDefinition(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error);
-
- // Loads the base device state fragment JSON file. This state fragment
- // defines the standard state properties from the 'base' package as defined
- // by GCD specification.
- bool LoadBaseStateDefinition(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error);
-
- // Loads state default values from JSON object.
- bool LoadStateDefaults(const base::DictionaryValue& json,
- chromeos::ErrorPtr* error);
-
- // Loads state default values from JSON file.
- bool LoadStateDefaults(const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error);
-
- // Finds a package by its name. Returns nullptr if not found.
- StatePackage* FindPackage(const std::string& package_name);
- // Finds a package by its name. If none exists, one will be created.
- StatePackage* FindOrCreatePackage(const std::string& package_name);
-
- StateChangeQueueInterface* state_change_queue_; // Owned by buffet::Manager.
- std::map<std::string, std::unique_ptr<StatePackage>> packages_;
- std::set<std::string> categories_;
-
- std::vector<base::Closure> on_changed_;
-
- DISALLOW_COPY_AND_ASSIGN(StateManager);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STATES_STATE_MANAGER_H_
diff --git a/buffet/states/state_manager_unittest.cc b/buffet/states/state_manager_unittest.cc
deleted file mode 100644
index 4437a18..0000000
--- a/buffet/states/state_manager_unittest.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/states/state_manager.h"
-
-#include <cstdlib> // for abs().
-#include <vector>
-
-#include <base/bind.h>
-#include <base/values.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/schema_constants.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/states/error_codes.h"
-#include "buffet/states/mock_state_change_queue_interface.h"
-
-namespace buffet {
-
-using testing::_;
-using testing::Return;
-using unittests::CreateDictionaryValue;
-
-namespace {
-std::unique_ptr<base::DictionaryValue> GetTestSchema() {
- return CreateDictionaryValue(R"({
- 'base': {
- 'manufacturer':'string',
- 'serialNumber':'string'
- },
- 'terminator': {
- 'target':'string'
- }
- })");
-}
-
-std::unique_ptr<base::DictionaryValue> GetTestValues() {
- return CreateDictionaryValue(R"({
- 'base': {
- 'manufacturer':'Skynet',
- 'serialNumber':'T1000'
- }
- })");
-}
-
-} // anonymous namespace
-
-class StateManagerTest : public ::testing::Test {
- public:
- void SetUp() override {
- // Initial expectations.
- EXPECT_CALL(mock_state_change_queue_, IsEmpty()).Times(0);
- EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(_, _))
- .Times(0);
- EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
- .Times(0);
- mgr_.reset(new StateManager(&mock_state_change_queue_));
-
- EXPECT_CALL(*this, OnStateChanged()).Times(1);
- mgr_->AddOnChangedCallback(
- base::Bind(&StateManagerTest::OnStateChanged, base::Unretained(this)));
-
- LoadStateDefinition(GetTestSchema().get(), "default", nullptr);
- ASSERT_TRUE(mgr_->LoadStateDefaults(*GetTestValues().get(), nullptr));
- }
- void TearDown() override { mgr_.reset(); }
-
- void LoadStateDefinition(const base::DictionaryValue* json,
- const std::string& category,
- chromeos::ErrorPtr* error) {
- ASSERT_TRUE(mgr_->LoadStateDefinition(*json, category, error));
- }
-
- bool SetPropertyValue(const std::string& name,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error) {
- return mgr_->SetPropertyValue(name, value, timestamp_, error);
- }
-
- MOCK_CONST_METHOD0(OnStateChanged, void());
-
- base::Time timestamp_{base::Time::Now()};
- std::unique_ptr<StateManager> mgr_;
- MockStateChangeQueueInterface mock_state_change_queue_;
-};
-
-TEST(StateManager, Empty) {
- MockStateChangeQueueInterface mock_state_change_queue;
- StateManager manager(&mock_state_change_queue);
- EXPECT_TRUE(manager.GetCategories().empty());
-}
-
-TEST_F(StateManagerTest, Initialized) {
- EXPECT_EQ(std::set<std::string>{"default"}, mgr_->GetCategories());
- auto expected = R"({
- 'base': {
- 'manufacturer': 'Skynet',
- 'serialNumber': 'T1000'
- },
- 'terminator': {
- 'target': ''
- }
- })";
- EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
-}
-
-TEST_F(StateManagerTest, LoadStateDefinition) {
- auto dict = CreateDictionaryValue(R"({
- 'power': {
- 'battery_level':'integer'
- }
- })");
- LoadStateDefinition(dict.get(), "powerd", nullptr);
- EXPECT_EQ((std::set<std::string>{"default", "powerd"}),
- mgr_->GetCategories());
-
- auto expected = R"({
- 'base': {
- 'manufacturer': 'Skynet',
- 'serialNumber': 'T1000'
- },
- 'power': {
- 'battery_level': 0
- },
- 'terminator': {
- 'target': ''
- }
- })";
- EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
-}
-
-TEST_F(StateManagerTest, SetPropertyValue) {
- native_types::Object expected_prop_set{
- {"terminator.target", unittests::make_string_prop_value("John Connor")},
- };
- EXPECT_CALL(mock_state_change_queue_,
- NotifyPropertiesUpdated(timestamp_, expected_prop_set))
- .WillOnce(Return(true));
- ASSERT_TRUE(SetPropertyValue("terminator.target", std::string{"John Connor"},
- nullptr));
- auto expected = R"({
- 'base': {
- 'manufacturer': 'Skynet',
- 'serialNumber': 'T1000'
- },
- 'terminator': {
- 'target': 'John Connor'
- }
- })";
- EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_NoName) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(SetPropertyValue("", int{0}, &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyNameMissing, error->GetCode());
- EXPECT_EQ("Property name is missing", error->GetMessage());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_NoPackage) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(SetPropertyValue("target", int{0}, &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPackageNameMissing, error->GetCode());
- EXPECT_EQ("Package name is missing in the property name",
- error->GetMessage());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownPackage) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(SetPropertyValue("power.level", int{0}, &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
- EXPECT_EQ("Unknown state property package 'power'", error->GetMessage());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownProperty) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(SetPropertyValue("base.level", int{0}, &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
- EXPECT_EQ("State property 'base.level' is not defined", error->GetMessage());
-}
-
-TEST_F(StateManagerTest, GetAndClearRecordedStateChanges) {
- EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(timestamp_, _))
- .WillOnce(Return(true));
- ASSERT_TRUE(SetPropertyValue("terminator.target", std::string{"John Connor"},
- nullptr));
- std::vector<StateChange> expected_val;
- expected_val.emplace_back(
- timestamp_,
- native_types::Object{{"terminator.target",
- unittests::make_string_prop_value("John Connor")}});
- EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
- .WillOnce(Return(expected_val));
- auto changes = mgr_->GetAndClearRecordedStateChanges();
- ASSERT_EQ(1, changes.second.size());
- EXPECT_EQ(expected_val.back().timestamp, changes.second.back().timestamp);
- EXPECT_EQ(expected_val.back().changed_properties,
- changes.second.back().changed_properties);
-}
-
-TEST_F(StateManagerTest, SetProperties) {
- native_types::Object expected_prop_set{
- {"base.manufacturer", unittests::make_string_prop_value("No Name")},
- };
- EXPECT_CALL(mock_state_change_queue_,
- NotifyPropertiesUpdated(_, expected_prop_set))
- .WillOnce(Return(true));
-
- EXPECT_CALL(*this, OnStateChanged()).Times(1);
- ASSERT_TRUE(mgr_->SetProperties(
- {{"base.manufacturer", std::string("No Name")}}, nullptr));
-
- auto expected = R"({
- 'base': {
- 'manufacturer': 'No Name',
- 'serialNumber': 'T1000'
- },
- 'terminator': {
- 'target': ''
- }
- })";
- EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
-}
-
-} // namespace buffet
diff --git a/buffet/states/state_package.cc b/buffet/states/state_package.cc
deleted file mode 100644
index 1292339..0000000
--- a/buffet/states/state_package.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/states/state_package.h"
-
-#include <base/logging.h>
-#include <base/values.h>
-#include <chromeos/dbus/data_serialization.h>
-
-#include "buffet/commands/prop_types.h"
-#include "buffet/commands/prop_values.h"
-#include "buffet/commands/schema_utils.h"
-#include "buffet/states/error_codes.h"
-
-namespace buffet {
-
-StatePackage::StatePackage(const std::string& name) : name_(name) {
-}
-
-bool StatePackage::AddSchemaFromJson(const base::DictionaryValue* json,
- chromeos::ErrorPtr* error) {
- ObjectSchema schema;
- if (!schema.FromJson(json, nullptr, error))
- return false;
-
- // Scan first to make sure we have no property redefinitions.
- for (const auto& pair : schema.GetProps()) {
- if (types_.GetProp(pair.first)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPropertyRedefinition,
- "State property '%s.%s' is already defined",
- name_.c_str(), pair.first.c_str());
- return false;
- }
- }
-
- // Now move all the properties to |types_| object.
- for (const auto& pair : schema.GetProps()) {
- types_.AddProp(pair.first, pair.second->Clone());
- // Create default value for this state property.
- values_.emplace(pair.first, pair.second->CreateValue());
- }
-
- return true;
-}
-
-bool StatePackage::AddValuesFromJson(const base::DictionaryValue* json,
- chromeos::ErrorPtr* error) {
- base::DictionaryValue::Iterator iter(*json);
- while (!iter.IsAtEnd()) {
- std::string property_name = iter.key();
- auto it = values_.find(property_name);
- if (it == values_.end()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPropertyNotDefined,
- "State property '%s.%s' is not defined",
- name_.c_str(), property_name.c_str());
- return false;
- }
- auto new_value = it->second->GetPropType()->CreateValue();
- if (!new_value->FromJson(&iter.value(), error))
- return false;
- it->second = std::move(new_value);
- iter.Advance();
- }
- return true;
-}
-
-std::unique_ptr<base::DictionaryValue> StatePackage::GetValuesAsJson(
- chromeos::ErrorPtr* error) const {
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- for (const auto& pair : values_) {
- auto value = pair.second->ToJson(error);
- if (!value) {
- dict.reset();
- break;
- }
- dict->SetWithoutPathExpansion(pair.first, value.release());
- }
- return dict;
-}
-
-chromeos::Any StatePackage::GetPropertyValue(const std::string& property_name,
- chromeos::ErrorPtr* error) const {
- auto it = values_.find(property_name);
- if (it == values_.end()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPropertyNotDefined,
- "State property '%s.%s' is not defined",
- name_.c_str(), property_name.c_str());
- return chromeos::Any();
- }
- return PropValueToDBusVariant(it->second.get());
-}
-
-bool StatePackage::SetPropertyValue(const std::string& property_name,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error) {
- auto it = values_.find(property_name);
- if (it == values_.end()) {
- chromeos::Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
- errors::state::kPropertyNotDefined,
- "State property '%s.%s' is not defined",
- name_.c_str(), property_name.c_str());
- return false;
- }
- auto new_value = PropValueFromDBusVariant(it->second->GetPropType(),
- value, error);
- if (!new_value)
- return false;
- it->second = std::move(new_value);
- return true;
-}
-
-} // namespace buffet
diff --git a/buffet/states/state_package.h b/buffet/states/state_package.h
deleted file mode 100644
index 1430b5c..0000000
--- a/buffet/states/state_package.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STATES_STATE_PACKAGE_H_
-#define BUFFET_STATES_STATE_PACKAGE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <base/macros.h>
-#include <chromeos/any.h>
-#include <chromeos/errors/error.h>
-
-#include "buffet/commands/object_schema.h"
-#include "buffet/commands/prop_values.h"
-
-namespace base {
-class DictionaryValue;
-} // namespace base
-
-namespace buffet {
-
-// A package is a set of related state properties. GCD specification defines
-// a number of standard state properties in "base" package such as
-// "base.manufacturer", "base.model", "base.firmwareVersion" and so on.
-class StatePackage final {
- public:
- explicit StatePackage(const std::string& name);
-
- // Loads state property definitions from a JSON object and adds them
- // to the current package.
- bool AddSchemaFromJson(const base::DictionaryValue* json,
- chromeos::ErrorPtr* error);
- // Loads a set of state property values from a JSON object and assigns them
- // to existing properties. A property must be defined prior to loading its
- // value. We use this when we load default values during buffet startup.
- bool AddValuesFromJson(const base::DictionaryValue* json,
- chromeos::ErrorPtr* error);
-
- // Returns a set of state properties and their values as a JSON object.
- // After being aggregated across multiple packages, this becomes the device
- // state object passed to the GCD server or a local client in the format
- // described by GCD specification, e.g.:
- // {
- // "base": {
- // "manufacturer":"...",
- // "model":"..."
- // },
- // "printer": {
- // "message": "Printer low on cyan ink"
- // }
- // }
- std::unique_ptr<base::DictionaryValue> GetValuesAsJson(
- chromeos::ErrorPtr* error) const;
-
- // Gets the value for a specific state property. |property_name| must not
- // include the package name as part of the property name.
- chromeos::Any GetPropertyValue(const std::string& property_name,
- chromeos::ErrorPtr* error) const;
- // Sets the value for a specific state property. |property_name| must not
- // include the package name as part of the property name.
- bool SetPropertyValue(const std::string& property_name,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error);
-
- std::shared_ptr<const PropValue>
- GetProperty(const std::string& property_name) const {
- auto it = values_.find(property_name);
- return it != values_.end() ?
- it->second : std::shared_ptr<const PropValue>{};
- }
-
- // Returns the name of the this package.
- const std::string& GetName() const { return name_; }
-
- private:
- std::string name_;
- ObjectSchema types_;
- native_types::Object values_;
-
- friend class StatePackageTestHelper;
- DISALLOW_COPY_AND_ASSIGN(StatePackage);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STATES_STATE_PACKAGE_H_
diff --git a/buffet/states/state_package_unittest.cc b/buffet/states/state_package_unittest.cc
deleted file mode 100644
index 179d206..0000000
--- a/buffet/states/state_package_unittest.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/states/state_package.h"
-
-#include <memory>
-#include <string>
-
-#include <base/values.h>
-#include <chromeos/variant_dictionary.h>
-#include <gtest/gtest.h>
-
-#include "buffet/commands/schema_constants.h"
-#include "buffet/commands/unittest_utils.h"
-#include "buffet/states/error_codes.h"
-
-namespace buffet {
-
-using unittests::CreateDictionaryValue;
-
-class StatePackageTestHelper {
- public:
- // Returns the state property definitions (types/constraints/etc).
- static const ObjectSchema& GetTypes(const StatePackage& package) {
- return package.types_;
- }
- // Returns the all state property values in this package.
- static const native_types::Object& GetValues(const StatePackage& package) {
- return package.values_;
- }
-};
-
-namespace {
-std::unique_ptr<base::DictionaryValue> GetTestSchema() {
- return CreateDictionaryValue(R"({
- 'light': 'boolean',
- 'color': 'string',
- 'direction':{'properties':{'azimuth':'number','altitude':{'maximum':90.0}}},
- 'iso': [50, 100, 200, 400]
- })");
-}
-
-std::unique_ptr<base::DictionaryValue> GetTestValues() {
- return CreateDictionaryValue(R"({
- 'light': true,
- 'color': 'white',
- 'direction': {'azimuth':57.2957795, 'altitude':89.9},
- 'iso': 200
- })");
-}
-
-inline const ObjectSchema& GetTypes(const StatePackage& package) {
- return StatePackageTestHelper::GetTypes(package);
-}
-// Returns the all state property values in this package.
-inline const native_types::Object& GetValues(const StatePackage& package) {
- return StatePackageTestHelper::GetValues(package);
-}
-
-} // anonymous namespace
-
-class StatePackageTest : public ::testing::Test {
- public:
- void SetUp() override {
- package_.reset(new StatePackage("test"));
- ASSERT_TRUE(package_->AddSchemaFromJson(GetTestSchema().get(), nullptr));
- ASSERT_TRUE(package_->AddValuesFromJson(GetTestValues().get(), nullptr));
- }
- void TearDown() override {
- package_.reset();
- }
- std::unique_ptr<StatePackage> package_;
-};
-
-TEST(StatePackage, Empty) {
- StatePackage package("test");
- EXPECT_EQ("test", package.GetName());
- EXPECT_TRUE(GetTypes(package).GetProps().empty());
- EXPECT_TRUE(GetValues(package).empty());
-}
-
-TEST(StatePackage, AddSchemaFromJson_OnEmpty) {
- StatePackage package("test");
- ASSERT_TRUE(package.AddSchemaFromJson(GetTestSchema().get(), nullptr));
- EXPECT_EQ(4, GetTypes(package).GetProps().size());
- EXPECT_EQ(4, GetValues(package).size());
-
- auto expected = R"({
- 'color': {
- 'type': 'string'
- },
- 'direction': {
- 'additionalProperties': false,
- 'properties': {
- 'altitude': {
- 'maximum': 90.0,
- 'type': 'number'
- },
- 'azimuth': {
- 'type': 'number'
- }
- },
- 'type': 'object'
- },
- 'iso': {
- 'enum': [50, 100, 200, 400],
- 'type': 'integer'
- },
- 'light': {
- 'type': 'boolean'
- }
- })";
- EXPECT_JSON_EQ(expected, *GetTypes(package).ToJson(true, nullptr));
-
- expected = R"({
- 'color': '',
- 'direction': {},
- 'iso': 0,
- 'light': false
- })";
- EXPECT_JSON_EQ(expected, *package.GetValuesAsJson(nullptr));
-}
-
-TEST(StatePackage, AddValuesFromJson_OnEmpty) {
- StatePackage package("test");
- ASSERT_TRUE(package.AddSchemaFromJson(GetTestSchema().get(), nullptr));
- ASSERT_TRUE(package.AddValuesFromJson(GetTestValues().get(), nullptr));
- EXPECT_EQ(4, GetValues(package).size());
- auto expected = R"({
- 'color': 'white',
- 'direction': {
- 'altitude': 89.9,
- 'azimuth': 57.2957795
- },
- 'iso': 200,
- 'light': true
- })";
- EXPECT_JSON_EQ(expected, *package.GetValuesAsJson(nullptr));
-}
-
-TEST_F(StatePackageTest, AddSchemaFromJson_AddMore) {
- auto dict = CreateDictionaryValue("{'brightness':['low', 'medium', 'high']}");
- ASSERT_TRUE(package_->AddSchemaFromJson(dict.get(), nullptr));
- EXPECT_EQ(5, GetTypes(*package_).GetProps().size());
- EXPECT_EQ(5, GetValues(*package_).size());
- auto expected = R"({
- 'brightness': {
- 'enum': ['low', 'medium', 'high'],
- 'type': 'string'
- },
- 'color': {
- 'type': 'string'
- },
- 'direction': {
- 'additionalProperties': false,
- 'properties': {
- 'altitude': {
- 'maximum': 90.0,
- 'type': 'number'
- },
- 'azimuth': {
- 'type': 'number'
- }
- },
- 'type': 'object'
- },
- 'iso': {
- 'enum': [50, 100, 200, 400],
- 'type': 'integer'
- },
- 'light': {
- 'type': 'boolean'
- }
- })";
- EXPECT_JSON_EQ(expected, *GetTypes(*package_).ToJson(true, nullptr));
-
- expected = R"({
- 'brightness': '',
- 'color': 'white',
- 'direction': {
- 'altitude': 89.9,
- 'azimuth': 57.2957795
- },
- 'iso': 200,
- 'light': true
- })";
- EXPECT_JSON_EQ(expected, *package_->GetValuesAsJson(nullptr));
-}
-
-TEST_F(StatePackageTest, AddValuesFromJson_AddMore) {
- auto dict = CreateDictionaryValue("{'brightness':['low', 'medium', 'high']}");
- ASSERT_TRUE(package_->AddSchemaFromJson(dict.get(), nullptr));
- dict = CreateDictionaryValue("{'brightness':'medium'}");
- ASSERT_TRUE(package_->AddValuesFromJson(dict.get(), nullptr));
- EXPECT_EQ(5, GetValues(*package_).size());
- auto expected = R"({
- 'brightness': 'medium',
- 'color': 'white',
- 'direction': {
- 'altitude': 89.9,
- 'azimuth': 57.2957795
- },
- 'iso': 200,
- 'light': true
- })";
- EXPECT_JSON_EQ(expected, *package_->GetValuesAsJson(nullptr));
-}
-
-TEST_F(StatePackageTest, AddSchemaFromJson_Error_Redefined) {
- auto dict = CreateDictionaryValue("{'color':['white', 'blue', 'red']}");
- chromeos::ErrorPtr error;
- EXPECT_FALSE(package_->AddSchemaFromJson(dict.get(), &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyRedefinition, error->GetCode());
- EXPECT_EQ("State property 'test.color' is already defined",
- error->GetMessage());
-}
-
-TEST_F(StatePackageTest, AddValuesFromJson_Error_Undefined) {
- auto dict = CreateDictionaryValue("{'brightness':'medium'}");
- chromeos::ErrorPtr error;
- EXPECT_FALSE(package_->AddValuesFromJson(dict.get(), &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
- EXPECT_EQ("State property 'test.brightness' is not defined",
- error->GetMessage());
-}
-
-TEST_F(StatePackageTest, GetPropertyValue) {
- chromeos::Any value = package_->GetPropertyValue("color", nullptr);
- EXPECT_EQ("white", value.TryGet<std::string>());
-
- value = package_->GetPropertyValue("light", nullptr);
- EXPECT_TRUE(value.TryGet<bool>());
-
- value = package_->GetPropertyValue("iso", nullptr);
- EXPECT_EQ(200, value.TryGet<int>());
-
- value = package_->GetPropertyValue("direction", nullptr);
- auto direction = value.TryGet<chromeos::VariantDictionary>();
- ASSERT_FALSE(direction.empty());
- EXPECT_DOUBLE_EQ(89.9, direction["altitude"].TryGet<double>());
- EXPECT_DOUBLE_EQ(57.2957795, direction["azimuth"].TryGet<double>());
-}
-
-TEST_F(StatePackageTest, GetPropertyValue_Unknown) {
- chromeos::ErrorPtr error;
- chromeos::Any value = package_->GetPropertyValue("volume", &error);
- EXPECT_TRUE(value.IsEmpty());
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
- EXPECT_EQ("State property 'test.volume' is not defined",
- error->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Simple) {
- EXPECT_TRUE(package_->SetPropertyValue("color", std::string{"blue"},
- nullptr));
- chromeos::Any value = package_->GetPropertyValue("color", nullptr);
- EXPECT_EQ("blue", value.TryGet<std::string>());
-
- EXPECT_TRUE(package_->SetPropertyValue("light", bool{false}, nullptr));
- value = package_->GetPropertyValue("light", nullptr);
- EXPECT_FALSE(value.TryGet<bool>());
-
- EXPECT_TRUE(package_->SetPropertyValue("iso", int{400}, nullptr));
- value = package_->GetPropertyValue("iso", nullptr);
- EXPECT_EQ(400, value.TryGet<int>());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Object) {
- chromeos::VariantDictionary direction{
- {"altitude", double{45.0}},
- {"azimuth", double{15.0}},
- };
- EXPECT_TRUE(package_->SetPropertyValue("direction", direction, nullptr));
-
- auto expected = R"({
- 'color': 'white',
- 'direction': {
- 'altitude': 45.0,
- 'azimuth': 15.0
- },
- 'iso': 200,
- 'light': true
- })";
- EXPECT_JSON_EQ(expected, *package_->GetValuesAsJson(nullptr));
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_TypeMismatch) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(package_->SetPropertyValue("color", int{12}, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- EXPECT_EQ("Unable to convert value to type 'string'", error->GetMessage());
- error.reset();
-
- ASSERT_FALSE(package_->SetPropertyValue("iso", bool{false}, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kTypeMismatch, error->GetCode());
- EXPECT_EQ("Unable to convert value to type 'integer'", error->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_OutOfRange) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(package_->SetPropertyValue("iso", int{150}, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
- EXPECT_EQ("Value 150 is invalid. Expected one of [50,100,200,400]",
- error->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_Object_TypeMismatch) {
- chromeos::ErrorPtr error;
- chromeos::VariantDictionary direction{
- {"altitude", double{45.0}},
- {"azimuth", int{15}},
- };
- ASSERT_FALSE(package_->SetPropertyValue("direction", direction, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kInvalidPropValue, error->GetCode());
- EXPECT_EQ("Invalid value for property 'azimuth'", error->GetMessage());
- const chromeos::Error* inner = error->GetInnerError();
- EXPECT_EQ(errors::commands::kDomain, inner->GetDomain());
- EXPECT_EQ(errors::commands::kTypeMismatch, inner->GetCode());
- EXPECT_EQ("Unable to convert value to type 'number'", inner->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_Object_OutOfRange) {
- chromeos::ErrorPtr error;
- chromeos::VariantDictionary direction{
- {"altitude", double{100.0}},
- {"azimuth", double{290.0}},
- };
- ASSERT_FALSE(package_->SetPropertyValue("direction", direction, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kInvalidPropValue, error->GetCode());
- EXPECT_EQ("Invalid value for property 'altitude'", error->GetMessage());
- const chromeos::Error* inner = error->GetInnerError();
- EXPECT_EQ(errors::commands::kDomain, inner->GetDomain());
- EXPECT_EQ(errors::commands::kOutOfRange, inner->GetCode());
- EXPECT_EQ("Value 100 is out of range. It must not be greater than 90",
- inner->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_Object_UnknownProperty) {
- chromeos::ErrorPtr error;
- chromeos::VariantDictionary direction{
- {"altitude", double{10.0}},
- {"azimuth", double{20.0}},
- {"spin", double{30.0}},
- };
- ASSERT_FALSE(package_->SetPropertyValue("direction", direction, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kUnknownProperty, error->GetCode());
- EXPECT_EQ("Unrecognized property 'spin'", error->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_Object_MissingProperty) {
- chromeos::ErrorPtr error;
- chromeos::VariantDictionary direction{
- {"altitude", double{10.0}},
- };
- ASSERT_FALSE(package_->SetPropertyValue("direction", direction, &error));
- EXPECT_EQ(errors::commands::kDomain, error->GetDomain());
- EXPECT_EQ(errors::commands::kPropertyMissing, error->GetCode());
- EXPECT_EQ("Required parameter missing: azimuth", error->GetMessage());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Error_Unknown) {
- chromeos::ErrorPtr error;
- ASSERT_FALSE(package_->SetPropertyValue("volume", int{100}, &error));
- EXPECT_EQ(errors::state::kDomain, error->GetDomain());
- EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
- EXPECT_EQ("State property 'test.volume' is not defined",
- error->GetMessage());
-}
-
-} // namespace buffet
diff --git a/buffet/storage_impls.cc b/buffet/storage_impls.cc
deleted file mode 100644
index d3242b7..0000000
--- a/buffet/storage_impls.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/storage_impls.h"
-
-#include <string>
-
-#include <base/files/important_file_writer.h>
-#include <base/json/json_writer.h>
-
-#include "buffet/utils.h"
-
-namespace buffet {
-
-FileStorage::FileStorage(const base::FilePath& file_path)
- : file_path_(file_path) { }
-
-std::unique_ptr<base::DictionaryValue> FileStorage::Load() {
- std::string json;
- if (!base::ReadFileToString(file_path_, &json))
- return std::unique_ptr<base::DictionaryValue>();
-
- return LoadJsonDict(json, nullptr);
-}
-
-bool FileStorage::Save(const base::DictionaryValue& config) {
- std::string json;
- base::JSONWriter::WriteWithOptions(
- config, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
- return base::ImportantFileWriter::WriteFileAtomically(file_path_, json);
-}
-
-std::unique_ptr<base::DictionaryValue> MemStorage::Load() {
- return std::unique_ptr<base::DictionaryValue>(cache_.DeepCopy());
-}
-
-bool MemStorage::Save(const base::DictionaryValue& config) {
- cache_.Clear();
- cache_.MergeDictionary(&config);
- return true;
-}
-
-} // namespace buffet
diff --git a/buffet/storage_impls.h b/buffet/storage_impls.h
deleted file mode 100644
index 6bdf251..0000000
--- a/buffet/storage_impls.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STORAGE_IMPLS_H_
-#define BUFFET_STORAGE_IMPLS_H_
-
-#include <base/files/file_util.h>
-#include <base/macros.h>
-#include <base/values.h>
-
-#include "buffet/storage_interface.h"
-
-namespace buffet {
-
-// Persists the given Value to an atomically written file.
-class FileStorage : public StorageInterface {
- public:
- explicit FileStorage(const base::FilePath& file_path);
- ~FileStorage() override = default;
- std::unique_ptr<base::DictionaryValue> Load() override;
- bool Save(const base::DictionaryValue& config) override;
-
- private:
- base::FilePath file_path_;
- DISALLOW_COPY_AND_ASSIGN(FileStorage);
-};
-
-// StorageInterface for testing. Just stores the values in memory.
-class MemStorage : public StorageInterface {
- public:
- MemStorage() = default;
- ~MemStorage() override = default;
- std::unique_ptr<base::DictionaryValue> Load() override;
- bool Save(const base::DictionaryValue& config) override;
-
- private:
- base::DictionaryValue cache_;
- DISALLOW_COPY_AND_ASSIGN(MemStorage);
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STORAGE_IMPLS_H_
diff --git a/buffet/storage_interface.h b/buffet/storage_interface.h
deleted file mode 100644
index c224513..0000000
--- a/buffet/storage_interface.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_STORAGE_INTERFACE_H_
-#define BUFFET_STORAGE_INTERFACE_H_
-
-#include <memory>
-
-#include <base/values.h>
-
-namespace buffet {
-
-// We need to persist data in a couple places, and it is convenient to hide
-// the details of this storage behind an interface for test purposes.
-class StorageInterface {
- public:
- virtual ~StorageInterface() = default;
-
- // Load the dictionary from storage. If it fails (e.g. the storage container
- // [file?] doesn't exist), then it returns empty unique_ptr (aka nullptr).
- virtual std::unique_ptr<base::DictionaryValue> Load() = 0;
-
- // Save the dictionary to storage. If saved successfully, returns true. Could
- // fail when writing to physical storage like file system for various reasons
- // (out of disk space,access permissions, etc).
- virtual bool Save(const base::DictionaryValue& config) = 0;
-};
-
-} // namespace buffet
-
-#endif // BUFFET_STORAGE_INTERFACE_H_
diff --git a/buffet/utils.cc b/buffet/utils.cc
deleted file mode 100644
index 33fc292..0000000
--- a/buffet/utils.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "buffet/utils.h"
-
-#include <map>
-#include <netdb.h>
-#include <string>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <base/bind_helpers.h>
-#include <base/files/file_util.h>
-#include <base/json/json_reader.h>
-#include <chromeos/errors/error_codes.h>
-
-namespace buffet {
-
-namespace {
-
-// Truncates a string if it is too long. Used for error reporting with really
-// long JSON strings.
-std::string LimitString(const std::string& text, size_t max_len) {
- if (text.size() <= max_len)
- return text;
- return text.substr(0, max_len - 3) + "...";
-}
-
-const size_t kMaxStrLen = 1700; // Log messages are limited to 2000 chars.
-
-} // anonymous namespace
-
-const char kErrorDomainBuffet[] = "buffet";
-const char kFileReadError[] = "file_read_error";
-const char kInvalidCategoryError[] = "invalid_category";
-const char kInvalidPackageError[] = "invalid_package";
-
-std::unique_ptr<base::DictionaryValue> LoadJsonDict(
- const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error) {
- std::string json_string;
- if (!base::ReadFileToString(json_file_path, &json_string)) {
- chromeos::errors::system::AddSystemError(error, FROM_HERE, errno);
- chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomainBuffet,
- kFileReadError,
- "Failed to read file '%s'",
- json_file_path.value().c_str());
- return {};
- }
- return LoadJsonDict(json_string, error);
-}
-
-std::unique_ptr<base::DictionaryValue> LoadJsonDict(
- const std::string& json_string,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<base::DictionaryValue> result;
- std::string error_message;
- auto value = base::JSONReader::ReadAndReturnError(
- json_string, base::JSON_PARSE_RFC, nullptr, &error_message);
- if (!value) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- chromeos::errors::json::kDomain,
- chromeos::errors::json::kParseError,
- "Error parsing JSON string '%s': %s",
- LimitString(json_string, kMaxStrLen).c_str(),
- error_message.c_str());
- return result;
- }
- base::DictionaryValue* dict_value = nullptr;
- if (!value->GetAsDictionary(&dict_value)) {
- chromeos::Error::AddToPrintf(error, FROM_HERE,
- chromeos::errors::json::kDomain,
- chromeos::errors::json::kObjectExpected,
- "JSON string '%s' is not a JSON object",
- LimitString(json_string, kMaxStrLen).c_str());
- return result;
- } else {
- // |value| is now owned by |dict_value|.
- base::IgnoreResult(value.release());
- }
- result.reset(dict_value);
- return result;
-}
-
-int ConnectSocket(const std::string& host, uint16_t port) {
- std::string service = std::to_string(port);
- addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM};
- addrinfo* result = nullptr;
- if (getaddrinfo(host.c_str(), service.c_str(), &hints, &result))
- return -1;
-
- int socket_fd = -1;
- for (const addrinfo* info = result; info != nullptr; info = info->ai_next) {
- socket_fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
- if (socket_fd < 0)
- continue;
-
- if (connect(socket_fd, info->ai_addr, info->ai_addrlen) == 0)
- break; // Success.
-
- close(socket_fd);
- socket_fd = -1;
- }
-
- freeaddrinfo(result);
- return socket_fd;
-}
-
-} // namespace buffet
diff --git a/buffet/utils.h b/buffet/utils.h
deleted file mode 100644
index 8e4bfd6..0000000
--- a/buffet/utils.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BUFFET_UTILS_H_
-#define BUFFET_UTILS_H_
-
-#include <memory>
-#include <string>
-
-#include <base/values.h>
-#include <base/files/file_path.h>
-#include <chromeos/errors/error.h>
-
-namespace buffet {
-
-// Buffet-wide errors.
-// TODO(avakulenko): This should be consolidated into errors::<domain> namespace
-// See crbug.com/417274
-extern const char kErrorDomainBuffet[];
-extern const char kFileReadError[];
-extern const char kInvalidCategoryError[];
-extern const char kInvalidPackageError[];
-
-// kDefaultCategory represents a default state property category for standard
-// properties from "base" package which are provided by buffet and not any of
-// the daemons running on the device.
-const char kDefaultCategory[] = "";
-
-// Helper function to load a JSON file that is expected to be
-// an object/dictionary. In case of error, returns empty unique ptr and fills
-// in error details in |error|.
-std::unique_ptr<base::DictionaryValue> LoadJsonDict(
- const base::FilePath& json_file_path,
- chromeos::ErrorPtr* error);
-
-// Helper function to load a JSON dictionary from a string.
-std::unique_ptr<base::DictionaryValue> LoadJsonDict(
- const std::string& json_string,
- chromeos::ErrorPtr* error);
-
-// Synchronously resolves the |host| and connects a socket to the resolved
-// address/port.
-// Returns the connected socket file descriptor or -1 if failed.
-int ConnectSocket(const std::string& host, uint16_t port);
-
-} // namespace buffet
-
-#endif // BUFFET_UTILS_H_