1 // Copyright 2015 The Weave 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 "src/device_manager.h"
6 
7 #include <string>
8 
9 #include <base/bind.h>
10 
11 #include "src/access_api_handler.h"
12 #include "src/access_black_list_manager_impl.h"
13 #include "src/base_api_handler.h"
14 #include "src/commands/schema_constants.h"
15 #include "src/component_manager_impl.h"
16 #include "src/config.h"
17 #include "src/device_registration_info.h"
18 #include "src/privet/auth_manager.h"
19 #include "src/privet/privet_manager.h"
20 #include "src/string_utils.h"
21 #include "src/utils.h"
22 
23 namespace weave {
24 
DeviceManager(provider::ConfigStore * config_store,provider::TaskRunner * task_runner,provider::HttpClient * http_client,provider::Network * network,provider::DnsServiceDiscovery * dns_sd,provider::HttpServer * http_server,provider::Wifi * wifi,provider::Bluetooth * bluetooth)25 DeviceManager::DeviceManager(provider::ConfigStore* config_store,
26                              provider::TaskRunner* task_runner,
27                              provider::HttpClient* http_client,
28                              provider::Network* network,
29                              provider::DnsServiceDiscovery* dns_sd,
30                              provider::HttpServer* http_server,
31                              provider::Wifi* wifi,
32                              provider::Bluetooth* bluetooth)
33     : config_{new Config{config_store}},
34       component_manager_{new ComponentManagerImpl{task_runner}} {
35   if (http_server) {
36     auth_manager_.reset(new privet::AuthManager(
37         config_.get(), http_server->GetHttpsCertificateFingerprint()));
38   }
39 
40   device_info_.reset(new DeviceRegistrationInfo(
41       config_.get(), component_manager_.get(), task_runner, http_client,
42       network, auth_manager_.get()));
43   base_api_handler_.reset(new BaseApiHandler{device_info_.get(), this});
44 
45   black_list_manager_.reset(new AccessBlackListManagerImpl{config_store});
46   access_api_handler_.reset(
47       new AccessApiHandler{this, black_list_manager_.get()});
48 
49   device_info_->Start();
50 
51   if (http_server) {
52     StartPrivet(task_runner, network, dns_sd, http_server, wifi, bluetooth);
53   } else {
54     CHECK(!dns_sd);
55   }
56 }
57 
~DeviceManager()58 DeviceManager::~DeviceManager() {}
59 
GetSettings() const60 const Settings& DeviceManager::GetSettings() const {
61   return device_info_->GetSettings();
62 }
63 
AddSettingsChangedCallback(const SettingsChangedCallback & callback)64 void DeviceManager::AddSettingsChangedCallback(
65     const SettingsChangedCallback& callback) {
66   device_info_->GetMutableConfig()->AddOnChangedCallback(callback);
67 }
68 
GetConfig()69 Config* DeviceManager::GetConfig() {
70   return device_info_->GetMutableConfig();
71 }
72 
StartPrivet(provider::TaskRunner * task_runner,provider::Network * network,provider::DnsServiceDiscovery * dns_sd,provider::HttpServer * http_server,provider::Wifi * wifi,provider::Bluetooth * bluetooth)73 void DeviceManager::StartPrivet(provider::TaskRunner* task_runner,
74                                 provider::Network* network,
75                                 provider::DnsServiceDiscovery* dns_sd,
76                                 provider::HttpServer* http_server,
77                                 provider::Wifi* wifi,
78                                 provider::Bluetooth* bluetooth) {
79   privet_.reset(new privet::Manager{task_runner});
80   privet_->Start(network, dns_sd, http_server, wifi, auth_manager_.get(),
81                  device_info_.get(), component_manager_.get());
82 }
83 
GetGcdState() const84 GcdState DeviceManager::GetGcdState() const {
85   return device_info_->GetGcdState();
86 }
87 
AddGcdStateChangedCallback(const GcdStateChangedCallback & callback)88 void DeviceManager::AddGcdStateChangedCallback(
89     const GcdStateChangedCallback& callback) {
90   device_info_->AddGcdStateChangedCallback(callback);
91 }
92 
AddTraitDefinitionsFromJson(const std::string & json)93 void DeviceManager::AddTraitDefinitionsFromJson(const std::string& json) {
94   CHECK(component_manager_->LoadTraits(json, nullptr));
95 }
96 
AddTraitDefinitions(const base::DictionaryValue & dict)97 void DeviceManager::AddTraitDefinitions(const base::DictionaryValue& dict) {
98   CHECK(component_manager_->LoadTraits(dict, nullptr));
99 }
100 
GetTraits() const101 const base::DictionaryValue& DeviceManager::GetTraits() const {
102   return component_manager_->GetTraits();
103 }
104 
AddTraitDefsChangedCallback(const base::Closure & callback)105 void DeviceManager::AddTraitDefsChangedCallback(const base::Closure& callback) {
106   component_manager_->AddTraitDefChangedCallback(callback);
107 }
108 
AddComponent(const std::string & name,const std::vector<std::string> & traits,ErrorPtr * error)109 bool DeviceManager::AddComponent(const std::string& name,
110                                  const std::vector<std::string>& traits,
111                                  ErrorPtr* error) {
112   return component_manager_->AddComponent("", name, traits, error);
113 }
114 
RemoveComponent(const std::string & name,ErrorPtr * error)115 bool DeviceManager::RemoveComponent(const std::string& name, ErrorPtr* error) {
116   return component_manager_->RemoveComponent("", name, error);
117 }
118 
AddComponentTreeChangedCallback(const base::Closure & callback)119 void DeviceManager::AddComponentTreeChangedCallback(
120     const base::Closure& callback) {
121   component_manager_->AddComponentTreeChangedCallback(callback);
122 }
123 
GetComponents() const124 const base::DictionaryValue& DeviceManager::GetComponents() const {
125   return component_manager_->GetComponents();
126 }
127 
SetStatePropertiesFromJson(const std::string & component,const std::string & json,ErrorPtr * error)128 bool DeviceManager::SetStatePropertiesFromJson(const std::string& component,
129                                                const std::string& json,
130                                                ErrorPtr* error) {
131   return component_manager_->SetStatePropertiesFromJson(component, json, error);
132 }
133 
SetStateProperties(const std::string & component,const base::DictionaryValue & dict,ErrorPtr * error)134 bool DeviceManager::SetStateProperties(const std::string& component,
135                                        const base::DictionaryValue& dict,
136                                        ErrorPtr* error) {
137   return component_manager_->SetStateProperties(component, dict, error);
138 }
139 
GetStateProperty(const std::string & component,const std::string & name,ErrorPtr * error) const140 const base::Value* DeviceManager::GetStateProperty(const std::string& component,
141                                                    const std::string& name,
142                                                    ErrorPtr* error) const {
143   return component_manager_->GetStateProperty(component, name, error);
144 }
145 
SetStateProperty(const std::string & component,const std::string & name,const base::Value & value,ErrorPtr * error)146 bool DeviceManager::SetStateProperty(const std::string& component,
147                                      const std::string& name,
148                                      const base::Value& value,
149                                      ErrorPtr* error) {
150   return component_manager_->SetStateProperty(component, name, value, error);
151 }
152 
AddCommandHandler(const std::string & component,const std::string & command_name,const CommandHandlerCallback & callback)153 void DeviceManager::AddCommandHandler(const std::string& component,
154                                       const std::string& command_name,
155                                       const CommandHandlerCallback& callback) {
156   component_manager_->AddCommandHandler(component, command_name, callback);
157 }
158 
AddCommandDefinitionsFromJson(const std::string & json)159 void DeviceManager::AddCommandDefinitionsFromJson(const std::string& json) {
160   auto dict = LoadJsonDict(json, nullptr);
161   CHECK(dict);
162   AddCommandDefinitions(*dict);
163 }
164 
AddCommandDefinitions(const base::DictionaryValue & dict)165 void DeviceManager::AddCommandDefinitions(const base::DictionaryValue& dict) {
166   CHECK(component_manager_->AddLegacyCommandDefinitions(dict, nullptr));
167 }
168 
AddCommand(const base::DictionaryValue & command,std::string * id,ErrorPtr * error)169 bool DeviceManager::AddCommand(const base::DictionaryValue& command,
170                                std::string* id,
171                                ErrorPtr* error) {
172   auto command_instance = component_manager_->ParseCommandInstance(
173       command, Command::Origin::kLocal, UserRole::kOwner, id, error);
174   if (!command_instance)
175     return false;
176   component_manager_->AddCommand(std::move(command_instance));
177   return true;
178 }
179 
FindCommand(const std::string & id)180 Command* DeviceManager::FindCommand(const std::string& id) {
181   return component_manager_->FindCommand(id);
182 }
183 
AddCommandHandler(const std::string & command_name,const CommandHandlerCallback & callback)184 void DeviceManager::AddCommandHandler(const std::string& command_name,
185                                       const CommandHandlerCallback& callback) {
186   if (command_name.empty())
187     return component_manager_->AddCommandHandler("", "", callback);
188 
189   auto trait = SplitAtFirst(command_name, ".", true).first;
190   std::string component = component_manager_->FindComponentWithTrait(trait);
191   CHECK(!component.empty());
192   component_manager_->AddCommandHandler(component, command_name, callback);
193 }
194 
AddStateChangedCallback(const base::Closure & callback)195 void DeviceManager::AddStateChangedCallback(const base::Closure& callback) {
196   component_manager_->AddStateChangedCallback(callback);
197 }
198 
AddStateDefinitionsFromJson(const std::string & json)199 void DeviceManager::AddStateDefinitionsFromJson(const std::string& json) {
200   auto dict = LoadJsonDict(json, nullptr);
201   CHECK(dict);
202   AddStateDefinitions(*dict);
203 }
204 
AddStateDefinitions(const base::DictionaryValue & dict)205 void DeviceManager::AddStateDefinitions(const base::DictionaryValue& dict) {
206   CHECK(component_manager_->AddLegacyStateDefinitions(dict, nullptr));
207 }
208 
SetStatePropertiesFromJson(const std::string & json,ErrorPtr * error)209 bool DeviceManager::SetStatePropertiesFromJson(const std::string& json,
210                                                ErrorPtr* error) {
211   auto dict = LoadJsonDict(json, error);
212   return dict && SetStateProperties(*dict, error);
213 }
214 
SetStateProperties(const base::DictionaryValue & dict,ErrorPtr * error)215 bool DeviceManager::SetStateProperties(const base::DictionaryValue& dict,
216                                        ErrorPtr* error) {
217   for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
218     std::string component =
219         component_manager_->FindComponentWithTrait(it.key());
220     if (component.empty()) {
221       Error::AddToPrintf(error, FROM_HERE, "unrouted_state",
222                          "Unable to set property value because there is no "
223                          "component supporting "
224                          "trait '%s'",
225                          it.key().c_str());
226       return false;
227     }
228     base::DictionaryValue trait_state;
229     trait_state.Set(it.key(), it.value().DeepCopy());
230     if (!component_manager_->SetStateProperties(component, trait_state, error))
231       return false;
232   }
233   return true;
234 }
235 
GetStateProperty(const std::string & name) const236 const base::Value* DeviceManager::GetStateProperty(
237     const std::string& name) const {
238   auto trait = SplitAtFirst(name, ".", true).first;
239   std::string component = component_manager_->FindComponentWithTrait(trait);
240   if (component.empty())
241     return nullptr;
242   return component_manager_->GetStateProperty(component, name, nullptr);
243 }
244 
SetStateProperty(const std::string & name,const base::Value & value,ErrorPtr * error)245 bool DeviceManager::SetStateProperty(const std::string& name,
246                                      const base::Value& value,
247                                      ErrorPtr* error) {
248   auto trait = SplitAtFirst(name, ".", true).first;
249   std::string component = component_manager_->FindComponentWithTrait(trait);
250   if (component.empty()) {
251     Error::AddToPrintf(
252         error, FROM_HERE, "unrouted_state",
253         "Unable set value of state property '%s' because there is no component "
254         "supporting trait '%s'",
255         name.c_str(), trait.c_str());
256     return false;
257   }
258   return component_manager_->SetStateProperty(component, name, value, error);
259 }
260 
GetState() const261 const base::DictionaryValue& DeviceManager::GetState() const {
262   return component_manager_->GetLegacyState();
263 }
264 
Register(const std::string & ticket_id,const DoneCallback & callback)265 void DeviceManager::Register(const std::string& ticket_id,
266                              const DoneCallback& callback) {
267   device_info_->RegisterDevice(ticket_id, callback);
268 }
269 
AddPairingChangedCallbacks(const PairingBeginCallback & begin_callback,const PairingEndCallback & end_callback)270 void DeviceManager::AddPairingChangedCallbacks(
271     const PairingBeginCallback& begin_callback,
272     const PairingEndCallback& end_callback) {
273   if (privet_)
274     privet_->AddOnPairingChangedCallbacks(begin_callback, end_callback);
275 }
276 
Create(provider::ConfigStore * config_store,provider::TaskRunner * task_runner,provider::HttpClient * http_client,provider::Network * network,provider::DnsServiceDiscovery * dns_sd,provider::HttpServer * http_server,provider::Wifi * wifi,provider::Bluetooth * bluetooth)277 std::unique_ptr<Device> Device::Create(provider::ConfigStore* config_store,
278                                        provider::TaskRunner* task_runner,
279                                        provider::HttpClient* http_client,
280                                        provider::Network* network,
281                                        provider::DnsServiceDiscovery* dns_sd,
282                                        provider::HttpServer* http_server,
283                                        provider::Wifi* wifi,
284                                        provider::Bluetooth* bluetooth) {
285   return std::unique_ptr<Device>{
286       new DeviceManager{config_store, task_runner, http_client, network, dns_sd,
287                         http_server, wifi, bluetooth}};
288 }
289 
290 }  // namespace weave
291