buffet: Add 'origin' property to Command

Now it is possible to distinguish commands that came from local
clients from those that were sent from the cloud.

The vendor applications could make a decision on how to process
the command depending on where it came from. Also, the command
status update code could do different things depending on whether
status updates need to go to the cloud or the local client.

BUG=None
TEST=`FEATURES=test emerge-link buffet`

Change-Id: I80156c5b43dace0b79b87b86618bfec017b30de9
Reviewed-on: https://chromium-review.googlesource.com/266563
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/commands/command_instance_unittest.cc b/buffet/commands/command_instance_unittest.cc
index e1d874b..55731b4 100644
--- a/buffet/commands/command_instance_unittest.cc
+++ b/buffet/commands/command_instance_unittest.cc
@@ -73,9 +73,10 @@
   params["phrase"] = str_prop.CreateValue(std::string("iPityDaFool"),
                                           nullptr);
   params["volume"] = int_prop.CreateValue(5, nullptr);
-  buffet::CommandInstance instance("robot.speak",
+  buffet::CommandInstance instance{"robot.speak",
+                                   "cloud",
                                    dict_.FindCommand("robot.speak"),
-                                   params);
+                                   params};
 
   buffet::native_types::Object results;
   results["foo"] = int_prop.CreateValue(239, nullptr);
@@ -84,18 +85,26 @@
   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());
+
+  buffet::CommandInstance instance2{"base.reboot",
+                                   "local",
+                                   dict_.FindCommand("base.reboot"),
+                                   {}};
+  EXPECT_EQ("local", instance2.GetOrigin());
 }
 
 TEST_F(CommandInstanceTest, SetID) {
-  buffet::CommandInstance instance("robot._beep",
-                                   dict_.FindCommand("robot.speak"),
-                                   {});
+  buffet::CommandInstance instance{"base.reboot",
+                                   "local",
+                                   dict_.FindCommand("base.reboot"),
+                                   {}};
   instance.SetID("command_id");
   EXPECT_EQ("command_id", instance.GetID());
 }
@@ -109,7 +118,8 @@
     },
     'results': {}
   })");
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, nullptr);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    nullptr);
   EXPECT_EQ("robot.jump", instance->GetName());
   EXPECT_EQ("robotd", instance->GetCategory());
   EXPECT_EQ(53, instance->FindParameter("height")->GetInt()->GetValue());
@@ -119,7 +129,8 @@
 
 TEST_F(CommandInstanceTest, FromJson_ParamsOmitted) {
   auto json = CreateDictionaryValue("{'name': 'base.reboot'}");
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, nullptr);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    nullptr);
   EXPECT_EQ("base.reboot", instance->GetName());
   EXPECT_EQ("robotd", instance->GetCategory());
   EXPECT_TRUE(instance->GetParameters().empty());
@@ -128,7 +139,8 @@
 TEST_F(CommandInstanceTest, FromJson_NotObject) {
   auto json = CreateValue("'string'");
   chromeos::ErrorPtr error;
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    &error);
   EXPECT_EQ(nullptr, instance.get());
   EXPECT_EQ("json_object_expected", error->GetCode());
   EXPECT_EQ("Command instance is not a JSON object", error->GetMessage());
@@ -137,7 +149,8 @@
 TEST_F(CommandInstanceTest, FromJson_NameMissing) {
   auto json = CreateDictionaryValue("{'param': 'value'}");
   chromeos::ErrorPtr error;
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    &error);
   EXPECT_EQ(nullptr, instance.get());
   EXPECT_EQ("parameter_missing", error->GetCode());
   EXPECT_EQ("Command name is missing", error->GetMessage());
@@ -146,7 +159,8 @@
 TEST_F(CommandInstanceTest, FromJson_UnknownCommand) {
   auto json = CreateDictionaryValue("{'name': 'robot.scream'}");
   chromeos::ErrorPtr error;
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    &error);
   EXPECT_EQ(nullptr, instance.get());
   EXPECT_EQ("invalid_command_name", error->GetCode());
   EXPECT_EQ("Unknown command received: robot.scream", error->GetMessage());
@@ -158,7 +172,8 @@
     'parameters': 'hello'
   })");
   chromeos::ErrorPtr error;
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    &error);
   EXPECT_EQ(nullptr, instance.get());
   auto inner = error->GetInnerError();
   EXPECT_EQ("json_object_expected", inner->GetCode());
@@ -176,7 +191,8 @@
     }
   })");
   chromeos::ErrorPtr error;
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    &error);
   EXPECT_EQ(nullptr, instance.get());
   auto first = error->GetFirstError();
   EXPECT_EQ("out_of_range", first->GetCode());
@@ -199,7 +215,8 @@
     },
     'results': {}
   })");
-  auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, nullptr);
+  auto instance = buffet::CommandInstance::FromJson(json.get(), "cloud", dict_,
+                                                    nullptr);
   instance->SetProgress(15);
   instance->SetID("testId");
   buffet::native_types::Object results;