blob: 72f83386b98ccd6e15b2c6698338ff9520660c9b [file] [log] [blame]
Christopher Wiley583d64b2015-03-24 14:30:17 -07001// Copyright 2015 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/buffet_config.h"
6
Vitaly Bukab56872f2015-06-21 18:39:34 -07007#include <set>
8
Alex Vakulenkof0281742015-05-18 14:31:10 -07009#include <base/files/file_util.h>
Christopher Wiley34eae042015-03-18 10:25:08 -070010#include <base/logging.h>
11#include <base/strings/string_number_conversions.h>
Vitaly Bukab56872f2015-06-21 18:39:34 -070012#include <chromeos/strings/string_utils.h>
Christopher Wiley34eae042015-03-18 10:25:08 -070013
Vitaly Bukaee7a3af2015-05-14 16:57:23 -070014#include "buffet/storage_impls.h"
15#include "buffet/storage_interface.h"
16
Vitaly Buka867b0882015-04-16 10:03:26 -070017namespace {
18
19// TODO(vitalybuka): Remove this when deviceKind is gone from server.
20std::string GetDeviceKind(const std::string& manifest_id) {
21 CHECK_EQ(5u, manifest_id.size());
22 std::string kind = manifest_id.substr(0, 2);
23 if (kind == "AC")
24 return "accessPoint";
25 if (kind == "AK")
26 return "aggregator";
27 if (kind == "AM")
28 return "camera";
29 if (kind == "AB")
30 return "developmentBoard";
31 if (kind == "AE")
32 return "printer";
33 if (kind == "AF")
34 return "scanner";
35 if (kind == "AD")
36 return "speaker";
37 if (kind == "AL")
38 return "storage";
39 if (kind == "AJ")
40 return "toy";
41 if (kind == "AA")
42 return "vendor";
43 if (kind == "AN")
44 return "video";
45 LOG(FATAL) << "Invalid model id: " << manifest_id;
46 return std::string();
47}
48
Vitaly Buka2c1029f2015-04-30 22:47:18 -070049bool IsValidAccessRole(const std::string& role) {
Vitaly Buka94675202015-05-13 11:48:54 -070050 return role == "none" || role == "viewer" || role == "user";
Vitaly Buka2c1029f2015-04-30 22:47:18 -070051}
52
Vitaly Buka2c4178e2015-06-22 16:01:58 -070053bool StringToTimeDelta(const std::string& value, base::TimeDelta* delta) {
54 uint64_t ms{0};
55 if (!base::StringToUint64(value, &ms))
56 return false;
57 *delta = base::TimeDelta::FromMilliseconds(ms);
58 return true;
59}
60
Vitaly Buka867b0882015-04-16 10:03:26 -070061} // namespace
62
Christopher Wiley583d64b2015-03-24 14:30:17 -070063namespace buffet {
Vitaly Buka867b0882015-04-16 10:03:26 -070064
Christopher Wiley583d64b2015-03-24 14:30:17 -070065namespace config_keys {
66
Vitaly Buka867b0882015-04-16 10:03:26 -070067const char kClientId[] = "client_id";
68const char kClientSecret[] = "client_secret";
69const char kApiKey[] = "api_key";
70const char kOAuthURL[] = "oauth_url";
71const char kServiceURL[] = "service_url";
72const char kName[] = "name";
73const char kDescription[] = "description";
74const char kLocation[] = "location";
Vitaly Buka4a3a9a22015-05-13 16:06:01 -070075const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role";
76const char kLocalDiscoveryEnabled[] = "local_discovery_enabled";
77const char kLocalPairingEnabled[] = "local_pairing_enabled";
Vitaly Buka867b0882015-04-16 10:03:26 -070078const char kOemName[] = "oem_name";
79const char kModelName[] = "model_name";
80const char kModelId[] = "model_id";
Vitaly Buka2c1029f2015-04-30 22:47:18 -070081const char kPollingPeriodMs[] = "polling_period_ms";
Alex Vakulenkod05725f2015-05-27 15:48:19 -070082const char kBackupPollingPeriodMs[] = "backup_polling_period_ms";
Vitaly Bukaee7a3af2015-05-14 16:57:23 -070083const char kRefreshToken[] = "refresh_token";
84const char kDeviceId[] = "device_id";
85const char kRobotAccount[] = "robot_account";
Vitaly Bukab56872f2015-06-21 18:39:34 -070086const char kWifiAutoSetupEnabled[] = "wifi_auto_setup_enabled";
87const char kEmbeddedCodePath[] = "embedded_code_path";
88const char kPairingModes[] = "pairing_modes";
89const char kLastConfiguredSsid[] = "last_configured_ssid";
Christopher Wiley583d64b2015-03-24 14:30:17 -070090
91} // namespace config_keys
92
Vitaly Bukaee7a3af2015-05-14 16:57:23 -070093BuffetConfig::BuffetConfig(std::unique_ptr<StorageInterface> storage)
94 : storage_{std::move(storage)} {
95}
96
97BuffetConfig::BuffetConfig(const base::FilePath& state_path)
98 : BuffetConfig{
99 std::unique_ptr<StorageInterface>{new FileStorage{state_path}}} {
100}
101
Christopher Wiley583d64b2015-03-24 14:30:17 -0700102void BuffetConfig::Load(const base::FilePath& config_path) {
103 chromeos::KeyValueStore store;
Alex Vakulenkof0281742015-05-18 14:31:10 -0700104 if (base::PathExists(config_path)) {
105 CHECK(store.Load(config_path)) << "Unable to read or parse config file at"
106 << config_path.value();
Christopher Wiley583d64b2015-03-24 14:30:17 -0700107 }
Alex Vakulenkof0281742015-05-18 14:31:10 -0700108 Load(store);
Christopher Wiley583d64b2015-03-24 14:30:17 -0700109}
110
111void BuffetConfig::Load(const chromeos::KeyValueStore& store) {
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700112 Transaction change{this};
113 change.save_ = false;
114
Christopher Wiley583d64b2015-03-24 14:30:17 -0700115 store.GetString(config_keys::kClientId, &client_id_);
Vitaly Buka867b0882015-04-16 10:03:26 -0700116 CHECK(!client_id_.empty());
117
Christopher Wiley583d64b2015-03-24 14:30:17 -0700118 store.GetString(config_keys::kClientSecret, &client_secret_);
Vitaly Buka867b0882015-04-16 10:03:26 -0700119 CHECK(!client_secret_.empty());
120
Christopher Wiley583d64b2015-03-24 14:30:17 -0700121 store.GetString(config_keys::kApiKey, &api_key_);
Vitaly Buka867b0882015-04-16 10:03:26 -0700122 CHECK(!api_key_.empty());
123
Christopher Wiley583d64b2015-03-24 14:30:17 -0700124 store.GetString(config_keys::kOAuthURL, &oauth_url_);
Vitaly Buka867b0882015-04-16 10:03:26 -0700125 CHECK(!oauth_url_.empty());
126
Christopher Wiley583d64b2015-03-24 14:30:17 -0700127 store.GetString(config_keys::kServiceURL, &service_url_);
Vitaly Buka867b0882015-04-16 10:03:26 -0700128 CHECK(!service_url_.empty());
129
130 store.GetString(config_keys::kOemName, &oem_name_);
131 CHECK(!oem_name_.empty());
132
133 store.GetString(config_keys::kModelName, &model_name_);
134 CHECK(!model_name_.empty());
135
Christopher Wiley583d64b2015-03-24 14:30:17 -0700136 store.GetString(config_keys::kModelId, &model_id_);
Vitaly Buka867b0882015-04-16 10:03:26 -0700137 device_kind_ = GetDeviceKind(model_id_);
138
Christopher Wiley34eae042015-03-18 10:25:08 -0700139 std::string polling_period_str;
Vitaly Buka867b0882015-04-16 10:03:26 -0700140 if (store.GetString(config_keys::kPollingPeriodMs, &polling_period_str))
Vitaly Buka2c4178e2015-06-22 16:01:58 -0700141 CHECK(StringToTimeDelta(polling_period_str, &polling_period_));
Vitaly Buka867b0882015-04-16 10:03:26 -0700142
Alex Vakulenkod05725f2015-05-27 15:48:19 -0700143 if (store.GetString(config_keys::kBackupPollingPeriodMs, &polling_period_str))
Vitaly Buka2c4178e2015-06-22 16:01:58 -0700144 CHECK(StringToTimeDelta(polling_period_str, &backup_polling_period_));
Alex Vakulenkod05725f2015-05-27 15:48:19 -0700145
Vitaly Bukab56872f2015-06-21 18:39:34 -0700146 store.GetBoolean(config_keys::kWifiAutoSetupEnabled,
147 &wifi_auto_setup_enabled_);
148
149 std::string embedded_code_path;
150 if (store.GetString(config_keys::kEmbeddedCodePath, &embedded_code_path)) {
151 embedded_code_path_ = base::FilePath(embedded_code_path);
152 if (!embedded_code_path_.empty())
153 pairing_modes_ = {privetd::PairingType::kEmbeddedCode};
154 }
155
156 std::string modes_str;
157 if (store.GetString(config_keys::kPairingModes, &modes_str)) {
158 std::set<privetd::PairingType> pairing_modes;
159 for (const std::string& mode :
160 chromeos::string_utils::Split(modes_str, ",", true, true)) {
161 privetd::PairingType pairing_mode;
162 CHECK(privetd::StringToPairingType(mode, &pairing_mode));
163 pairing_modes.insert(pairing_mode);
164 }
165 pairing_modes_ = std::move(pairing_modes);
166 }
167
Vitaly Buka798a0e72015-06-02 15:37:51 -0700168 // Empty name set by user or server is allowed, still we expect some
169 // meaningfull config value.
Vitaly Buka867b0882015-04-16 10:03:26 -0700170 store.GetString(config_keys::kName, &name_);
171 CHECK(!name_.empty());
172
173 store.GetString(config_keys::kDescription, &description_);
174 store.GetString(config_keys::kLocation, &location_);
Vitaly Buka2c1029f2015-04-30 22:47:18 -0700175
Vitaly Buka4a3a9a22015-05-13 16:06:01 -0700176 store.GetString(config_keys::kLocalAnonymousAccessRole,
177 &local_anonymous_access_role_);
178 CHECK(IsValidAccessRole(local_anonymous_access_role_))
179 << "Invalid role: " << local_anonymous_access_role_;
180
181 store.GetBoolean(config_keys::kLocalDiscoveryEnabled,
182 &local_discovery_enabled_);
183 store.GetBoolean(config_keys::kLocalPairingEnabled, &local_pairing_enabled_);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700184
185 change.LoadState();
Vitaly Buka867b0882015-04-16 10:03:26 -0700186}
187
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700188void BuffetConfig::Transaction::LoadState() {
189 if (!config_->storage_)
190 return;
191 auto value = config_->storage_->Load();
192 const base::DictionaryValue* dict = nullptr;
193 if (!value || !value->GetAsDictionary(&dict))
194 return;
195
Vitaly Bukaff81db62015-05-14 21:25:45 -0700196 std::string tmp;
197 bool tmp_bool{false};
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700198
Vitaly Bukaff81db62015-05-14 21:25:45 -0700199 if (dict->GetString(config_keys::kClientId, &tmp))
200 set_client_id(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700201
Vitaly Bukaff81db62015-05-14 21:25:45 -0700202 if (dict->GetString(config_keys::kClientSecret, &tmp))
203 set_client_secret(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700204
Vitaly Bukaff81db62015-05-14 21:25:45 -0700205 if (dict->GetString(config_keys::kApiKey, &tmp))
206 set_api_key(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700207
Vitaly Bukaff81db62015-05-14 21:25:45 -0700208 if (dict->GetString(config_keys::kOAuthURL, &tmp))
209 set_oauth_url(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700210
Vitaly Bukaff81db62015-05-14 21:25:45 -0700211 if (dict->GetString(config_keys::kServiceURL, &tmp))
212 set_service_url(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700213
Vitaly Bukaff81db62015-05-14 21:25:45 -0700214 if (dict->GetString(config_keys::kName, &tmp))
215 set_name(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700216
Vitaly Bukaff81db62015-05-14 21:25:45 -0700217 if (dict->GetString(config_keys::kDescription, &tmp))
218 set_description(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700219
Vitaly Bukaff81db62015-05-14 21:25:45 -0700220 if (dict->GetString(config_keys::kLocation, &tmp))
221 set_location(tmp);
222
223 if (dict->GetString(config_keys::kLocalAnonymousAccessRole, &tmp))
224 set_local_anonymous_access_role(tmp);
225
226 if (dict->GetBoolean(config_keys::kLocalDiscoveryEnabled, &tmp_bool))
227 set_local_discovery_enabled(tmp_bool);
228
229 if (dict->GetBoolean(config_keys::kLocalPairingEnabled, &tmp_bool))
230 set_local_pairing_enabled(tmp_bool);
231
232 if (dict->GetString(config_keys::kRefreshToken, &tmp))
233 set_refresh_token(tmp);
234
235 if (dict->GetString(config_keys::kRobotAccount, &tmp))
236 set_robot_account(tmp);
237
Vitaly Bukab56872f2015-06-21 18:39:34 -0700238 if (dict->GetString(config_keys::kLastConfiguredSsid, &tmp))
239 set_last_configured_ssid(tmp);
240
Vitaly Bukaff81db62015-05-14 21:25:45 -0700241 if (dict->GetString(config_keys::kDeviceId, &tmp))
242 set_device_id(tmp);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700243}
244
245bool BuffetConfig::Save() {
246 if (!storage_)
247 return false;
248 base::DictionaryValue dict;
Vitaly Bukaff81db62015-05-14 21:25:45 -0700249 dict.SetString(config_keys::kClientId, client_id_);
250 dict.SetString(config_keys::kClientSecret, client_secret_);
251 dict.SetString(config_keys::kApiKey, api_key_);
252 dict.SetString(config_keys::kOAuthURL, oauth_url_);
253 dict.SetString(config_keys::kServiceURL, service_url_);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700254 dict.SetString(config_keys::kRefreshToken, refresh_token_);
255 dict.SetString(config_keys::kDeviceId, device_id_);
256 dict.SetString(config_keys::kRobotAccount, robot_account_);
Vitaly Bukab56872f2015-06-21 18:39:34 -0700257 dict.SetString(config_keys::kLastConfiguredSsid, last_configured_ssid_);
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700258 dict.SetString(config_keys::kName, name_);
259 dict.SetString(config_keys::kDescription, description_);
260 dict.SetString(config_keys::kLocation, location_);
261 dict.SetString(config_keys::kLocalAnonymousAccessRole,
262 local_anonymous_access_role_);
263 dict.SetBoolean(config_keys::kLocalDiscoveryEnabled,
264 local_discovery_enabled_);
265 dict.SetBoolean(config_keys::kLocalPairingEnabled, local_pairing_enabled_);
266
267 return storage_->Save(dict);
268}
269
270BuffetConfig::Transaction::~Transaction() {
271 Commit();
272}
273
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700274bool BuffetConfig::Transaction::set_local_anonymous_access_role(
275 const std::string& role) {
Vitaly Buka4a3a9a22015-05-13 16:06:01 -0700276 if (!IsValidAccessRole(role)) {
277 LOG(ERROR) << "Invalid role: " << role;
278 return false;
279 }
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700280 config_->local_anonymous_access_role_ = role;
Vitaly Buka4a3a9a22015-05-13 16:06:01 -0700281 return true;
Vitaly Buka2c1029f2015-04-30 22:47:18 -0700282}
283
Vitaly Bukaee7a3af2015-05-14 16:57:23 -0700284void BuffetConfig::Transaction::Commit() {
285 if (!config_)
286 return;
287 if (save_)
288 config_->Save();
289 for (const auto& cb : config_->on_changed_)
290 cb.Run(*config_);
291 config_ = nullptr;
292}
293
Christopher Wiley583d64b2015-03-24 14:30:17 -0700294} // namespace buffet