| // Copyright 2015 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "libweave/src/buffet_config.h" |
| |
| #include <set> |
| |
| #include <base/files/file_util.h> |
| #include <base/logging.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <weave/enum_to_string.h> |
| |
| #include "libweave/src/storage_impls.h" |
| #include "libweave/src/storage_interface.h" |
| #include "libweave/src/string_utils.h" |
| |
| namespace { |
| |
| bool IsValidAccessRole(const std::string& role) { |
| return role == "none" || role == "viewer" || role == "user"; |
| } |
| |
| bool StringToTimeDelta(const std::string& value, base::TimeDelta* delta) { |
| uint64_t ms{0}; |
| if (!base::StringToUint64(value, &ms)) |
| return false; |
| *delta = base::TimeDelta::FromMilliseconds(ms); |
| return true; |
| } |
| |
| } // namespace |
| |
| namespace weave { |
| |
| namespace config_keys { |
| |
| const char kClientId[] = "client_id"; |
| const char kClientSecret[] = "client_secret"; |
| const char kApiKey[] = "api_key"; |
| const char kOAuthURL[] = "oauth_url"; |
| const char kServiceURL[] = "service_url"; |
| const char kName[] = "name"; |
| const char kDescription[] = "description"; |
| const char kLocation[] = "location"; |
| const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role"; |
| const char kLocalDiscoveryEnabled[] = "local_discovery_enabled"; |
| const char kLocalPairingEnabled[] = "local_pairing_enabled"; |
| const char kOemName[] = "oem_name"; |
| const char kModelName[] = "model_name"; |
| const char kModelId[] = "model_id"; |
| const char kPollingPeriodMs[] = "polling_period_ms"; |
| const char kBackupPollingPeriodMs[] = "backup_polling_period_ms"; |
| const char kRefreshToken[] = "refresh_token"; |
| const char kDeviceId[] = "device_id"; |
| const char kRobotAccount[] = "robot_account"; |
| const char kWifiAutoSetupEnabled[] = "wifi_auto_setup_enabled"; |
| const char kBleSetupEnabled[] = "ble_setup_enabled"; |
| const char kEmbeddedCode[] = "embedded_code"; |
| const char kPairingModes[] = "pairing_modes"; |
| const char kLastConfiguredSsid[] = "last_configured_ssid"; |
| |
| } // namespace config_keys |
| |
| Settings BuffetConfig::CreateDefaultSettings() { |
| Settings result; |
| result.client_id = "58855907228.apps.googleusercontent.com"; |
| result.client_secret = "eHSAREAHrIqPsHBxCE9zPPBi"; |
| result.api_key = "AIzaSyDSq46gG-AxUnC3zoqD9COIPrjolFsMfMA"; |
| result.oauth_url = "https://accounts.google.com/o/oauth2/"; |
| result.service_url = "https://www.googleapis.com/clouddevices/v1/"; |
| result.name = "Developer device"; |
| result.local_anonymous_access_role = "viewer"; |
| result.local_discovery_enabled = true; |
| result.local_pairing_enabled = true; |
| result.oem_name = "Chromium"; |
| result.model_name = "Brillo"; |
| result.model_id = "AAAAA"; |
| result.polling_period = base::TimeDelta::FromSeconds(7); |
| result.backup_polling_period = base::TimeDelta::FromMinutes(30); |
| result.wifi_auto_setup_enabled = true; |
| result.ble_setup_enabled = false; |
| result.pairing_modes.emplace(PairingType::kPinCode); |
| return result; |
| } |
| |
| BuffetConfig::BuffetConfig(std::unique_ptr<StorageInterface> storage) |
| : storage_{std::move(storage)} { |
| } |
| |
| BuffetConfig::BuffetConfig(const base::FilePath& state_path) |
| : BuffetConfig{ |
| std::unique_ptr<StorageInterface>{new FileStorage{state_path}}} { |
| } |
| |
| void BuffetConfig::AddOnChangedCallback(const OnChangedCallback& callback) { |
| on_changed_.push_back(callback); |
| // Force to read current state. |
| callback.Run(settings_); |
| } |
| |
| const Settings& BuffetConfig::GetSettings() const { |
| return settings_; |
| } |
| |
| void BuffetConfig::Load(const base::FilePath& config_path) { |
| chromeos::KeyValueStore store; |
| if (base::PathExists(config_path)) { |
| CHECK(store.Load(config_path)) << "Unable to read or parse config file at" |
| << config_path.value(); |
| } |
| Load(store); |
| } |
| |
| void BuffetConfig::Load(const chromeos::KeyValueStore& store) { |
| Transaction change{this}; |
| change.save_ = false; |
| |
| store.GetString(config_keys::kClientId, &settings_.client_id); |
| CHECK(!settings_.client_id.empty()); |
| |
| store.GetString(config_keys::kClientSecret, &settings_.client_secret); |
| CHECK(!settings_.client_secret.empty()); |
| |
| store.GetString(config_keys::kApiKey, &settings_.api_key); |
| CHECK(!settings_.api_key.empty()); |
| |
| store.GetString(config_keys::kOAuthURL, &settings_.oauth_url); |
| CHECK(!settings_.oauth_url.empty()); |
| |
| store.GetString(config_keys::kServiceURL, &settings_.service_url); |
| CHECK(!settings_.service_url.empty()); |
| |
| store.GetString(config_keys::kOemName, &settings_.oem_name); |
| CHECK(!settings_.oem_name.empty()); |
| |
| store.GetString(config_keys::kModelName, &settings_.model_name); |
| CHECK(!settings_.model_name.empty()); |
| |
| store.GetString(config_keys::kModelId, &settings_.model_id); |
| CHECK(!settings_.model_id.empty()); |
| |
| std::string polling_period_str; |
| if (store.GetString(config_keys::kPollingPeriodMs, &polling_period_str)) |
| CHECK(StringToTimeDelta(polling_period_str, &settings_.polling_period)); |
| |
| if (store.GetString(config_keys::kBackupPollingPeriodMs, &polling_period_str)) |
| CHECK(StringToTimeDelta(polling_period_str, |
| &settings_.backup_polling_period)); |
| |
| store.GetBoolean(config_keys::kWifiAutoSetupEnabled, |
| &settings_.wifi_auto_setup_enabled); |
| |
| store.GetBoolean(config_keys::kBleSetupEnabled, |
| &settings_.ble_setup_enabled); |
| |
| store.GetString(config_keys::kEmbeddedCode, &settings_.embedded_code); |
| |
| std::string modes_str; |
| if (store.GetString(config_keys::kPairingModes, &modes_str)) { |
| std::set<PairingType> pairing_modes; |
| for (const std::string& mode : Split(modes_str, ",", true, true)) { |
| PairingType pairing_mode; |
| CHECK(StringToEnum(mode, &pairing_mode)); |
| pairing_modes.insert(pairing_mode); |
| } |
| settings_.pairing_modes = std::move(pairing_modes); |
| } |
| |
| // Empty name set by user or server is allowed, still we expect some |
| // meaningfull config value. |
| store.GetString(config_keys::kName, &settings_.name); |
| CHECK(!settings_.name.empty()); |
| |
| store.GetString(config_keys::kDescription, &settings_.description); |
| store.GetString(config_keys::kLocation, &settings_.location); |
| |
| store.GetString(config_keys::kLocalAnonymousAccessRole, |
| &settings_.local_anonymous_access_role); |
| CHECK(IsValidAccessRole(settings_.local_anonymous_access_role)) |
| << "Invalid role: " << settings_.local_anonymous_access_role; |
| |
| store.GetBoolean(config_keys::kLocalDiscoveryEnabled, |
| &settings_.local_discovery_enabled); |
| store.GetBoolean(config_keys::kLocalPairingEnabled, |
| &settings_.local_pairing_enabled); |
| |
| change.LoadState(); |
| } |
| |
| void BuffetConfig::Transaction::LoadState() { |
| if (!config_->storage_) |
| return; |
| auto value = config_->storage_->Load(); |
| const base::DictionaryValue* dict = nullptr; |
| if (!value || !value->GetAsDictionary(&dict)) |
| return; |
| |
| std::string tmp; |
| bool tmp_bool{false}; |
| |
| if (dict->GetString(config_keys::kClientId, &tmp)) |
| set_client_id(tmp); |
| |
| if (dict->GetString(config_keys::kClientSecret, &tmp)) |
| set_client_secret(tmp); |
| |
| if (dict->GetString(config_keys::kApiKey, &tmp)) |
| set_api_key(tmp); |
| |
| if (dict->GetString(config_keys::kOAuthURL, &tmp)) |
| set_oauth_url(tmp); |
| |
| if (dict->GetString(config_keys::kServiceURL, &tmp)) |
| set_service_url(tmp); |
| |
| if (dict->GetString(config_keys::kName, &tmp)) |
| set_name(tmp); |
| |
| if (dict->GetString(config_keys::kDescription, &tmp)) |
| set_description(tmp); |
| |
| if (dict->GetString(config_keys::kLocation, &tmp)) |
| set_location(tmp); |
| |
| if (dict->GetString(config_keys::kLocalAnonymousAccessRole, &tmp)) |
| set_local_anonymous_access_role(tmp); |
| |
| if (dict->GetBoolean(config_keys::kLocalDiscoveryEnabled, &tmp_bool)) |
| set_local_discovery_enabled(tmp_bool); |
| |
| if (dict->GetBoolean(config_keys::kLocalPairingEnabled, &tmp_bool)) |
| set_local_pairing_enabled(tmp_bool); |
| |
| if (dict->GetString(config_keys::kRefreshToken, &tmp)) |
| set_refresh_token(tmp); |
| |
| if (dict->GetString(config_keys::kRobotAccount, &tmp)) |
| set_robot_account(tmp); |
| |
| if (dict->GetString(config_keys::kLastConfiguredSsid, &tmp)) |
| set_last_configured_ssid(tmp); |
| |
| if (dict->GetString(config_keys::kDeviceId, &tmp)) |
| set_device_id(tmp); |
| } |
| |
| bool BuffetConfig::Save() { |
| if (!storage_) |
| return false; |
| base::DictionaryValue dict; |
| dict.SetString(config_keys::kClientId, settings_.client_id); |
| dict.SetString(config_keys::kClientSecret, settings_.client_secret); |
| dict.SetString(config_keys::kApiKey, settings_.api_key); |
| dict.SetString(config_keys::kOAuthURL, settings_.oauth_url); |
| dict.SetString(config_keys::kServiceURL, settings_.service_url); |
| dict.SetString(config_keys::kRefreshToken, settings_.refresh_token); |
| dict.SetString(config_keys::kDeviceId, settings_.device_id); |
| dict.SetString(config_keys::kRobotAccount, settings_.robot_account); |
| dict.SetString(config_keys::kLastConfiguredSsid, |
| settings_.last_configured_ssid); |
| dict.SetString(config_keys::kName, settings_.name); |
| dict.SetString(config_keys::kDescription, settings_.description); |
| dict.SetString(config_keys::kLocation, settings_.location); |
| dict.SetString(config_keys::kLocalAnonymousAccessRole, |
| settings_.local_anonymous_access_role); |
| dict.SetBoolean(config_keys::kLocalDiscoveryEnabled, |
| settings_.local_discovery_enabled); |
| dict.SetBoolean(config_keys::kLocalPairingEnabled, |
| settings_.local_pairing_enabled); |
| |
| return storage_->Save(dict); |
| } |
| |
| BuffetConfig::Transaction::~Transaction() { |
| Commit(); |
| } |
| |
| bool BuffetConfig::Transaction::set_local_anonymous_access_role( |
| const std::string& role) { |
| if (!IsValidAccessRole(role)) { |
| LOG(ERROR) << "Invalid role: " << role; |
| return false; |
| } |
| settings_->local_anonymous_access_role = role; |
| return true; |
| } |
| |
| void BuffetConfig::Transaction::Commit() { |
| if (!config_) |
| return; |
| if (save_) |
| config_->Save(); |
| for (const auto& cb : config_->on_changed_) |
| cb.Run(*settings_); |
| config_ = nullptr; |
| } |
| |
| } // namespace weave |