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