privetd: Implement /privet/v3/commandDefs

Buffet exposes D-Bus property CommandDefs.
Privetd reads commands from buffet using D-Bus in CloudDelegate.
Buffet will update property if definitions changed. Still there is no Buffet
codepath which changes commad definitions after loading.

BUG=brillo:426
TEST=unittest

Change-Id: I18dac0f87325257fa31c0fe3e0c883a9ed40e4c7
Reviewed-on: https://chromium-review.googlesource.com/261611
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/commands/command_manager.cc b/buffet/commands/command_manager.cc
index 78e0dee..afdd518 100644
--- a/buffet/commands/command_manager.cc
+++ b/buffet/commands/command_manager.cc
@@ -47,7 +47,11 @@
 bool CommandManager::LoadCommands(const base::DictionaryValue& json,
                                   const std::string& category,
                                   chromeos::ErrorPtr* error) {
-  return dictionary_.LoadCommands(json, category, &base_dictionary_, error);
+  bool result =
+      dictionary_.LoadCommands(json, category, &base_dictionary_, error);
+  if (!on_command_defs_changed_.is_null())
+    on_command_defs_changed_.Run();
+  return result;
 }
 
 bool CommandManager::LoadCommands(const base::FilePath& json_file_path,
diff --git a/buffet/commands/command_manager.h b/buffet/commands/command_manager.h
index f176cad..8088e26 100644
--- a/buffet/commands/command_manager.h
+++ b/buffet/commands/command_manager.h
@@ -37,7 +37,12 @@
       const base::WeakPtr<chromeos::dbus_utils::ExportedObjectManager>&
           object_manager);
 
-  // Get the command definitions for the device.
+  // Sets callback which is called when command definitions is changed.
+  void SetOnCommandDefChanged(const base::Closure& on_command_defs_changed) {
+    on_command_defs_changed_ = on_command_defs_changed;
+  }
+
+  // Returns the command definitions for the device.
   const CommandDictionary& GetCommandDictionary() const;
 
   // Loads base/standard GCD command definitions.
@@ -91,6 +96,7 @@
   CommandDictionary dictionary_;  // Command definitions/schemas.
   CommandQueue command_queue_;
   DBusCommandDispacher command_dispatcher_;
+  base::Closure on_command_defs_changed_;
 
   DISALLOW_COPY_AND_ASSIGN(CommandManager);
 };
diff --git a/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml b/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
index 7ec49a7..8473fe2 100644
--- a/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
+++ b/buffet/dbus_bindings/org.chromium.Buffet.Manager.xml
@@ -61,5 +61,10 @@
         GCD ID if the device is registered or empty otherwise.
       </tp:docstring>
     </property>
+    <property name="CommandDefs" type="s" access="read">
+      <tp:docstring>
+        JSON with command definitions of the devices.
+      </tp:docstring>
+    </property>
   </interface>
 </node>
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 0855384..f7bef10 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -51,6 +51,8 @@
                             const AsyncEventSequencer::CompletionAction& cb) {
   command_manager_ =
       std::make_shared<CommandManager>(dbus_object_.GetObjectManager());
+  command_manager_->SetOnCommandDefChanged(
+      base::Bind(&Manager::OnCommandDefsChanged, base::Unretained(this)));
   command_manager_->Startup(base::FilePath{"/etc/buffet"},
                             test_definitions_path);
   state_change_queue_ = std::unique_ptr<StateChangeQueue>(
@@ -199,4 +201,14 @@
   dbus_adaptor_.SetDeviceId(device_info_->GetDeviceId());
 }
 
+void Manager::OnCommandDefsChanged() {
+  chromeos::ErrorPtr error;
+  std::unique_ptr<base::DictionaryValue> commands =
+      command_manager_->GetCommandDictionary().GetCommandsAsJson(true, &error);
+  CHECK(commands);
+  std::string json;
+  base::JSONWriter::Write(commands.get(), &json);
+  dbus_adaptor_.SetCommandDefs(json);
+}
+
 }  // namespace buffet
diff --git a/buffet/manager.h b/buffet/manager.h
index 0136019..d307ca2 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -74,6 +74,7 @@
   std::string TestMethod(const std::string& message) override;
 
   void OnRegistrationStatusChanged();
+  void OnCommandDefsChanged();
 
   org::chromium::Buffet::ManagerAdaptor dbus_adaptor_{this};
   chromeos::dbus_utils::DBusObject dbus_object_;