buffet: Add read-only properties with buffet config options

Added OemName, ModelName, ModelId, Name, Description, Location buffet
properties.
Added UpdateDeviceInfo to allow changing of device Name, Description and
Location.

BUG=brillo:377
TEST=FEATURE=test emerge-gizmo buffet
     test_that -b $BOARD $DEV_HOST buffet_BasicDBusAPI
CQ-DEPEND=CL:266217

Change-Id: Id27f9a65194d4b7176196b599280fc4ada66eda2
Reviewed-on: https://chromium-review.googlesource.com/266206
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/dbus_bindings/org.chromium.Buffet.Manager.xml b/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
index 249700c..0d9c485 100644
--- a/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
+++ b/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
@@ -21,6 +21,12 @@
       <arg name="device_id" type="s" direction="out"/>
       <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
     </method>
+    <method name="UpdateDeviceInfo">
+      <arg name="name" type="s" direction="in"/>
+      <arg name="description" type="s" direction="in"/>
+      <arg name="location" type="s" direction="in"/>
+      <annotation name="org.chromium.DBus.Method.Kind" value="normal"/>
+    </method>
     <method name="UpdateState">
       <arg name="property_set" type="a{sv}" direction="in"/>
       <annotation name="org.chromium.DBus.Method.Kind" value="async"/>
@@ -72,5 +78,35 @@
         JSON with command definitions of the devices.
       </tp:docstring>
     </property>
+    <property name="OemName" type="s" access="read">
+      <tp:docstring>
+        Name of the device maker.
+      </tp:docstring>
+    </property>
+    <property name="ModelName" type="s" access="read">
+      <tp:docstring>
+        Name of the device model.
+      </tp:docstring>
+    </property>
+    <property name="ModelId" type="s" access="read">
+      <tp:docstring>
+        Five character code assigned by the cloud registry of device models.
+      </tp:docstring>
+    </property>
+    <property name="Name" type="s" access="read">
+      <tp:docstring>
+        Human readable name of the device. Must not be empty.
+      </tp:docstring>
+    </property>
+    <property name="Description" type="s" access="read">
+      <tp:docstring>
+        Human readable description of the device.
+      </tp:docstring>
+    </property>
+    <property name="Location" type="s" access="read">
+      <tp:docstring>
+        Location of the device.
+      </tp:docstring>
+    </property>
   </interface>
 </node>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index ff8db89..a9601cd 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -25,6 +25,7 @@
 #include "buffet/commands/command_definition.h"
 #include "buffet/commands/command_manager.h"
 #include "buffet/device_registration_storage_keys.h"
+#include "buffet/org.chromium.Buffet.Manager.h"
 #include "buffet/states/state_manager.h"
 #include "buffet/utils.h"
 
@@ -127,14 +128,15 @@
     const std::shared_ptr<chromeos::http::Transport>& transport,
     const std::shared_ptr<StorageInterface>& state_store,
     bool xmpp_enabled,
-    const base::Closure& on_status_changed)
+    org::chromium::Buffet::ManagerAdaptor* manager)
     : transport_{transport},
       storage_{state_store},
       command_manager_{command_manager},
       state_manager_{state_manager},
       config_{std::move(config)},
       xmpp_enabled_{xmpp_enabled},
-      on_status_changed_{on_status_changed} {
+      manager_{manager} {
+  OnConfigChanged();
 }
 
 DeviceRegistrationInfo::~DeviceRegistrationInfo() = default;
@@ -198,6 +200,8 @@
   if (dict->GetString(storage_keys::kDeviceId, &device_id))
     SetDeviceId(device_id);
 
+  OnConfigChanged();
+
   if (HaveRegistrationCredentials(nullptr)) {
     // Wait a significant amount of time for local daemons to publish their
     // state to Buffet before publishing it to the cloud.
@@ -455,25 +459,22 @@
   if (!GetWithDefault(params, "ticket_id", "", &ticket_id)) {
     chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainBuffet,
                            "missing_parameter",
-                           "Need ticket_id parameter for RegisterDevice().");
+                           "Need ticket_id parameter for RegisterDevice()");
     return std::string();
   }
+
   // These fields are optional, and will default to values from the manufacturer
   // supplied config.
   std::string name;
   GetWithDefault(params, storage_keys::kName, config_->name(), &name);
-  if (!name.empty())
-    config_->set_name(name);
-
   std::string description;
   GetWithDefault(params, storage_keys::kDescription, config_->description(),
                  &description);
