- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / settings / cros_settings.cc
1 // Copyright (c) 2012 The Chromium 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 "chrome/browser/chromeos/settings/cros_settings.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/values.h"
13 #include "chrome/browser/chromeos/settings/device_settings_provider.h"
14 #include "chrome/browser/chromeos/settings/device_settings_service.h"
15 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
16 #include "chrome/browser/chromeos/settings/system_settings_provider.h"
17 #include "chromeos/chromeos_switches.h"
18 #include "google_apis/gaia/gaia_auth_util.h"
19
20 namespace chromeos {
21
22 static CrosSettings*  g_cros_settings = NULL;
23
24 // static
25 void CrosSettings::Initialize() {
26   CHECK(!g_cros_settings);
27   g_cros_settings = new CrosSettings(DeviceSettingsService::Get());
28 }
29
30 // static
31 bool CrosSettings::IsInitialized() {
32   return g_cros_settings;
33 }
34
35 // static
36 void CrosSettings::Shutdown() {
37   DCHECK(g_cros_settings);
38   delete g_cros_settings;
39   g_cros_settings = NULL;
40 }
41
42 // static
43 CrosSettings* CrosSettings::Get() {
44   CHECK(g_cros_settings);
45   return g_cros_settings;
46 }
47
48 CrosSettings::CrosSettings(DeviceSettingsService* device_settings_service) {
49   CrosSettingsProvider::NotifyObserversCallback notify_cb(
50       base::Bind(&CrosSettings::FireObservers,
51                  // This is safe since |this| is never deleted.
52                  base::Unretained(this)));
53   if (CommandLine::ForCurrentProcess()->HasSwitch(
54           switches::kStubCrosSettings)) {
55     AddSettingsProvider(new StubCrosSettingsProvider(notify_cb));
56   } else {
57     AddSettingsProvider(
58         new DeviceSettingsProvider(notify_cb, device_settings_service));
59   }
60   // System settings are not mocked currently.
61   AddSettingsProvider(new SystemSettingsProvider(notify_cb));
62 }
63
64 CrosSettings::~CrosSettings() {
65   STLDeleteElements(&providers_);
66   STLDeleteValues(&settings_observers_);
67 }
68
69 bool CrosSettings::IsCrosSettings(const std::string& path) {
70   return StartsWithASCII(path, kCrosSettingsPrefix, true);
71 }
72
73 void CrosSettings::Set(const std::string& path, const base::Value& in_value) {
74   DCHECK(CalledOnValidThread());
75   CrosSettingsProvider* provider;
76   provider = GetProvider(path);
77   if (provider)
78     provider->Set(path, in_value);
79 }
80
81 const base::Value* CrosSettings::GetPref(const std::string& path) const {
82   DCHECK(CalledOnValidThread());
83   CrosSettingsProvider* provider = GetProvider(path);
84   if (provider)
85     return provider->Get(path);
86   NOTREACHED() << path << " preference was not found in the signed settings.";
87   return NULL;
88 }
89
90 CrosSettingsProvider::TrustedStatus CrosSettings::PrepareTrustedValues(
91     const base::Closure& callback) const {
92   DCHECK(CalledOnValidThread());
93   for (size_t i = 0; i < providers_.size(); ++i) {
94     CrosSettingsProvider::TrustedStatus status =
95         providers_[i]->PrepareTrustedValues(callback);
96     if (status != CrosSettingsProvider::TRUSTED)
97       return status;
98   }
99   return CrosSettingsProvider::TRUSTED;
100 }
101
102 void CrosSettings::SetBoolean(const std::string& path, bool in_value) {
103   DCHECK(CalledOnValidThread());
104   base::FundamentalValue value(in_value);
105   Set(path, value);
106 }
107
108 void CrosSettings::SetInteger(const std::string& path, int in_value) {
109   DCHECK(CalledOnValidThread());
110   base::FundamentalValue value(in_value);
111   Set(path, value);
112 }
113
114 void CrosSettings::SetDouble(const std::string& path, double in_value) {
115   DCHECK(CalledOnValidThread());
116   base::FundamentalValue value(in_value);
117   Set(path, value);
118 }
119
120 void CrosSettings::SetString(const std::string& path,
121                              const std::string& in_value) {
122   DCHECK(CalledOnValidThread());
123   base::StringValue value(in_value);
124   Set(path, value);
125 }
126
127 void CrosSettings::AppendToList(const std::string& path,
128                                 const base::Value* value) {
129   DCHECK(CalledOnValidThread());
130   const base::Value* old_value = GetPref(path);
131   scoped_ptr<base::Value> new_value(
132       old_value ? old_value->DeepCopy() : new base::ListValue());
133   static_cast<base::ListValue*>(new_value.get())->Append(value->DeepCopy());
134   Set(path, *new_value);
135 }
136
137 void CrosSettings::RemoveFromList(const std::string& path,
138                                   const base::Value* value) {
139   DCHECK(CalledOnValidThread());
140   const base::Value* old_value = GetPref(path);
141   scoped_ptr<base::Value> new_value(
142       old_value ? old_value->DeepCopy() : new base::ListValue());
143   static_cast<base::ListValue*>(new_value.get())->Remove(*value, NULL);
144   Set(path, *new_value);
145 }
146
147 bool CrosSettings::GetBoolean(const std::string& path,
148                               bool* bool_value) const {
149   DCHECK(CalledOnValidThread());
150   const base::Value* value = GetPref(path);
151   if (value)
152     return value->GetAsBoolean(bool_value);
153   return false;
154 }
155
156 bool CrosSettings::GetInteger(const std::string& path,
157                               int* out_value) const {
158   DCHECK(CalledOnValidThread());
159   const base::Value* value = GetPref(path);
160   if (value)
161     return value->GetAsInteger(out_value);
162   return false;
163 }
164
165 bool CrosSettings::GetDouble(const std::string& path,
166                              double* out_value) const {
167   DCHECK(CalledOnValidThread());
168   const base::Value* value = GetPref(path);
169   if (value)
170     return value->GetAsDouble(out_value);
171   return false;
172 }
173
174 bool CrosSettings::GetString(const std::string& path,
175                              std::string* out_value) const {
176   DCHECK(CalledOnValidThread());
177   const base::Value* value = GetPref(path);
178   if (value)
179     return value->GetAsString(out_value);
180   return false;
181 }
182
183 bool CrosSettings::GetList(const std::string& path,
184                            const base::ListValue** out_value) const {
185   DCHECK(CalledOnValidThread());
186   const base::Value* value = GetPref(path);
187   if (value)
188     return value->GetAsList(out_value);
189   return false;
190 }
191
192 bool CrosSettings::GetDictionary(
193     const std::string& path,
194     const base::DictionaryValue** out_value) const {
195   DCHECK(CalledOnValidThread());
196   const base::Value* value = GetPref(path);
197   if (value)
198     return value->GetAsDictionary(out_value);
199   return false;
200 }
201
202 bool CrosSettings::FindEmailInList(const std::string& path,
203                                    const std::string& email) const {
204   DCHECK(CalledOnValidThread());
205   std::string canonicalized_email(
206       gaia::CanonicalizeEmail(gaia::SanitizeEmail(email)));
207   std::string wildcard_email;
208   std::string::size_type at_pos = canonicalized_email.find('@');
209   if (at_pos != std::string::npos) {
210     wildcard_email =
211         std::string("*").append(canonicalized_email.substr(at_pos));
212   }
213
214   const base::ListValue* list;
215   if (!GetList(path, &list))
216     return false;
217   for (base::ListValue::const_iterator entry(list->begin());
218        entry != list->end();
219        ++entry) {
220     std::string entry_string;
221     if (!(*entry)->GetAsString(&entry_string)) {
222       NOTREACHED();
223       continue;
224     }
225     std::string canonicalized_entry(
226         gaia::CanonicalizeEmail(gaia::SanitizeEmail(entry_string)));
227
228     if (canonicalized_entry == canonicalized_email ||
229         canonicalized_entry == wildcard_email) {
230       return true;
231     }
232   }
233   return false;
234 }
235
236 bool CrosSettings::AddSettingsProvider(CrosSettingsProvider* provider) {
237   DCHECK(CalledOnValidThread());
238   providers_.push_back(provider);
239
240   // Allow the provider to notify this object when settings have changed.
241   // Providers instantiated inside this class will have the same callback
242   // passed to their constructor, but doing it here allows for providers
243   // to be instantiated outside this class.
244   CrosSettingsProvider::NotifyObserversCallback notify_cb(
245       base::Bind(&CrosSettings::FireObservers, base::Unretained(this)));
246   provider->SetNotifyObserversCallback(notify_cb);
247   return true;
248 }
249
250 bool CrosSettings::RemoveSettingsProvider(CrosSettingsProvider* provider) {
251   DCHECK(CalledOnValidThread());
252   std::vector<CrosSettingsProvider*>::iterator it =
253       std::find(providers_.begin(), providers_.end(), provider);
254   if (it != providers_.end()) {
255     providers_.erase(it);
256     return true;
257   }
258   return false;
259 }
260
261 scoped_ptr<CrosSettings::ObserverSubscription>
262 CrosSettings::AddSettingsObserver(const std::string& path,
263                                   const base::Closure& callback) {
264   DCHECK(!path.empty());
265   DCHECK(!callback.is_null());
266   DCHECK(CalledOnValidThread());
267
268   if (!GetProvider(path)) {
269     NOTREACHED() << "Trying to add an observer for an unregistered setting: "
270                  << path;
271     return scoped_ptr<CrosSettings::ObserverSubscription>();
272   }
273
274   // Get the callback registry associated with the path.
275   base::CallbackList<void(void)>* registry = NULL;
276   SettingsObserverMap::iterator observer_iterator =
277       settings_observers_.find(path);
278   if (observer_iterator == settings_observers_.end()) {
279     registry = new base::CallbackList<void(void)>;
280     settings_observers_[path] = registry;
281   } else {
282     registry = observer_iterator->second;
283   }
284
285   return registry->Add(callback);
286 }
287
288 CrosSettingsProvider* CrosSettings::GetProvider(
289     const std::string& path) const {
290   for (size_t i = 0; i < providers_.size(); ++i) {
291     if (providers_[i]->HandlesSetting(path))
292       return providers_[i];
293   }
294   return NULL;
295 }
296
297 void CrosSettings::FireObservers(const std::string& path) {
298   DCHECK(CalledOnValidThread());
299   SettingsObserverMap::iterator observer_iterator =
300       settings_observers_.find(path);
301   if (observer_iterator == settings_observers_.end())
302     return;
303
304   observer_iterator->second->Notify();
305 }
306
307 ScopedTestCrosSettings::ScopedTestCrosSettings() {
308   CrosSettings::Initialize();
309 }
310
311 ScopedTestCrosSettings::~ScopedTestCrosSettings() {
312   CrosSettings::Shutdown();
313 }
314
315 }  // namespace chromeos