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);
};