Vitaly Buka | 4615e0d | 2015-10-14 15:35:12 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Weave Authors. All rights reserved. |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Stefan Sauer | 2d16dfa | 2015-09-25 17:08:35 +0200 | [diff] [blame] | 5 | #include "src/config.h" |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 6 | |
Alex Vakulenko | b9bbdc6 | 2016-03-28 13:26:51 -0700 | [diff] [blame] | 7 | |
| 8 | #include <algorithm> |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 9 | #include <set> |
| 10 | |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 11 | #include <base/bind.h> |
Johan Euphrosine | 0b7bb9f | 2015-09-29 01:11:21 -0700 | [diff] [blame] | 12 | #include <base/guid.h> |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 13 | #include <base/json/json_reader.h> |
| 14 | #include <base/json/json_writer.h> |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 15 | #include <base/logging.h> |
| 16 | #include <base/strings/string_number_conversions.h> |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 17 | #include <base/values.h> |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 18 | #include <weave/enum_to_string.h> |
| 19 | |
Vitaly Buka | f08caeb | 2015-12-02 13:47:48 -0800 | [diff] [blame] | 20 | #include "src/data_encoding.h" |
Stefan Sauer | 2d16dfa | 2015-09-25 17:08:35 +0200 | [diff] [blame] | 21 | #include "src/privet/privet_types.h" |
| 22 | #include "src/string_utils.h" |
Vitaly Buka | ac18fcf | 2016-01-15 14:48:54 -0800 | [diff] [blame] | 23 | #include "src/bind_lambda.h" |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 24 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 25 | namespace weave { |
| 26 | |
Vitaly Buka | d1e6c4f | 2016-01-15 12:19:17 -0800 | [diff] [blame] | 27 | const char kConfigName[] = "config"; |
| 28 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 29 | namespace config_keys { |
| 30 | |
Vitaly Buka | bced5af | 2015-10-12 17:42:30 -0700 | [diff] [blame] | 31 | const char kVersion[] = "version"; |
| 32 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 33 | const char kClientId[] = "client_id"; |
| 34 | const char kClientSecret[] = "client_secret"; |
| 35 | const char kApiKey[] = "api_key"; |
Vitaly Buka | 1e019fa | 2016-02-10 11:28:16 -0800 | [diff] [blame] | 36 | const char kOAuthUrl[] = "oauth_url"; |
| 37 | const char kServiceUrl[] = "service_url"; |
Vitaly Buka | 3b8fbc5 | 2016-02-04 15:42:04 -0800 | [diff] [blame] | 38 | const char kXmppEndpoint[] = "xmpp_endpoint"; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 39 | const char kName[] = "name"; |
| 40 | const char kDescription[] = "description"; |
| 41 | const char kLocation[] = "location"; |
| 42 | const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role"; |
| 43 | const char kLocalDiscoveryEnabled[] = "local_discovery_enabled"; |
| 44 | const char kLocalPairingEnabled[] = "local_pairing_enabled"; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 45 | const char kRefreshToken[] = "refresh_token"; |
Johan Euphrosine | 312c2f5 | 2015-09-29 00:04:29 -0700 | [diff] [blame] | 46 | const char kCloudId[] = "cloud_id"; |
Johan Euphrosine | 0b7bb9f | 2015-09-29 01:11:21 -0700 | [diff] [blame] | 47 | const char kDeviceId[] = "device_id"; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 48 | const char kRobotAccount[] = "robot_account"; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 49 | const char kLastConfiguredSsid[] = "last_configured_ssid"; |
Vitaly Buka | 8589b05 | 2015-09-29 00:46:14 -0700 | [diff] [blame] | 50 | const char kSecret[] = "secret"; |
Vitaly Buka | 63c9862 | 2015-12-11 11:06:04 -0800 | [diff] [blame] | 51 | const char kRootClientTokenOwner[] = "root_client_token_owner"; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 52 | |
| 53 | } // namespace config_keys |
| 54 | |
Vitaly Buka | 0d7aac8 | 2015-11-16 23:02:24 -0800 | [diff] [blame] | 55 | const char kWeaveUrl[] = "https://www.googleapis.com/weave/v1/"; |
| 56 | const char kDeprecatedUrl[] = "https://www.googleapis.com/clouddevices/v1/"; |
Vitaly Buka | 3b8fbc5 | 2016-02-04 15:42:04 -0800 | [diff] [blame] | 57 | const char kXmppEndpoint[] = "talk.google.com:5223"; |
Vitaly Buka | 0d7aac8 | 2015-11-16 23:02:24 -0800 | [diff] [blame] | 58 | |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 59 | namespace { |
| 60 | |
Vitaly Buka | bced5af | 2015-10-12 17:42:30 -0700 | [diff] [blame] | 61 | const int kCurrentConfigVersion = 1; |
| 62 | |
| 63 | void MigrateFromV0(base::DictionaryValue* dict) { |
| 64 | std::string cloud_id; |
| 65 | if (dict->GetString(config_keys::kCloudId, &cloud_id) && !cloud_id.empty()) |
| 66 | return; |
| 67 | scoped_ptr<base::Value> tmp; |
| 68 | if (dict->Remove(config_keys::kDeviceId, &tmp)) |
| 69 | dict->Set(config_keys::kCloudId, std::move(tmp)); |
| 70 | } |
| 71 | |
Vitaly Buka | 03ee8ac | 2016-02-05 11:40:33 -0800 | [diff] [blame] | 72 | Config::Settings CreateDefaultSettings(provider::ConfigStore* config_store) { |
Vitaly Buka | 238db69 | 2015-09-29 16:58:39 -0700 | [diff] [blame] | 73 | Config::Settings result; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 74 | result.oauth_url = "https://accounts.google.com/o/oauth2/"; |
Vitaly Buka | 0d7aac8 | 2015-11-16 23:02:24 -0800 | [diff] [blame] | 75 | result.service_url = kWeaveUrl; |
Vitaly Buka | 3b8fbc5 | 2016-02-04 15:42:04 -0800 | [diff] [blame] | 76 | result.xmpp_endpoint = kXmppEndpoint; |
Vitaly Buka | b624bc4 | 2015-09-29 19:13:55 -0700 | [diff] [blame] | 77 | result.local_anonymous_access_role = AuthScope::kViewer; |
Vitaly Buka | 52d006a | 2015-11-21 17:14:51 -0800 | [diff] [blame] | 78 | result.pairing_modes.insert(PairingType::kPinCode); |
Johan Euphrosine | 0b7bb9f | 2015-09-29 01:11:21 -0700 | [diff] [blame] | 79 | result.device_id = base::GenerateGUID(); |
Vitaly Buka | 03ee8ac | 2016-02-05 11:40:33 -0800 | [diff] [blame] | 80 | |
| 81 | if (!config_store) |
| 82 | return result; |
| 83 | |
| 84 | // Crash on any mistakes in defaults. |
| 85 | CHECK(config_store->LoadDefaults(&result)); |
| 86 | |
| 87 | CHECK(!result.client_id.empty()); |
| 88 | CHECK(!result.client_secret.empty()); |
| 89 | CHECK(!result.api_key.empty()); |
| 90 | CHECK(!result.oauth_url.empty()); |
| 91 | CHECK(!result.service_url.empty()); |
| 92 | CHECK(!result.xmpp_endpoint.empty()); |
| 93 | CHECK(!result.oem_name.empty()); |
| 94 | CHECK(!result.model_name.empty()); |
| 95 | CHECK(!result.model_id.empty()); |
| 96 | CHECK(!result.name.empty()); |
| 97 | CHECK(!result.device_id.empty()); |
| 98 | CHECK_EQ(result.embedded_code.empty(), |
| 99 | (result.pairing_modes.find(PairingType::kEmbeddedCode) == |
| 100 | result.pairing_modes.end())); |
| 101 | |
| 102 | // Values below will be generated at runtime. |
| 103 | CHECK(result.cloud_id.empty()); |
| 104 | CHECK(result.refresh_token.empty()); |
| 105 | CHECK(result.robot_account.empty()); |
| 106 | CHECK(result.last_configured_ssid.empty()); |
| 107 | CHECK(result.secret.empty()); |
| 108 | CHECK(result.root_client_token_owner == RootClientTokenOwner::kNone); |
| 109 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 110 | return result; |
| 111 | } |
| 112 | |
Vitaly Buka | 63c9862 | 2015-12-11 11:06:04 -0800 | [diff] [blame] | 113 | const EnumToStringMap<RootClientTokenOwner>::Map kRootClientTokenOwnerMap[] = { |
| 114 | {RootClientTokenOwner::kNone, "none"}, |
| 115 | {RootClientTokenOwner::kClient, "client"}, |
| 116 | {RootClientTokenOwner::kCloud, "cloud"}, |
| 117 | }; |
| 118 | |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 119 | } // namespace |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 120 | |
Vitaly Buka | 63c9862 | 2015-12-11 11:06:04 -0800 | [diff] [blame] | 121 | template <> |
| 122 | LIBWEAVE_EXPORT EnumToStringMap<RootClientTokenOwner>::EnumToStringMap() |
| 123 | : EnumToStringMap(kRootClientTokenOwnerMap) {} |
| 124 | |
Vitaly Buka | 1e36367 | 2015-09-25 14:01:16 -0700 | [diff] [blame] | 125 | Config::Config(provider::ConfigStore* config_store) |
Vitaly Buka | 03ee8ac | 2016-02-05 11:40:33 -0800 | [diff] [blame] | 126 | : defaults_{CreateDefaultSettings(config_store)}, |
| 127 | settings_{defaults_}, |
| 128 | config_store_{config_store} { |
| 129 | Transaction change{this}; |
| 130 | change.save_ = false; |
| 131 | change.LoadState(); |
Vitaly Buka | 3d6b552 | 2015-12-22 13:14:16 -0800 | [diff] [blame] | 132 | } |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 133 | |
| 134 | void Config::AddOnChangedCallback(const OnChangedCallback& callback) { |
| 135 | on_changed_.push_back(callback); |
| 136 | // Force to read current state. |
| 137 | callback.Run(settings_); |
| 138 | } |
| 139 | |
Vitaly Buka | 238db69 | 2015-09-29 16:58:39 -0700 | [diff] [blame] | 140 | const Config::Settings& Config::GetSettings() const { |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 141 | return settings_; |
| 142 | } |
| 143 | |
Vitaly Buka | 03ee8ac | 2016-02-05 11:40:33 -0800 | [diff] [blame] | 144 | const Config::Settings& Config::GetDefaults() const { |
| 145 | return defaults_; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 146 | } |
| 147 | |
| 148 | void Config::Transaction::LoadState() { |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 149 | if (!config_->config_store_) |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 150 | return; |
Vitaly Buka | d1e6c4f | 2016-01-15 12:19:17 -0800 | [diff] [blame] | 151 | std::string json_string = config_->config_store_->LoadSettings(kConfigName); |
| 152 | if (json_string.empty()) { |
| 153 | json_string = config_->config_store_->LoadSettings(); |
| 154 | if (json_string.empty()) |
| 155 | return; |
| 156 | } |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 157 | |
| 158 | auto value = base::JSONReader::Read(json_string); |
Vitaly Buka | bced5af | 2015-10-12 17:42:30 -0700 | [diff] [blame] | 159 | base::DictionaryValue* dict = nullptr; |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 160 | if (!value || !value->GetAsDictionary(&dict)) { |
| 161 | LOG(ERROR) << "Failed to parse settings."; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 162 | return; |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 163 | } |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 164 | |
Vitaly Buka | bced5af | 2015-10-12 17:42:30 -0700 | [diff] [blame] | 165 | int loaded_version = 0; |
| 166 | dict->GetInteger(config_keys::kVersion, &loaded_version); |
| 167 | |
| 168 | if (loaded_version != kCurrentConfigVersion) { |
| 169 | LOG(INFO) << "State version mismatch. expected: " << kCurrentConfigVersion |
| 170 | << ", loaded: " << loaded_version; |
| 171 | save_ = true; |
| 172 | } |
| 173 | |
| 174 | if (loaded_version == 0) { |
| 175 | MigrateFromV0(dict); |
| 176 | } |
| 177 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 178 | std::string tmp; |
| 179 | bool tmp_bool{false}; |
| 180 | |
| 181 | if (dict->GetString(config_keys::kClientId, &tmp)) |
| 182 | set_client_id(tmp); |
| 183 | |
| 184 | if (dict->GetString(config_keys::kClientSecret, &tmp)) |
| 185 | set_client_secret(tmp); |
| 186 | |
| 187 | if (dict->GetString(config_keys::kApiKey, &tmp)) |
| 188 | set_api_key(tmp); |
| 189 | |
Vitaly Buka | 1e019fa | 2016-02-10 11:28:16 -0800 | [diff] [blame] | 190 | if (dict->GetString(config_keys::kOAuthUrl, &tmp)) |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 191 | set_oauth_url(tmp); |
| 192 | |
Vitaly Buka | 1e019fa | 2016-02-10 11:28:16 -0800 | [diff] [blame] | 193 | if (dict->GetString(config_keys::kServiceUrl, &tmp)) { |
Vitaly Buka | 0d7aac8 | 2015-11-16 23:02:24 -0800 | [diff] [blame] | 194 | if (tmp == kDeprecatedUrl) |
| 195 | tmp = kWeaveUrl; |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 196 | set_service_url(tmp); |
Vitaly Buka | 0d7aac8 | 2015-11-16 23:02:24 -0800 | [diff] [blame] | 197 | } |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 198 | |
Vitaly Buka | 3b8fbc5 | 2016-02-04 15:42:04 -0800 | [diff] [blame] | 199 | if (dict->GetString(config_keys::kXmppEndpoint, &tmp)) { |
| 200 | set_xmpp_endpoint(tmp); |
| 201 | } |
| 202 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 203 | if (dict->GetString(config_keys::kName, &tmp)) |
| 204 | set_name(tmp); |
| 205 | |
| 206 | if (dict->GetString(config_keys::kDescription, &tmp)) |
| 207 | set_description(tmp); |
| 208 | |
| 209 | if (dict->GetString(config_keys::kLocation, &tmp)) |
| 210 | set_location(tmp); |
| 211 | |
Vitaly Buka | b624bc4 | 2015-09-29 19:13:55 -0700 | [diff] [blame] | 212 | AuthScope scope{AuthScope::kNone}; |
| 213 | if (dict->GetString(config_keys::kLocalAnonymousAccessRole, &tmp) && |
| 214 | StringToEnum(tmp, &scope)) { |
| 215 | set_local_anonymous_access_role(scope); |
| 216 | } |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 217 | |
| 218 | if (dict->GetBoolean(config_keys::kLocalDiscoveryEnabled, &tmp_bool)) |
| 219 | set_local_discovery_enabled(tmp_bool); |
| 220 | |
| 221 | if (dict->GetBoolean(config_keys::kLocalPairingEnabled, &tmp_bool)) |
| 222 | set_local_pairing_enabled(tmp_bool); |
| 223 | |
Vitaly Buka | 8589b05 | 2015-09-29 00:46:14 -0700 | [diff] [blame] | 224 | if (dict->GetString(config_keys::kCloudId, &tmp)) |
| 225 | set_cloud_id(tmp); |
| 226 | |
Johan Euphrosine | 0b7bb9f | 2015-09-29 01:11:21 -0700 | [diff] [blame] | 227 | if (dict->GetString(config_keys::kDeviceId, &tmp)) |
| 228 | set_device_id(tmp); |
| 229 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 230 | if (dict->GetString(config_keys::kRefreshToken, &tmp)) |
| 231 | set_refresh_token(tmp); |
| 232 | |
| 233 | if (dict->GetString(config_keys::kRobotAccount, &tmp)) |
| 234 | set_robot_account(tmp); |
| 235 | |
| 236 | if (dict->GetString(config_keys::kLastConfiguredSsid, &tmp)) |
| 237 | set_last_configured_ssid(tmp); |
| 238 | |
Vitaly Buka | f08caeb | 2015-12-02 13:47:48 -0800 | [diff] [blame] | 239 | std::vector<uint8_t> secret; |
| 240 | if (dict->GetString(config_keys::kSecret, &tmp) && Base64Decode(tmp, &secret)) |
| 241 | set_secret(secret); |
Vitaly Buka | a580328 | 2015-12-06 20:11:55 -0800 | [diff] [blame] | 242 | |
Vitaly Buka | 63c9862 | 2015-12-11 11:06:04 -0800 | [diff] [blame] | 243 | RootClientTokenOwner token_owner{RootClientTokenOwner::kNone}; |
| 244 | if (dict->GetString(config_keys::kRootClientTokenOwner, &tmp) && |
| 245 | StringToEnum(tmp, &token_owner)) { |
| 246 | set_root_client_token_owner(token_owner); |
| 247 | } |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 248 | } |
| 249 | |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 250 | void Config::Save() { |
| 251 | if (!config_store_) |
| 252 | return; |
| 253 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 254 | base::DictionaryValue dict; |
Vitaly Buka | bced5af | 2015-10-12 17:42:30 -0700 | [diff] [blame] | 255 | dict.SetInteger(config_keys::kVersion, kCurrentConfigVersion); |
| 256 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 257 | dict.SetString(config_keys::kClientId, settings_.client_id); |
| 258 | dict.SetString(config_keys::kClientSecret, settings_.client_secret); |
| 259 | dict.SetString(config_keys::kApiKey, settings_.api_key); |
Vitaly Buka | 1e019fa | 2016-02-10 11:28:16 -0800 | [diff] [blame] | 260 | dict.SetString(config_keys::kOAuthUrl, settings_.oauth_url); |
| 261 | dict.SetString(config_keys::kServiceUrl, settings_.service_url); |
Vitaly Buka | 3b8fbc5 | 2016-02-04 15:42:04 -0800 | [diff] [blame] | 262 | dict.SetString(config_keys::kXmppEndpoint, settings_.xmpp_endpoint); |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 263 | dict.SetString(config_keys::kRefreshToken, settings_.refresh_token); |
Johan Euphrosine | 312c2f5 | 2015-09-29 00:04:29 -0700 | [diff] [blame] | 264 | dict.SetString(config_keys::kCloudId, settings_.cloud_id); |
Johan Euphrosine | 0b7bb9f | 2015-09-29 01:11:21 -0700 | [diff] [blame] | 265 | dict.SetString(config_keys::kDeviceId, settings_.device_id); |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 266 | dict.SetString(config_keys::kRobotAccount, settings_.robot_account); |
| 267 | dict.SetString(config_keys::kLastConfiguredSsid, |
| 268 | settings_.last_configured_ssid); |
Vitaly Buka | f08caeb | 2015-12-02 13:47:48 -0800 | [diff] [blame] | 269 | dict.SetString(config_keys::kSecret, Base64Encode(settings_.secret)); |
Vitaly Buka | 63c9862 | 2015-12-11 11:06:04 -0800 | [diff] [blame] | 270 | dict.SetString(config_keys::kRootClientTokenOwner, |
| 271 | EnumToString(settings_.root_client_token_owner)); |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 272 | dict.SetString(config_keys::kName, settings_.name); |
| 273 | dict.SetString(config_keys::kDescription, settings_.description); |
| 274 | dict.SetString(config_keys::kLocation, settings_.location); |
| 275 | dict.SetString(config_keys::kLocalAnonymousAccessRole, |
Vitaly Buka | b624bc4 | 2015-09-29 19:13:55 -0700 | [diff] [blame] | 276 | EnumToString(settings_.local_anonymous_access_role)); |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 277 | dict.SetBoolean(config_keys::kLocalDiscoveryEnabled, |
| 278 | settings_.local_discovery_enabled); |
| 279 | dict.SetBoolean(config_keys::kLocalPairingEnabled, |
| 280 | settings_.local_pairing_enabled); |
| 281 | |
Vitaly Buka | c11a17d | 2015-08-15 10:36:10 -0700 | [diff] [blame] | 282 | std::string json_string; |
| 283 | base::JSONWriter::WriteWithOptions( |
| 284 | dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string); |
| 285 | |
Vitaly Buka | ac18fcf | 2016-01-15 14:48:54 -0800 | [diff] [blame] | 286 | config_store_->SaveSettings( |
| 287 | kConfigName, json_string, |
| 288 | base::Bind([](ErrorPtr error) { CHECK(!error); })); |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 289 | } |
| 290 | |
| 291 | Config::Transaction::~Transaction() { |
| 292 | Commit(); |
| 293 | } |
| 294 | |
Vitaly Buka | d322a3c | 2015-08-16 01:03:02 -0700 | [diff] [blame] | 295 | void Config::Transaction::Commit() { |
| 296 | if (!config_) |
| 297 | return; |
| 298 | if (save_) |
| 299 | config_->Save(); |
| 300 | for (const auto& cb : config_->on_changed_) |
| 301 | cb.Run(*settings_); |
| 302 | config_ = nullptr; |
| 303 | } |
| 304 | |
| 305 | } // namespace weave |