-  config_->set_description(description);
-
   std::string location;
   GetWithDefault(params, storage_keys::kLocation, config_->location(),
                  &location);
-  config_->set_location(location);
+  if (!UpdateDeviceInfo(name, description, location, error))
+    return std::string();
 
   std::unique_ptr<base::DictionaryValue> device_draft =
       BuildDeviceResource(error);
@@ -745,6 +746,29 @@
   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) {
+  if (name.empty()) {
+    chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainBuffet,
+                           "invalid_parameter", "Empty device name");
+    return false;
+  }
+  config_->set_name(name);
+  config_->set_description(description);
+  config_->set_location(location);
+
+  OnConfigChanged();
+
+  if (HaveRegistrationCredentials(nullptr)) {
+    UpdateDeviceResource(base::Bind(&base::DoNothing),
+                         base::Bind(&IgnoreCloudError));
+  }
+
+  return true;
+}
+
 void DeviceRegistrationInfo::UpdateCommand(
     const std::string& command_id,
     const base::DictionaryValue& command_patch) {
@@ -929,20 +953,28 @@
 
 void DeviceRegistrationInfo::SetRegistrationStatus(
     RegistrationStatus new_status) {
-  if (new_status == registration_status_)
-    return;
-  VLOG(1) << "Changing registration status to " << StatusToString(new_status);
   registration_status_ = new_status;
-  if (!on_status_changed_.is_null())
-    on_status_changed_.Run();
+  if (manager_)
+    manager_->SetStatus(StatusToString(registration_status_));
+  VLOG_IF(1, new_status != registration_status_)
+      << "Changing registration status to " << StatusToString(new_status);
 }
 
 void DeviceRegistrationInfo::SetDeviceId(const std::string& device_id) {
-  if (device_id == device_id_)
-    return;
   device_id_ = device_id;
-  if (!on_status_changed_.is_null())
-    on_status_changed_.Run();
+  if (manager_)
+    manager_->SetDeviceId(device_id_);
+}
+
+void DeviceRegistrationInfo::OnConfigChanged() {
+  if (!manager_)
+    return;
+  manager_->SetOemName(config_->oem_name());
+  manager_->SetModelName(config_->model_name());
+  manager_->SetModelId(config_->model_id());
+  manager_->SetName(config_->name());
+  manager_->SetDescription(config_->description());
+  manager_->SetLocation(config_->location());
 }
 
 }  // namespace buffet
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h
index 11b8e37..e3a4b80 100644
--- a/buffet/device_registration_info.h
+++ b/buffet/device_registration_info.h
@@ -25,6 +25,14 @@
 #include "buffet/storage_interface.h"
 #include "buffet/xmpp/xmpp_client.h"
 
+namespace org {
+namespace chromium {
+namespace Buffet {
+class ManagerAdaptor;
+}
+}
+}
+
 namespace base {
 class DictionaryValue;
 }  // namespace base
@@ -55,7 +63,7 @@
       const std::shared_ptr<chromeos::http::Transport>& transport,
       const std::shared_ptr<StorageInterface>& state_store,
       bool xmpp_enabled,
-      const base::Closure& on_status_changed);
+      org::chromium::Buffet::ManagerAdaptor* manager);
 
   ~DeviceRegistrationInfo() override;
 
@@ -134,6 +142,12 @@
   void UpdateCommand(const std::string& command_id,
                      const base::DictionaryValue& command_patch);
 
+  // Updates basic device information.
+  bool UpdateDeviceInfo(const std::string& name,
+                        const std::string& description,
+                        const std::string& location,
+                        chromeos::ErrorPtr* error);
+
  private:
   // Cause DeviceRegistrationInfo to attempt to StartDevice on its own later.
   void ScheduleStartDevice(const base::TimeDelta& later);
@@ -209,6 +223,7 @@
 
   void SetRegistrationStatus(RegistrationStatus new_status);
   void SetDeviceId(const std::string& device_id);
+  void OnConfigChanged();
 
   // Data that is cached here, persisted in the state store.
   std::string refresh_token_;
@@ -236,7 +251,7 @@
 
   // Tracks our current registration status.
   RegistrationStatus registration_status_{RegistrationStatus::kUnconfigured};
-  base::Closure on_status_changed_;
+  org::chromium::Buffet::ManagerAdaptor* manager_;
 
   base::RepeatingTimer<DeviceRegistrationInfo> command_poll_timer_;
   base::RepeatingTimer<DeviceRegistrationInfo> state_push_timer_;
