blob: d0743deaecd09d671a1cf1878f20f99a2e886934 [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
102CommandInstance* CommandManager::FindCommand(const std::string& id) const {
103 return command_queue_.Find(id);
Alex Vakulenko95110752014-09-03 16:27:21 -0700104}
105
Alex Vakulenkoe03af6d2015-04-20 11:00:54 -0700106bool CommandManager::SetCommandVisibility(
107 const std::vector<std::string>& command_names,
108 CommandDefinition::Visibility visibility,
109 chromeos::ErrorPtr* error) {
110 if (command_names.empty())
111 return true;
112
113 std::vector<CommandDefinition*> definitions;
114 definitions.reserve(command_names.size());
115
116 // Find/validate command definitions first.
117 for (const std::string& name : command_names) {
118 CommandDefinition* def = dictionary_.FindCommand(name);
119 if (!def) {
120 chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
121 errors::commands::kInvalidCommandName,
122 "Command '%s' is unknown", name.c_str());
123 return false;
124 }
125 definitions.push_back(def);
126 }
127
128 // Now that we know that all the command names were valid,
129 // update the respective commands' visibility.
Vitaly Buka5e6ff6c2015-05-11 15:41:33 -0700130 for (CommandDefinition* def : definitions)
Alex Vakulenkoe03af6d2015-04-20 11:00:54 -0700131 def->SetVisibility(visibility);
Vitaly Buka5e6ff6c2015-05-11 15:41:33 -0700132 for (const auto& cb : on_command_changed_)
133 cb.Run();
Alex Vakulenkoe03af6d2015-04-20 11:00:54 -0700134 return true;
135}
136
Vitaly Buka72410b22015-05-13 13:48:59 -0700137void CommandManager::AddOnCommandAddedCallback(
138 const CommandQueue::Callback& callback) {
139 command_queue_.AddOnCommandAddedCallback(callback);
140}
141
142void CommandManager::AddOnCommandRemovedCallback(
143 const CommandQueue::Callback& callback) {
144 command_queue_.AddOnCommandRemovedCallback(callback);
145}
146
Alex Vakulenko7c36b672014-07-16 14:50:58 -0700147} // namespace buffet