blob: 3f5bd8a2aec1a7d9a62b049b965fa76f9a482d48 [file] [log] [blame]
// 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