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
23namespace weave {
24
25DeviceManager::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
58DeviceManager::~DeviceManager() {}
59
60const Settings& DeviceManager::GetSettings() const {
61  return device_info_->GetSettings();
62}
63
64void DeviceManager::AddSettingsChangedCallback(
65    const SettingsChangedCallback& callback) {
66  device_info_->GetMutableConfig()->AddOnChangedCallback(callback);
67}
68
69Config* DeviceManager::GetConfig() {
70  return device_info_->GetMutableConfig();
71}
72
73void 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
84GcdState DeviceManager::GetGcdState() const {
85  return device_info_->GetGcdState();
86}
87
88void DeviceManager::AddGcdStateChangedCallback(
89    const GcdStateChangedCallback& callback) {
90  device_info_->AddGcdStateChangedCallback(callback);
91}
92
93void DeviceManager::AddTraitDefinitionsFromJson(const std::string& json) {
94  CHECK(component_manager_->LoadTraits(json, nullptr));
95}
96
97void DeviceManager::AddTraitDefinitions(const base::DictionaryValue& dict) {
98  CHECK(component_manager_->LoadTraits(dict, nullptr));
99}
100
101const base::DictionaryValue& DeviceManager::GetTraits() const {
102  return component_manager_->GetTraits();
103}
104
105void DeviceManager::AddTraitDefsChangedCallback(const base::Closure& callback) {
106  component_manager_->AddTraitDefChangedCallback(callback);
107}
108
109bool 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
115bool DeviceManager::RemoveComponent(const std::string& name, ErrorPtr* error) {
116  return component_manager_->RemoveComponent("", name, error);
117}
118
119void DeviceManager::AddComponentTreeChangedCallback(
120    const base::Closure& callback) {
121  component_manager_->AddComponentTreeChangedCallback(callback);
122}
123
124const base::DictionaryValue& DeviceManager::GetComponents() const {
125  return component_manager_->GetComponents();
126}
127
128bool DeviceManager::SetStatePropertiesFromJson(const std::string& component,
129                                               const std::string& json,
130                                               ErrorPtr* error) {
131  return component_manager_->SetStatePropertiesFromJson(component, json, error);
132}
133
134bool DeviceManager::SetStateProperties(const std::string& component,
135                                       const base::DictionaryValue& dict,
136                                       ErrorPtr* error) {
137  return component_manager_->SetStateProperties(component, dict, error);
138}
139
140const 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
146bool 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
153void 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
159void DeviceManager::AddCommandDefinitionsFromJson(const std::string& json) {
160  auto dict = LoadJsonDict(json, nullptr);
161  CHECK(dict);
162  AddCommandDefinitions(*dict);
163}
164
165void DeviceManager::AddCommandDefinitions(const base::DictionaryValue& dict) {
166  CHECK(component_manager_->AddLegacyCommandDefinitions(dict, nullptr));
167}
168
169bool 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
180Command* DeviceManager::FindCommand(const std::string& id) {
181  return component_manager_->FindCommand(id);
182}
183
184void 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
195void DeviceManager::AddStateChangedCallback(const base::Closure& callback) {
196  component_manager_->AddStateChangedCallback(callback);
197}
198
199void DeviceManager::AddStateDefinitionsFromJson(const std::string& json) {
200  auto dict = LoadJsonDict(json, nullptr);
201  CHECK(dict);
202  AddStateDefinitions(*dict);
203}
204
205void DeviceManager::AddStateDefinitions(const base::DictionaryValue& dict) {
206  CHECK(component_manager_->AddLegacyStateDefinitions(dict, nullptr));
207}
208
209bool DeviceManager::SetStatePropertiesFromJson(const std::string& json,
210                                               ErrorPtr* error) {
211  auto dict = LoadJsonDict(json, error);
212  return dict && SetStateProperties(*dict, error);
213}
214
215bool 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
236const 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
245bool 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
261const base::DictionaryValue& DeviceManager::GetState() const {
262  return component_manager_->GetLegacyState();
263}
264
265void DeviceManager::Register(const std::string& ticket_id,
266                             const DoneCallback& callback) {
267  device_info_->RegisterDevice(ticket_id, callback);
268}
269
270void DeviceManager::AddPairingChangedCallbacks(
271    const PairingBeginCallback& begin_callback,
272    const PairingEndCallback& end_callback) {
273  if (privet_)
274    privet_->AddOnPairingChangedCallbacks(begin_callback, end_callback);
275}
276
277std::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