buffet: Add the ability to change command visibility Now it is possible to change the visibility of command and make it visible to cloud only, local only, both or none. BUG=brillo:797 TEST=`FEATURES=test emerge-link buffet` Change-Id: I81d526b3d43adf5d6cd03a4e31a31e1494ff5c1b Reviewed-on: https://chromium-review.googlesource.com/266396 Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org> Tested-by: Alex Vakulenko <avakulenko@chromium.org> Reviewed-by: Vitaly Buka <vitalybuka@chromium.org> Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/commands/command_dictionary.cc b/buffet/commands/command_dictionary.cc index f2b6f2f..3ab57a5 100644 --- a/buffet/commands/command_dictionary.cc +++ b/buffet/commands/command_dictionary.cc
@@ -235,6 +235,12 @@ return (pair != definitions_.end()) ? pair->second.get() : nullptr; } +CommandDefinition* CommandDictionary::FindCommand( + const std::string& command_name) { + auto pair = definitions_.find(command_name); + return (pair != definitions_.end()) ? pair->second.get() : nullptr; +} + void CommandDictionary::Clear() { definitions_.clear(); }
diff --git a/buffet/commands/command_dictionary.h b/buffet/commands/command_dictionary.h index 52e1a10..7668fba 100644 --- a/buffet/commands/command_dictionary.h +++ b/buffet/commands/command_dictionary.h
@@ -78,6 +78,7 @@ void Clear(); // Finds a definition for the given command. const CommandDefinition* FindCommand(const std::string& command_name) const; + CommandDefinition* FindCommand(const std::string& command_name); private: using CommandMap = std::map<std::string, std::unique_ptr<CommandDefinition>>;
diff --git a/buffet/commands/command_manager.cc b/buffet/commands/command_manager.cc index 6facaf9..dd90e7d 100644 --- a/buffet/commands/command_manager.cc +++ b/buffet/commands/command_manager.cc
@@ -104,4 +104,35 @@ return command_queue_.Find(id); } +bool CommandManager::SetCommandVisibility( + const std::vector<std::string>& command_names, + CommandDefinition::Visibility visibility, + chromeos::ErrorPtr* error) { + if (command_names.empty()) + return true; + + std::vector<CommandDefinition*> definitions; + definitions.reserve(command_names.size()); + + // Find/validate command definitions first. + for (const std::string& name : command_names) { + CommandDefinition* def = dictionary_.FindCommand(name); + if (!def) { + chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain, + errors::commands::kInvalidCommandName, + "Command '%s' is unknown", name.c_str()); + return false; + } + definitions.push_back(def); + } + + // Now that we know that all the command names were valid, + // update the respective commands' visibility. + for (CommandDefinition* def : definitions) { + def->SetVisibility(visibility); + } + on_command_changed_.Notify(); + return true; +} + } // namespace buffet
diff --git a/buffet/commands/command_manager.h b/buffet/commands/command_manager.h index 3e23cbf..072d055 100644 --- a/buffet/commands/command_manager.h +++ b/buffet/commands/command_manager.h
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include <vector> #include <base/callback.h> #include <base/callback_list.h> @@ -49,7 +50,8 @@ explicit CommandManager(CommandDispachInterface* dispatch_interface); // Sets callback which is called when command definitions is changed. - CallbackToken AddOnCommandDefChanged(const base::Closure& callback) { + CallbackToken AddOnCommandDefChanged( + const base::Closure& callback) WARN_UNUSED_RESULT { return CallbackToken{on_command_changed_.Add(callback).release()}; } @@ -102,6 +104,11 @@ // for a long period of time. CommandInstance* FindCommand(const std::string& id) const; + // Changes the visibility of commands. + bool SetCommandVisibility(const std::vector<std::string>& command_names, + CommandDefinition::Visibility visibility, + chromeos::ErrorPtr* error); + private: CommandDictionary base_dictionary_; // Base/std command definitions/schemas. CommandDictionary dictionary_; // Command definitions/schemas.
diff --git a/buffet/commands/command_manager_unittest.cc b/buffet/commands/command_manager_unittest.cc index 2d4fed8..57e0d06 100644 --- a/buffet/commands/command_manager_unittest.cc +++ b/buffet/commands/command_manager_unittest.cc
@@ -7,6 +7,7 @@ #include <base/files/file_util.h> #include <base/files/scoped_temp_dir.h> #include <base/json/json_writer.h> +#include <chromeos/bind_lambda.h> #include <gtest/gtest.h> #include "buffet/commands/unittest_utils.h" @@ -156,3 +157,61 @@ EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("test._yo")); } + +TEST(CommandManager, UpdateCommandVisibility) { + buffet::CommandManager manager; + int update_count = 0; + auto on_command_change = [&update_count]() { update_count++; }; + auto token = manager.AddOnCommandDefChanged(base::Bind(on_command_change)); + + auto json = CreateDictionaryValue(R"({ + 'foo': { + '_baz': { + 'parameters': {}, + 'results': {} + }, + '_bar': { + 'parameters': {}, + 'results': {} + } + }, + 'bar': { + '_quux': { + 'parameters': {}, + 'results': {}, + 'visibility': 'none' + } + } + })"); + ASSERT_TRUE(manager.LoadCommands(*json, "test", nullptr)); + EXPECT_EQ(1, update_count); + const buffet::CommandDictionary& dict = manager.GetCommandDictionary(); + EXPECT_TRUE(manager.SetCommandVisibility( + {"foo._baz"}, + buffet::CommandDefinition::Visibility::GetLocal(), nullptr)); + EXPECT_EQ(2, update_count); + EXPECT_EQ("local", dict.FindCommand("foo._baz")->GetVisibility().ToString()); + EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString()); + EXPECT_EQ("none", dict.FindCommand("bar._quux")->GetVisibility().ToString()); + + chromeos::ErrorPtr error; + ASSERT_FALSE(manager.SetCommandVisibility( + {"foo._baz", "foo._bar", "test.cmd"}, + buffet::CommandDefinition::Visibility::GetLocal(), &error)); + EXPECT_EQ(buffet::errors::commands::kInvalidCommandName, error->GetCode()); + EXPECT_EQ("Command 'test.cmd' is unknown", error->GetMessage()); + // The visibility state of commands shouldn't have changed. + EXPECT_EQ(2, update_count); + EXPECT_EQ("local", dict.FindCommand("foo._baz")->GetVisibility().ToString()); + EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString()); + EXPECT_EQ("none", dict.FindCommand("bar._quux")->GetVisibility().ToString()); + + EXPECT_TRUE(manager.SetCommandVisibility( + {"foo._baz", "bar._quux"}, + buffet::CommandDefinition::Visibility::GetCloud(), nullptr)); + EXPECT_EQ(3, update_count); + EXPECT_EQ("cloud", dict.FindCommand("foo._baz")->GetVisibility().ToString()); + EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString()); + EXPECT_EQ("cloud", dict.FindCommand("bar._quux")->GetVisibility().ToString()); +} +