blob: 9a18bb0baa754635cdd21480e1e8a565e086de82 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Bukad322a3c2015-08-16 01:03:02 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/config.h"
Vitaly Bukad322a3c2015-08-16 01:03:02 -07006
7#include <set>
8
Vitaly Bukac11a17d2015-08-15 10:36:10 -07009#include <base/bind.h>
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070010#include <base/guid.h>
Vitaly Bukac11a17d2015-08-15 10:36:10 -070011#include <base/json/json_reader.h>
12#include <base/json/json_writer.h>
Vitaly Bukad322a3c2015-08-16 01:03:02 -070013#include <base/logging.h>
14#include <base/strings/string_number_conversions.h>
Vitaly Bukac11a17d2015-08-15 10:36:10 -070015#include <base/values.h>
Vitaly Bukad322a3c2015-08-16 01:03:02 -070016#include <weave/enum_to_string.h>
17
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020018#include "src/privet/privet_types.h"
19#include "src/string_utils.h"
Vitaly Bukad322a3c2015-08-16 01:03:02 -070020
Vitaly Bukad322a3c2015-08-16 01:03:02 -070021namespace weave {
22
23namespace config_keys {
24
Vitaly Bukabced5af2015-10-12 17:42:30 -070025const char kVersion[] = "version";
26
Vitaly Bukad322a3c2015-08-16 01:03:02 -070027const char kClientId[] = "client_id";
28const char kClientSecret[] = "client_secret";
29const char kApiKey[] = "api_key";
30const char kOAuthURL[] = "oauth_url";
31const char kServiceURL[] = "service_url";
32const char kName[] = "name";
33const char kDescription[] = "description";
34const char kLocation[] = "location";
35const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role";
36const char kLocalDiscoveryEnabled[] = "local_discovery_enabled";
37const char kLocalPairingEnabled[] = "local_pairing_enabled";
Vitaly Bukad322a3c2015-08-16 01:03:02 -070038const char kRefreshToken[] = "refresh_token";
Johan Euphrosine312c2f52015-09-29 00:04:29 -070039const char kCloudId[] = "cloud_id";
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070040const char kDeviceId[] = "device_id";
Vitaly Bukad322a3c2015-08-16 01:03:02 -070041const char kRobotAccount[] = "robot_account";
Vitaly Bukad322a3c2015-08-16 01:03:02 -070042const char kLastConfiguredSsid[] = "last_configured_ssid";
Vitaly Buka8589b052015-09-29 00:46:14 -070043const char kSecret[] = "secret";
Vitaly Bukad322a3c2015-08-16 01:03:02 -070044
45} // namespace config_keys
46
Vitaly Bukac11a17d2015-08-15 10:36:10 -070047namespace {
48
Vitaly Bukabced5af2015-10-12 17:42:30 -070049const int kCurrentConfigVersion = 1;
50
51void MigrateFromV0(base::DictionaryValue* dict) {
52 std::string cloud_id;
53 if (dict->GetString(config_keys::kCloudId, &cloud_id) && !cloud_id.empty())
54 return;
55 scoped_ptr<base::Value> tmp;
56 if (dict->Remove(config_keys::kDeviceId, &tmp))
57 dict->Set(config_keys::kCloudId, std::move(tmp));
58}
59
Vitaly Buka238db692015-09-29 16:58:39 -070060Config::Settings CreateDefaultSettings() {
61 Config::Settings result;
Vitaly Bukad322a3c2015-08-16 01:03:02 -070062 result.oauth_url = "https://accounts.google.com/o/oauth2/";
63 result.service_url = "https://www.googleapis.com/clouddevices/v1/";
Vitaly Bukab624bc42015-09-29 19:13:55 -070064 result.local_anonymous_access_role = AuthScope::kViewer;
Vitaly Bukad322a3c2015-08-16 01:03:02 -070065 result.pairing_modes.emplace(PairingType::kPinCode);
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070066 result.device_id = base::GenerateGUID();
Vitaly Bukad322a3c2015-08-16 01:03:02 -070067 return result;
68}
69
Vitaly Bukac11a17d2015-08-15 10:36:10 -070070} // namespace
Vitaly Bukad322a3c2015-08-16 01:03:02 -070071
Vitaly Buka1e363672015-09-25 14:01:16 -070072Config::Config(provider::ConfigStore* config_store)
Vitaly Bukac11a17d2015-08-15 10:36:10 -070073 : settings_{CreateDefaultSettings()}, config_store_{config_store} {
Vitaly Bukac11a17d2015-08-15 10:36:10 -070074}
Vitaly Bukad322a3c2015-08-16 01:03:02 -070075
76void Config::AddOnChangedCallback(const OnChangedCallback& callback) {
77 on_changed_.push_back(callback);
78 // Force to read current state.
79 callback.Run(settings_);
80}
81
Vitaly Buka238db692015-09-29 16:58:39 -070082const Config::Settings& Config::GetSettings() const {
Vitaly Bukad322a3c2015-08-16 01:03:02 -070083 return settings_;
84}
85
Vitaly Bukac11a17d2015-08-15 10:36:10 -070086void Config::Load() {
Vitaly Bukad322a3c2015-08-16 01:03:02 -070087 Transaction change{this};
88 change.save_ = false;
89
Vitaly Bukac11a17d2015-08-15 10:36:10 -070090 settings_ = CreateDefaultSettings();
91
92 if (!config_store_)
93 return;
94
95 // Crash on any mistakes in defaults.
96 CHECK(config_store_->LoadDefaults(&settings_));
97
Vitaly Bukad322a3c2015-08-16 01:03:02 -070098 CHECK(!settings_.client_id.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -070099 CHECK(!settings_.client_secret.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700100 CHECK(!settings_.api_key.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700101 CHECK(!settings_.oauth_url.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700102 CHECK(!settings_.service_url.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700103 CHECK(!settings_.oem_name.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700104 CHECK(!settings_.model_name.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700105 CHECK(!settings_.model_id.empty());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700106 CHECK(!settings_.name.empty());
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700107 CHECK(!settings_.device_id.empty());
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700108 CHECK_EQ(
109 settings_.embedded_code.empty(),
110 std::find(settings_.pairing_modes.begin(), settings_.pairing_modes.end(),
111 PairingType::kEmbeddedCode) == settings_.pairing_modes.end());
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700112
Vitaly Buka8589b052015-09-29 00:46:14 -0700113 // Values below will be generated at runtime.
114 CHECK(settings_.cloud_id.empty());
115 CHECK(settings_.refresh_token.empty());
116 CHECK(settings_.robot_account.empty());
117 CHECK(settings_.last_configured_ssid.empty());
118 CHECK(settings_.secret.empty());
119
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700120 change.LoadState();
121}
122
123void Config::Transaction::LoadState() {
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700124 if (!config_->config_store_)
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700125 return;
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700126 std::string json_string = config_->config_store_->LoadSettings();
127 if (json_string.empty())
128 return;
129
130 auto value = base::JSONReader::Read(json_string);
Vitaly Bukabced5af2015-10-12 17:42:30 -0700131 base::DictionaryValue* dict = nullptr;
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700132 if (!value || !value->GetAsDictionary(&dict)) {
133 LOG(ERROR) << "Failed to parse settings.";
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700134 return;
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700135 }
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700136
Vitaly Bukabced5af2015-10-12 17:42:30 -0700137 int loaded_version = 0;
138 dict->GetInteger(config_keys::kVersion, &loaded_version);
139
140 if (loaded_version != kCurrentConfigVersion) {
141 LOG(INFO) << "State version mismatch. expected: " << kCurrentConfigVersion
142 << ", loaded: " << loaded_version;
143 save_ = true;
144 }
145
146 if (loaded_version == 0) {
147 MigrateFromV0(dict);
148 }
149
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700150 std::string tmp;
151 bool tmp_bool{false};
152
153 if (dict->GetString(config_keys::kClientId, &tmp))
154 set_client_id(tmp);
155
156 if (dict->GetString(config_keys::kClientSecret, &tmp))
157 set_client_secret(tmp);
158
159 if (dict->GetString(config_keys::kApiKey, &tmp))
160 set_api_key(tmp);
161
162 if (dict->GetString(config_keys::kOAuthURL, &tmp))
163 set_oauth_url(tmp);
164
165 if (dict->GetString(config_keys::kServiceURL, &tmp))
166 set_service_url(tmp);
167
168 if (dict->GetString(config_keys::kName, &tmp))
169 set_name(tmp);
170
171 if (dict->GetString(config_keys::kDescription, &tmp))
172 set_description(tmp);
173
174 if (dict->GetString(config_keys::kLocation, &tmp))
175 set_location(tmp);
176
Vitaly Bukab624bc42015-09-29 19:13:55 -0700177 AuthScope scope{AuthScope::kNone};
178 if (dict->GetString(config_keys::kLocalAnonymousAccessRole, &tmp) &&
179 StringToEnum(tmp, &scope)) {
180 set_local_anonymous_access_role(scope);
181 }
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700182
183 if (dict->GetBoolean(config_keys::kLocalDiscoveryEnabled, &tmp_bool))
184 set_local_discovery_enabled(tmp_bool);
185
186 if (dict->GetBoolean(config_keys::kLocalPairingEnabled, &tmp_bool))
187 set_local_pairing_enabled(tmp_bool);
188
Vitaly Buka8589b052015-09-29 00:46:14 -0700189 if (dict->GetString(config_keys::kCloudId, &tmp))
190 set_cloud_id(tmp);
191
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700192 if (dict->GetString(config_keys::kDeviceId, &tmp))
193 set_device_id(tmp);
194
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700195 if (dict->GetString(config_keys::kRefreshToken, &tmp))
196 set_refresh_token(tmp);
197
198 if (dict->GetString(config_keys::kRobotAccount, &tmp))
199 set_robot_account(tmp);
200
201 if (dict->GetString(config_keys::kLastConfiguredSsid, &tmp))
202 set_last_configured_ssid(tmp);
203
Vitaly Buka8589b052015-09-29 00:46:14 -0700204 if (dict->GetString(config_keys::kSecret, &tmp))
205 set_secret(tmp);
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700206}
207
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700208void Config::Save() {
209 if (!config_store_)
210 return;
211
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700212 base::DictionaryValue dict;
Vitaly Bukabced5af2015-10-12 17:42:30 -0700213 dict.SetInteger(config_keys::kVersion, kCurrentConfigVersion);
214
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700215 dict.SetString(config_keys::kClientId, settings_.client_id);
216 dict.SetString(config_keys::kClientSecret, settings_.client_secret);
217 dict.SetString(config_keys::kApiKey, settings_.api_key);
218 dict.SetString(config_keys::kOAuthURL, settings_.oauth_url);
219 dict.SetString(config_keys::kServiceURL, settings_.service_url);
220 dict.SetString(config_keys::kRefreshToken, settings_.refresh_token);
Johan Euphrosine312c2f52015-09-29 00:04:29 -0700221 dict.SetString(config_keys::kCloudId, settings_.cloud_id);
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700222 dict.SetString(config_keys::kDeviceId, settings_.device_id);
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700223 dict.SetString(config_keys::kRobotAccount, settings_.robot_account);
224 dict.SetString(config_keys::kLastConfiguredSsid,
225 settings_.last_configured_ssid);
Vitaly Buka8589b052015-09-29 00:46:14 -0700226 dict.SetString(config_keys::kSecret, settings_.secret);
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700227 dict.SetString(config_keys::kName, settings_.name);
228 dict.SetString(config_keys::kDescription, settings_.description);
229 dict.SetString(config_keys::kLocation, settings_.location);
230 dict.SetString(config_keys::kLocalAnonymousAccessRole,
Vitaly Bukab624bc42015-09-29 19:13:55 -0700231 EnumToString(settings_.local_anonymous_access_role));
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700232 dict.SetBoolean(config_keys::kLocalDiscoveryEnabled,
233 settings_.local_discovery_enabled);
234 dict.SetBoolean(config_keys::kLocalPairingEnabled,
235 settings_.local_pairing_enabled);
236
Vitaly Bukac11a17d2015-08-15 10:36:10 -0700237 std::string json_string;
238 base::JSONWriter::WriteWithOptions(
239 dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string);
240
241 config_store_->SaveSettings(json_string);
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700242}
243
244Config::Transaction::~Transaction() {
245 Commit();
246}
247
Vitaly Bukad322a3c2015-08-16 01:03:02 -0700248void Config::Transaction::Commit() {
249 if (!config_)
250 return;
251 if (save_)
252 config_->Save();
253 for (const auto& cb : config_->on_changed_)
254 cb.Run(*settings_);
255 config_ = nullptr;
256}
257
258} // namespace weave