blob: ad834f86f57f1166dd6036c82ce3730a25434d4c [file] [log] [blame]
Vitaly Buka1175a9b2015-08-15 10:42: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 Bukabecd4612015-08-16 23:31:55 -07007#include <map>
Vitaly Buka1175a9b2015-08-15 10:42:17 -07008#include <set>
9
Vitaly Bukabecd4612015-08-16 23:31:55 -070010#include <base/files/file_enumerator.h>
Vitaly Buka1175a9b2015-08-15 10:42:17 -070011#include <base/files/file_util.h>
12#include <base/files/important_file_writer.h>
13#include <base/logging.h>
14#include <base/strings/string_number_conversions.h>
Vitaly Bukabecd4612015-08-16 23:31:55 -070015#include <chromeos/errors/error.h>
16#include <chromeos/errors/error_codes.h>
Vitaly Buka1175a9b2015-08-15 10:42:17 -070017#include <chromeos/strings/string_utils.h>
18#include <weave/enum_to_string.h>
19
20namespace buffet {
21
22namespace {
23
Vitaly Bukabecd4612015-08-16 23:31:55 -070024const char kErrorDomain[] = "buffet";
25const char kFileReadError[] = "file_read_error";
26
Vitaly Buka1175a9b2015-08-15 10:42:17 -070027bool StringToTimeDelta(const std::string& value, base::TimeDelta* delta) {
28 uint64_t ms{0};
29 if (!base::StringToUint64(value, &ms))
30 return false;
31 *delta = base::TimeDelta::FromMilliseconds(ms);
32 return true;
33}
34
Vitaly Bukabecd4612015-08-16 23:31:55 -070035bool LoadFile(const base::FilePath& file_path,
36 std::string* data,
37 chromeos::ErrorPtr* error) {
38 if (!base::ReadFileToString(file_path, data)) {
39 chromeos::errors::system::AddSystemError(error, FROM_HERE, errno);
40 chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
41 "Failed to read file '%s'",
42 file_path.value().c_str());
43 return false;
44 }
45 return true;
46}
47
Vitaly Buka1175a9b2015-08-15 10:42:17 -070048} // namespace
49
50namespace config_keys {
51
52const char kClientId[] = "client_id";
53const char kClientSecret[] = "client_secret";
54const char kApiKey[] = "api_key";
55const char kOAuthURL[] = "oauth_url";
56const char kServiceURL[] = "service_url";
57const char kName[] = "name";
58const char kDescription[] = "description";
59const char kLocation[] = "location";
60const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role";
61const char kLocalDiscoveryEnabled[] = "local_discovery_enabled";
62const char kLocalPairingEnabled[] = "local_pairing_enabled";
63const char kOemName[] = "oem_name";
64const char kModelName[] = "model_name";
65const char kModelId[] = "model_id";
66const char kPollingPeriodMs[] = "polling_period_ms";
67const char kBackupPollingPeriodMs[] = "backup_polling_period_ms";
68const char kWifiAutoSetupEnabled[] = "wifi_auto_setup_enabled";
69const char kBleSetupEnabled[] = "ble_setup_enabled";
70const char kEmbeddedCode[] = "embedded_code";
71const char kPairingModes[] = "pairing_modes";
72
73} // namespace config_keys
74
Vitaly Bukabecd4612015-08-16 23:31:55 -070075BuffetConfig::BuffetConfig(const BuffetConfigPaths& paths) : paths_(paths) {}
Vitaly Buka1175a9b2015-08-15 10:42:17 -070076
77void BuffetConfig::AddOnChangedCallback(const OnChangedCallback& callback) {
78 on_changed_.push_back(callback);
79}
80
81bool BuffetConfig::LoadDefaults(weave::Settings* settings) {
Vitaly Bukabecd4612015-08-16 23:31:55 -070082 if (!base::PathExists(paths_.defaults))
Vitaly Buka1175a9b2015-08-15 10:42:17 -070083 return true; // Nothing to load.
84
85 chromeos::KeyValueStore store;
Vitaly Bukabecd4612015-08-16 23:31:55 -070086 if (!store.Load(paths_.defaults))
Vitaly Buka1175a9b2015-08-15 10:42:17 -070087 return false;
88 return LoadDefaults(store, settings);
89}
90
Vitaly Bukabecd4612015-08-16 23:31:55 -070091std::string BuffetConfig::LoadBaseCommandDefs() {
92 // Load global standard GCD command dictionary.
93 base::FilePath path{paths_.definitions.Append("gcd.json")};
94 LOG(INFO) << "Loading standard commands from " << path.value();
95 std::string result;
96 CHECK(LoadFile(path, &result, nullptr));
97 return result;
98}
99
100std::map<std::string, std::string> BuffetConfig::LoadCommandDefs() {
101 std::map<std::string, std::string> result;
102 auto load_packages = [&result](const base::FilePath& root,
103 const base::FilePath::StringType& pattern) {
104 base::FilePath dir{root.Append("commands")};
105 VLOG(2) << "Looking for commands in " << dir.value();
106 base::FileEnumerator enumerator(dir, false, base::FileEnumerator::FILES,
107 pattern);
108 for (base::FilePath path = enumerator.Next(); !path.empty();
109 path = enumerator.Next()) {
110 LOG(INFO) << "Loading command schema from " << path.value();
111 std::string category = path.BaseName().RemoveExtension().value();
112 CHECK(LoadFile(path, &result[category], nullptr));
113 }
114 };
115 load_packages(paths_.definitions, FILE_PATH_LITERAL("*.json"));
116 load_packages(paths_.test_definitions, FILE_PATH_LITERAL("*test.json"));
117 return result;
118}
119
120std::string BuffetConfig::LoadBaseStateDefs() {
121 // Load standard device state definition.
122 base::FilePath path{paths_.definitions.Append("base_state.schema.json")};
123 LOG(INFO) << "Loading standard state definition from " << path.value();
124 std::string result;
125 CHECK(LoadFile(path, &result, nullptr));
126 return result;
127}
128
129std::string BuffetConfig::LoadBaseStateDefaults() {
130 // Load standard device state defaults.
131 base::FilePath path{paths_.definitions.Append("base_state.defaults.json")};
132 LOG(INFO) << "Loading base state defaults from " << path.value();
133 std::string result;
134 CHECK(LoadFile(path, &result, nullptr));
135 return result;
136}
137
138std::map<std::string, std::string> BuffetConfig::LoadStateDefs() {
139 // Load component-specific device state definitions.
140 base::FilePath dir{paths_.definitions.Append("states")};
141 base::FileEnumerator enumerator(dir, false, base::FileEnumerator::FILES,
142 FILE_PATH_LITERAL("*.schema.json"));
143 std::map<std::string, std::string> result;
144 for (base::FilePath path = enumerator.Next(); !path.empty();
145 path = enumerator.Next()) {
146 LOG(INFO) << "Loading state definition from " << path.value();
147 std::string category = path.BaseName().RemoveExtension().value();
148 CHECK(LoadFile(path, &result[category], nullptr));
149 }
150 return result;
151}
152
153std::vector<std::string> BuffetConfig::LoadStateDefaults() {
154 // Load component-specific device state defaults.
155 base::FilePath dir{paths_.definitions.Append("states")};
156 base::FileEnumerator enumerator(dir, false, base::FileEnumerator::FILES,
157 FILE_PATH_LITERAL("*.defaults.json"));
158 std::vector<std::string> result;
159 for (base::FilePath path = enumerator.Next(); !path.empty();
160 path = enumerator.Next()) {
161 LOG(INFO) << "Loading state defaults from " << path.value();
162 std::string json;
163 CHECK(LoadFile(path, &json, nullptr));
164 result.push_back(json);
165 }
166 return result;
167}
168
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700169bool BuffetConfig::LoadDefaults(const chromeos::KeyValueStore& store,
170 weave::Settings* settings) {
171 store.GetString(config_keys::kClientId, &settings->client_id);
172 store.GetString(config_keys::kClientSecret, &settings->client_secret);
173 store.GetString(config_keys::kApiKey, &settings->api_key);
174 store.GetString(config_keys::kOAuthURL, &settings->oauth_url);
175 store.GetString(config_keys::kServiceURL, &settings->service_url);
176 store.GetString(config_keys::kOemName, &settings->oem_name);
177 store.GetString(config_keys::kModelName, &settings->model_name);
178 store.GetString(config_keys::kModelId, &settings->model_id);
Vitaly Buka7b9ebee2015-08-16 01:55:41 -0700179
180 base::FilePath lsb_release_path("/etc/lsb-release");
181 chromeos::KeyValueStore lsb_release_store;
182 if (lsb_release_store.Load(lsb_release_path) &&
183 lsb_release_store.GetString("CHROMEOS_RELEASE_VERSION",
184 &settings->firmware_version)) {
185 } else {
186 LOG(ERROR) << "Failed to get CHROMEOS_RELEASE_VERSION from "
187 << lsb_release_path.value();
188 }
189
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700190 std::string polling_period_str;
191 if (store.GetString(config_keys::kPollingPeriodMs, &polling_period_str) &&
192 !StringToTimeDelta(polling_period_str, &settings->polling_period)) {
193 return false;
194 }
195
196 if (store.GetString(config_keys::kBackupPollingPeriodMs,
197 &polling_period_str) &&
198 !StringToTimeDelta(polling_period_str,
199 &settings->backup_polling_period)) {
200 return false;
201 }
202
203 store.GetBoolean(config_keys::kWifiAutoSetupEnabled,
204 &settings->wifi_auto_setup_enabled);
205 store.GetBoolean(config_keys::kBleSetupEnabled, &settings->ble_setup_enabled);
206 store.GetString(config_keys::kEmbeddedCode, &settings->embedded_code);
207
208 std::string modes_str;
209 if (store.GetString(config_keys::kPairingModes, &modes_str)) {
210 std::set<weave::PairingType> pairing_modes;
211 for (const std::string& mode :
212 chromeos::string_utils::Split(modes_str, ",", true, true)) {
213 weave::PairingType pairing_mode;
214 if (!StringToEnum(mode, &pairing_mode))
215 return false;
216 pairing_modes.insert(pairing_mode);
217 }
218 settings->pairing_modes = std::move(pairing_modes);
219 }
220
221 store.GetString(config_keys::kName, &settings->name);
222 store.GetString(config_keys::kDescription, &settings->description);
223 store.GetString(config_keys::kLocation, &settings->location);
224 store.GetString(config_keys::kLocalAnonymousAccessRole,
225 &settings->local_anonymous_access_role);
226 store.GetBoolean(config_keys::kLocalDiscoveryEnabled,
227 &settings->local_discovery_enabled);
228 store.GetBoolean(config_keys::kLocalPairingEnabled,
229 &settings->local_pairing_enabled);
230 return true;
231}
232
233std::string BuffetConfig::LoadSettings() {
234 std::string json_string;
Vitaly Bukabecd4612015-08-16 23:31:55 -0700235 base::ReadFileToString(paths_.settings, &json_string);
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700236 return json_string;
237}
238
239void BuffetConfig::SaveSettings(const std::string& settings) {
Vitaly Bukabecd4612015-08-16 23:31:55 -0700240 base::ImportantFileWriter::WriteFileAtomically(paths_.settings, settings);
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700241}
242
243void BuffetConfig::OnSettingsChanged(const weave::Settings& settings) {
244 for (const auto& cb : on_changed_)
245 cb.Run(settings);
246}
247
248} // namespace buffet