buffet: Added base.updateDeviceInfo handler base.updateDeviceInfo changes 'name', 'description' and 'location' properties of the device resource. BUG=brillo:697 TEST='FEATURES=test emerge-storm buffet' Change-Id: Id1b349c97d2132117cdf803dda8e39d25c64621a Reviewed-on: https://chromium-review.googlesource.com/270787 Reviewed-by: Vitaly Buka <vitalybuka@chromium.org> Commit-Queue: Vitaly Buka <vitalybuka@chromium.org> Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/base_api_handler.cc b/buffet/base_api_handler.cc new file mode 100644 index 0000000..ce08bd1 --- /dev/null +++ b/buffet/base_api_handler.cc
@@ -0,0 +1,75 @@ +// 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" + +namespace buffet { + +namespace { + +// Helps to get parameters from native_types::Object representing +// CommandInstance parameters. +class ParametersReader { + 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; + } + + private: + const native_types::Object* parameters_; +}; + +} // namespace + +BaseApiHandler::BaseApiHandler( + const base::WeakPtr<DeviceRegistrationInfo>& device_info, + const std::shared_ptr<CommandManager>& command_manager) + : device_info_{device_info} { + 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.updateDeviceInfo") + return UpdateDeviceInfo(command); +} + +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 new file mode 100644 index 0000000..8743bcf --- /dev/null +++ b/buffet/base_api_handler.h
@@ -0,0 +1,41 @@ +// 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; + +// Handles commands from 'base' package. +// Objects of the class subscribe for notification from CommandManager and +// execute incoming commands. +// Handled commands: +// base.updateDeviceInfo +class BaseApiHandler final { + public: + BaseApiHandler(const base::WeakPtr<DeviceRegistrationInfo>& device_info, + const std::shared_ptr<CommandManager>& command_manager); + + private: + void OnCommandAdded(CommandInstance* command); + void UpdateDeviceInfo(CommandInstance* command); + + base::WeakPtr<DeviceRegistrationInfo> device_info_; + + 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 new file mode 100644 index 0000000..011f639 --- /dev/null +++ b/buffet/base_api_handler_unittest.cc
@@ -0,0 +1,99 @@ +// 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 { + storage_ = std::make_shared<MemStorage>(); + transport_ = std::make_shared<chromeos::http::fake::Transport>(); + command_manager_ = std::make_shared<CommandManager>(); + state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_); + state_manager_->Startup(); + dev_reg_.reset(new DeviceRegistrationInfo( + command_manager_, state_manager_, + std::unique_ptr<BuffetConfig>{new BuffetConfig}, transport_, storage_, + true, nullptr)); + handler_.reset(new BaseApiHandler{dev_reg_->AsWeakPtr(), 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<MemStorage> storage_; + 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, 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 e67b6ea..83cebba 100644 --- a/buffet/buffet.gyp +++ b/buffet/buffet.gyp
@@ -18,6 +18,7 @@ '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', @@ -106,6 +107,7 @@ }, 'includes': ['../common-mk/common_test.gypi'], 'sources': [ + 'base_api_handler_unittest.cc', 'buffet_testrunner.cc', 'commands/command_definition_unittest.cc', 'commands/command_dictionary_unittest.cc',
diff --git a/buffet/commands/command_manager.cc b/buffet/commands/command_manager.cc index cbaaeca..d0743de 100644 --- a/buffet/commands/command_manager.cc +++ b/buffet/commands/command_manager.cc
@@ -134,4 +134,14 @@ 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 index 88ebca7..9a891ba 100644 --- a/buffet/commands/command_manager.h +++ b/buffet/commands/command_manager.h
@@ -98,6 +98,12 @@ 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.
diff --git a/buffet/commands/command_queue.cc b/buffet/commands/command_queue.cc index 614261e..f4cda60 100644 --- a/buffet/commands/command_queue.cc +++ b/buffet/commands/command_queue.cc
@@ -15,6 +15,9 @@ 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) {
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h index a762758..40f4f94 100644 --- a/buffet/device_registration_info.h +++ b/buffet/device_registration_info.h
@@ -146,6 +146,12 @@ const std::string& location, chromeos::ErrorPtr* error); + const BuffetConfig& GetConfig() const { return *config_; } + + base::WeakPtr<DeviceRegistrationInfo> AsWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + private: // Cause DeviceRegistrationInfo to attempt to StartDevice on its own later. void ScheduleStartDevice(const base::TimeDelta& later);
diff --git a/buffet/manager.cc b/buffet/manager.cc index a5fff7d..90562aa 100644 --- a/buffet/manager.cc +++ b/buffet/manager.cc
@@ -21,6 +21,7 @@ #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/states/state_change_queue.h" @@ -57,8 +58,7 @@ &Manager::OnCommandDefsChanged, weak_ptr_factory_.GetWeakPtr())); command_manager_->Startup(base::FilePath{"/etc/buffet"}, test_definitions_path); - state_change_queue_ = std::unique_ptr<StateChangeQueue>( - new StateChangeQueue(kMaxStateChangeQueueSize)); + state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize)); state_manager_ = std::make_shared<StateManager>(state_change_queue_.get()); state_manager_->Startup(); std::unique_ptr<BuffetConfig> config{new BuffetConfig}; @@ -66,15 +66,14 @@ std::unique_ptr<FileStorage> state_store{new FileStorage{state_path}}; // TODO(avakulenko): Figure out security implications of storing // device info state data unencrypted. - device_info_ = std::unique_ptr<DeviceRegistrationInfo>( - new DeviceRegistrationInfo( - command_manager_, - state_manager_, - std::move(config), - chromeos::http::Transport::CreateDefault(), - std::move(state_store), - xmpp_enabled, - &dbus_adaptor_)); + device_info_.reset(new DeviceRegistrationInfo( + command_manager_, state_manager_, std::move(config), + chromeos::http::Transport::CreateDefault(), std::move(state_store), + xmpp_enabled, &dbus_adaptor_)); + + base_api_handler_.reset( + new BaseApiHandler{device_info_->AsWeakPtr(), command_manager_}); + device_info_->Load(); dbus_adaptor_.RegisterWithDBusObject(&dbus_object_); dbus_object_.RegisterAsync(cb);
diff --git a/buffet/manager.h b/buffet/manager.h index a685a05..44790d3 100644 --- a/buffet/manager.h +++ b/buffet/manager.h
@@ -31,9 +31,10 @@ namespace buffet { +class BaseApiHandler; +class BuffetConfig; class StateChangeQueue; class StateManager; -class BuffetConfig; template<typename... Types> using DBusMethodResponse = @@ -88,9 +89,9 @@ std::unique_ptr<StateChangeQueue> state_change_queue_; std::shared_ptr<StateManager> state_manager_; std::unique_ptr<DeviceRegistrationInfo> device_info_; + std::unique_ptr<BaseApiHandler> base_api_handler_; base::WeakPtrFactory<Manager> weak_ptr_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(Manager); };