blob: 71ea5a9cb8765a1ea265014f91d61a0e8961dfbc [file] [log] [blame]
Alex Vakulenko7c36b672014-07-16 14:50:58 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "buffet/commands/command_manager.h"
6
Alex Vakulenko5841c302014-07-23 10:49:49 -07007#include <base/files/file_enumerator.h>
Alex Vakulenko5841c302014-07-23 10:49:49 -07008#include <base/values.h>
Alex Vakulenko95110752014-09-03 16:27:21 -07009#include <chromeos/dbus/exported_object_manager.h>
Alex Vakulenkoa8b95bc2014-08-27 11:00:57 -070010#include <chromeos/errors/error.h>
Alex Vakulenkofd448692014-07-22 07:46:53 -070011
12#include "buffet/commands/schema_constants.h"
Alex Vakulenkob04936f2014-09-19 14:53:58 -070013#include "buffet/utils.h"
Alex Vakulenkofd448692014-07-22 07:46:53 -070014
Alex Vakulenko95110752014-09-03 16:27:21 -070015using chromeos::dbus_utils::ExportedObjectManager;
16
Alex Vakulenko7c36b672014-07-16 14:50:58 -070017namespace buffet {
18
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070019CommandManager::CommandManager()
20 : CommandManager(base::WeakPtr<ExportedObjectManager>{}) {
Alex Vakulenko95110752014-09-03 16:27:21 -070021}
22
23CommandManager::CommandManager(
24 const base::WeakPtr<ExportedObjectManager>& object_manager)
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070025 : command_dispatcher_(object_manager) {
26 command_queue_.AddOnCommandAddedCallback(
27 base::Bind(&DBusCommandDispacher::OnCommandAdded,
28 base::Unretained(&command_dispatcher_)));
Alex Vakulenko9e2f8cd2015-04-07 16:28:09 -070029}
30
Alex Vakulenko7c36b672014-07-16 14:50:58 -070031const CommandDictionary& CommandManager::GetCommandDictionary() const {
32 return dictionary_;
33}
34
Alex Vakulenkofd448692014-07-22 07:46:53 -070035bool CommandManager::LoadBaseCommands(const base::DictionaryValue& json,
Alex Vakulenko5f472062014-08-14 17:54:04 -070036 chromeos::ErrorPtr* error) {
Alex Vakulenkofd448692014-07-22 07:46:53 -070037 return base_dictionary_.LoadCommands(json, "", nullptr, error);
38}
39
40bool CommandManager::LoadBaseCommands(const base::FilePath& json_file_path,
Alex Vakulenko5f472062014-08-14 17:54:04 -070041 chromeos::ErrorPtr* error) {
Alex Vakulenkofd448692014-07-22 07:46:53 -070042 std::unique_ptr<const base::DictionaryValue> json = LoadJsonDict(
43 json_file_path, error);
44 if (!json)
45 return false;
46 return LoadBaseCommands(*json, error);
47}
48
49bool CommandManager::LoadCommands(const base::DictionaryValue& json,
50 const std::string& category,
Alex Vakulenko5f472062014-08-14 17:54:04 -070051 chromeos::ErrorPtr* error) {
Vitaly Bukaaabadee2015-03-18 23:33:44 -070052 bool result =
53 dictionary_.LoadCommands(json, category, &base_dictionary_, error);
Vitaly Buka5e6ff6c2015-05-11 15:41:33 -070054 for (const auto& cb : on_command_changed_)
55 cb.Run();
Vitaly Bukaaabadee2015-03-18 23:33:44 -070056 return result;
Alex Vakulenkofd448692014-07-22 07:46:53 -070057}
58
59bool CommandManager::LoadCommands(const base::FilePath& json_file_path,
Alex Vakulenko5f472062014-08-14 17:54:04 -070060 chromeos::ErrorPtr* error) {
Alex Vakulenkofd448692014-07-22 07:46:53 -070061 std::unique_ptr<const base::DictionaryValue> json = LoadJsonDict(
62 json_file_path, error);
63 if (!json)
64 return false;
65 std::string category = json_file_path.BaseName().RemoveExtension().value();
66 return LoadCommands(*json, category, error);
67}
68
Christopher Wileybb5b8482015-02-12 13:42:16 -080069void CommandManager::Startup(const base::FilePath& definitions_path,
70 const base::FilePath& test_definitions_path) {
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -070071 LOG(INFO) << "Initializing CommandManager.";
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -070072 // Load global standard GCD command dictionary.
Christopher Wileybb5b8482015-02-12 13:42:16 -080073 base::FilePath base_command_file{definitions_path.Append("gcd.json")};
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -070074 LOG(INFO) << "Loading standard commands from " << base_command_file.value();
Alex Vakulenkoc2bc9a42014-07-23 10:57:58 -070075 CHECK(LoadBaseCommands(base_command_file, nullptr))
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -070076 << "Failed to load the standard command definitions.";
77
Christopher Wileybb5b8482015-02-12 13:42:16 -080078 auto LoadPackages = [this](const base::FilePath& root,
79 const base::FilePath::StringType& pattern) {
80 base::FilePath device_command_dir{root.Append("commands")};
81 VLOG(2) << "Looking for commands in " << root.value();
82 base::FileEnumerator enumerator(device_command_dir, false,
83 base::FileEnumerator::FILES,
84 pattern);
85 base::FilePath json_file_path = enumerator.Next();
86 while (!json_file_path.empty()) {
87 LOG(INFO) << "Loading command schema from " << json_file_path.value();
88 CHECK(this->LoadCommands(json_file_path, nullptr))
89 << "Failed to load the command definition file.";
90 json_file_path = enumerator.Next();
91 }
92 };
93 LoadPackages(definitions_path, FILE_PATH_LITERAL("*.json"));
94 LoadPackages(test_definitions_path, FILE_PATH_LITERAL("*test.json"));
Alex Vakulenkoe4efaaf2014-07-22 08:08:44 -070095}
96
Anton Muhin5191e812014-10-30 17:49:48 +040097void CommandManager::AddCommand(
Alex Vakulenko95110752014-09-03 16:27:21 -070098 std::unique_ptr<CommandInstance> command_instance) {
Anton Muhin5191e812014-10-30 17:49:48 +040099 command_queue_.Add(std::move(command_instance));
100}
101
Vitaly Buka4547afa2015-06-09 09:46:53 -0700102bool CommandManager::AddCommand(const base::DictionaryValue& command,
103 UserRole role,
104 std::string* id,
105 chromeos::ErrorPtr* error) {
106 auto command_instance = buffet::CommandInstance::FromJson(
107 &command, commands::attributes::kCommand_Visibility_Local,
108 GetCommandDictionary(), nullptr, error);
109 if (!command_instance)
110 return false;
111
112 UserRole minimal_role =
113 command_instance->GetCommandDefinition()->GetMinimalRole();
114 if (role < minimal_role) {
115 chromeos::Error::AddToPrintf(
116 error, FROM_HERE, errors::commands::kDomain, "access_denied",
117 "User role '%s' less than minimal: '%s'", ToString(role).c_str(),
118 ToString(minimal_role).c_str());
119 return false;
120 }
121
122 *id = std::to_string(++next_command_id_);
123 command_instance->SetID(*id);
124 AddCommand(std::move(command_instance));
125 return true;
126}
127
Anton Muhin5191e812014-10-30 17:49:48 +0400128CommandInstance* CommandManager::FindCommand(const std::string& id) const {
129 return command_queue_.Find(id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700130}
131
Alex Vakulenkoe03af6d2015-04-20 11:00:54 -0700132bool CommandManager::SetCommandVisibility(
133 const std::vector<std::string>& command_names,
134 CommandDefinition::Visibility visibility,
135 chromeos::ErrorPtr* error) {
136 if (command_names.empty())
137 return true;
138
139 std::vector<CommandDefinition*> definitions;
140 definitions.reserve(command_names.size());
141
142 // Find/validate command definitions first.
143 for (const std::string& name : command_names) {
144 CommandDefinition* def = dictionary_.FindCommand(name);
145 if (!def) {
146 chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
147 errors::commands::kInvalidCommandName,
148 "Command '%s' is unknown", name.c_str());
149 return false;
150 }
151 definitions.push_back(def);
152 }
153
154 // Now that we know that all the command names were valid,
155 // update the respective commands' visibility.
Vitaly Buka5e6ff6c2015-05-11 15:41:33 -0700156 for (CommandDefinition* def : definitions)
Alex Vakulenkoe03af6d2015-04-20 11:00:54 -0700157 def->SetVisibility(visibility);
Vitaly Buka5e6ff6c2015-05-11 15:41:33 -0700158 for (const auto& cb : on_command_changed_)
159 cb.Run();
Alex Vakulenkoe03af6d2015-04-20 11:00:54 -0700160 return true;
161}
162
Vitaly Buka72410b22015-05-13 13:48:59 -0700163void CommandManager::AddOnCommandAddedCallback(
164 const CommandQueue::Callback& callback) {
165 command_queue_.AddOnCommandAddedCallback(callback);
166}
167
168void CommandManager::AddOnCommandRemovedCallback(
169 const CommandQueue::Callback& callback) {
170 command_queue_.AddOnCommandRemovedCallback(callback);
171}
172
Alex Vakulenko7c36b672014-07-16 14:50:58 -0700173} // namespace buffet