| // Copyright 2015 The Weave Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/commands/command_manager.h" | |
| #include <base/values.h> | |
| #include <weave/enum_to_string.h> | |
| #include <weave/error.h> | |
| #include "src/commands/schema_constants.h" | |
| #include "src/utils.h" | |
| namespace weave { | |
| CommandManager::CommandManager() {} | |
| CommandManager::~CommandManager() {} | |
| void CommandManager::AddCommandDefChanged(const base::Closure& callback) { | |
| on_command_changed_.push_back(callback); | |
| callback.Run(); | |
| } | |
| const CommandDictionary& CommandManager::GetCommandDictionary() const { | |
| return dictionary_; | |
| } | |
| bool CommandManager::LoadCommands(const base::DictionaryValue& dict, | |
| ErrorPtr* error) { | |
| bool result = dictionary_.LoadCommands(dict, nullptr, error); | |
| for (const auto& cb : on_command_changed_) | |
| cb.Run(); | |
| return result; | |
| } | |
| bool CommandManager::LoadCommands(const std::string& json, | |
| ErrorPtr* error) { | |
| std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error); | |
| if (!dict) | |
| return false; | |
| return LoadCommands(*dict, error); | |
| } | |
| void CommandManager::AddCommand( | |
| std::unique_ptr<CommandInstance> command_instance) { | |
| command_queue_.Add(std::move(command_instance)); | |
| } | |
| bool CommandManager::AddCommand(const base::DictionaryValue& command, | |
| std::string* id, | |
| ErrorPtr* error) { | |
| return AddCommand(command, UserRole::kOwner, id, error); | |
| } | |
| bool CommandManager::AddCommand(const base::DictionaryValue& command, | |
| UserRole role, | |
| std::string* id, | |
| ErrorPtr* error) { | |
| auto command_instance = | |
| CommandInstance::FromJson(&command, Command::Origin::kLocal, | |
| GetCommandDictionary(), nullptr, error); | |
| if (!command_instance) | |
| return false; | |
| UserRole minimal_role = | |
| command_instance->GetCommandDefinition()->GetMinimalRole(); | |
| if (role < minimal_role) { | |
| Error::AddToPrintf( | |
| error, FROM_HERE, errors::commands::kDomain, "access_denied", | |
| "User role '%s' less than minimal: '%s'", EnumToString(role).c_str(), | |
| EnumToString(minimal_role).c_str()); | |
| return false; | |
| } | |
| *id = std::to_string(++next_command_id_); | |
| command_instance->SetID(*id); | |
| AddCommand(std::move(command_instance)); | |
| return true; | |
| } | |
| CommandInstance* CommandManager::FindCommand(const std::string& id) { | |
| return command_queue_.Find(id); | |
| } | |
| bool CommandManager::SetCommandVisibility( | |
| const std::vector<std::string>& command_names, | |
| CommandDefinition::Visibility visibility, | |
| 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) { | |
| 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); | |
| for (const auto& cb : on_command_changed_) | |
| cb.Run(); | |
| return true; | |
| } | |
| void CommandManager::AddCommandAddedCallback( | |
| const CommandQueue::CommandCallback& callback) { | |
| command_queue_.AddCommandAddedCallback(callback); | |
| } | |
| void CommandManager::AddCommandRemovedCallback( | |
| const CommandQueue::CommandCallback& callback) { | |
| command_queue_.AddCommandRemovedCallback(callback); | |
| } | |
| void CommandManager::AddCommandHandler( | |
| const std::string& command_name, | |
| const Device::CommandHandlerCallback& callback) { | |
| CHECK(command_name.empty() || dictionary_.FindCommand(command_name)) | |
| << "Command undefined: " << command_name; | |
| command_queue_.AddCommandHandler(command_name, callback); | |
| } | |
| } // namespace weave |