diff --git a/buffet/device_registration_info_unittest.cc b/buffet/device_registration_info_unittest.cc
index 2f25d7a..7e09cfd 100644
--- a/buffet/device_registration_info_unittest.cc
+++ b/buffet/device_registration_info_unittest.cc
@@ -197,21 +197,14 @@
     config_store.SetString("service_url", test_data::kServiceURL);
     std::unique_ptr<BuffetConfig> config{new BuffetConfig};
     config->Load(config_store);
-    auto mock_callback = base::Bind(
-        &DeviceRegistrationInfoTest::OnRegistrationStatusChange,
-        base::Unretained(this));
     dev_reg_ = std::unique_ptr<DeviceRegistrationInfo>(
         new DeviceRegistrationInfo(command_manager_, state_manager_,
                                    std::move(config),
                                    transport_, storage_,
                                    true,
-                                   mock_callback));
-    EXPECT_CALL(*this, OnRegistrationStatusChange())
-        .Times(testing::AnyNumber());
+                                   nullptr));
   }
 
-  MOCK_METHOD0(OnRegistrationStatusChange, void());
-
   base::DictionaryValue data_;
   std::shared_ptr<MemStorage> storage_;
   std::shared_ptr<chromeos::http::fake::Transport> transport_;
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 34dad7a..93d3029 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -73,8 +73,7 @@
           chromeos::http::Transport::CreateDefault(),
           std::move(state_store),
           xmpp_enabled,
-          base::Bind(&Manager::OnRegistrationStatusChanged,
-                     base::Unretained(this))));
+          &dbus_adaptor_));
   device_info_->Load();
   dbus_adaptor_.RegisterWithDBusObject(&dbus_object_);
   dbus_object_.RegisterAsync(cb);
@@ -213,10 +212,12 @@
   return message;
 }
 
-void Manager::OnRegistrationStatusChanged() {
-  dbus_adaptor_.SetStatus(
-      StatusToString(device_info_->GetRegistrationStatus()));
-  dbus_adaptor_.SetDeviceId(device_info_->GetDeviceId());
+bool Manager::UpdateDeviceInfo(chromeos::ErrorPtr* error,
+                               const std::string& in_name,
+                               const std::string& in_description,
+                               const std::string& in_location) {
+  return device_info_->UpdateDeviceInfo(in_name, in_description, in_location,
+                                        error);
 }
 
 void Manager::OnCommandDefsChanged() {
diff --git a/buffet/manager.h b/buffet/manager.h
index 6a4f88d..177d3d1 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -32,6 +32,7 @@
 class CommandManager;
 class StateChangeQueue;
 class StateManager;
+class BuffetConfig;
 
 template<typename... Types>
 using DBusMethodResponse =
@@ -56,28 +57,23 @@
 
  private:
   // DBus methods:
-  // Handles calls to org.chromium.Buffet.Manager.CheckDeviceRegistered().
   void CheckDeviceRegistered(DBusMethodResponse<std::string> response) override;
-  // Handles calls to org.chromium.Buffet.Manager.GetDeviceInfo().
   void GetDeviceInfo(DBusMethodResponse<std::string> response) override;
-  // Handles calls to org.chromium.Buffet.Manager.RegisterDevice().
   void RegisterDevice(DBusMethodResponse<std::string> response,
                       const chromeos::VariantDictionary& params) override;
-  // Handles calls to org.chromium.Buffet.Manager.UpdateState().
+  bool UpdateDeviceInfo(chromeos::ErrorPtr* error,
+                        const std::string& in_name,
+                        const std::string& in_description,
+                        const std::string& in_location) override;
   void UpdateState(DBusMethodResponse<> response,
                    const chromeos::VariantDictionary& property_set) override;
-  // Handles calls to org.chromium.Buffet.Manager.GetState().
   bool GetState(chromeos::ErrorPtr* error, std::string* state) override;
-  // Handles calls to org.chromium.Buffet.Manager.AddCommand().
   void AddCommand(DBusMethodResponse<std::string> response,
                   const std::string& json_command) override;
-  // Handles calls to org.chromium.Buffet.Manager.GetCommand().
   void GetCommand(DBusMethodResponse<std::string> response,
                   const std::string& id) override;
-  // Handles calls to org.chromium.Buffet.Manager.Test()
   std::string TestMethod(const std::string& message) override;
 
-  void OnRegistrationStatusChanged();
   void OnCommandDefsChanged();
 
   org::chromium::Buffet::ManagerAdaptor dbus_adaptor_{this};