Upstream version 11.40.277.0
[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,
204                                    bool* wildcard_match) const {
205   DCHECK(CalledOnValidThread());
206   std::string canonicalized_email(
207       gaia::CanonicalizeEmail(gaia::SanitizeEmail(email)));
208   std::string wildcard_email;
209   std::string::size_type at_pos = canonicalized_email.find('@');
210   if (at_pos != std::string::npos) {
211     wildcard_email =
212         std::string("*").append(canonicalized_email.substr(at_pos));
213   }
214
215   if (wildcard_match)
216     *wildcard_match = false;
217
218   const base::ListValue* list;
219   if (!GetList(path, &list))
220     return false;
221
222   bool found_wildcard_match = false;
223   for (base::ListValue::const_iterator entry(list->begin());
224        entry != list->end();
225        ++entry) {
226     std::string entry_string;
227     if (!(*entry)->GetAsString(&entry_string)) {
228       NOTREACHED();
229       continue;
230     }
231     std::string canonicalized_entry(
232         gaia::CanonicalizeEmail(gaia::SanitizeEmail(entry_string)));
233
234     if (canonicalized_entry != wildcard_email &&
235         canonicalized_entry == canonicalized_email) {
236       return true;
237     }
238
239     // If there is a wildcard match, don't exit early. There might be an exact
240     // match further down the list that should take precedence if present.
241     if (canonicalized_entry == wildcard_email)
242       found_wildcard_match = true;
243   }
244
245   if (wildcard_match)
246     *wildcard_match = found_wildcard_match;
247
248   return found_wildcard_match;
249 }
250
251 bool CrosSettings::AddSettingsProvider(CrosSettingsProvider* provider) {
252   DCHECK(CalledOnValidThread());
253   providers_.push_back(provider);
254
255   // Allow the provider to notify this object when settings have changed.
256   // Providers instantiated inside this class will have the same callback
257   // passed to their constructor, but doing it here allows for providers
258   // to be instantiated outside this class.
259   CrosSettingsProvider::NotifyObserversCallback notify_cb(
260       base::Bind(&CrosSettings::FireObservers, base::Unretained(this)));
261   provider->SetNotifyObserversCallback(notify_cb);
262   return true;
263 }
264
265 bool CrosSettings::RemoveSettingsProvider(CrosSettingsProvider* provider) {
266   DCHECK(CalledOnValidThread());
267   std::vector<CrosSettingsProvider*>::iterator it =
268       std::find(providers_.begin(), providers_.end(), provider);
269   if (it != providers_.end()) {
270     providers_.erase(it);
271     return true;
272   }
273   return false;
274 }
275
276 scoped_ptr<CrosSettings::ObserverSubscription>
277 CrosSettings::AddSettingsObserver(const std::string& path,
278                                   const base::Closure& callback) {
279   DCHECK(!path.empty());
280   DCHECK(!callback.is_null());
281   DCHECK(CalledOnValidThread());
282
283   if (!GetProvider(path)) {
284     NOTREACHED() << "Trying to add an observer for an unregistered setting: "
285                  << path;
286     return scoped_ptr<CrosSettings::ObserverSubscription>();
287   }
288
289   // Get the callback registry associated with the path.
290   base::CallbackList<void(void)>* registry = NULL;
291   SettingsObserverMap::iterator observer_iterator =
292       settings_observers_.find(path);
293   if (observer_iterator == settings_observers_.end()) {
294     registry = new base::CallbackList<void(void)>;
295     settings_observers_[path] = registry;
296   } else {
297     registry = observer_iterator->second;
298   }
299
300   return registry->Add(callback);
301 }
302
303 CrosSettingsProvider* CrosSettings::GetProvider(
304     const std::string& path) const {
305   for (size_t i = 0; i < providers_.size(); ++i) {
306     if (providers_[i]->HandlesSetting(path))
307       return providers_[i];
308   }
309   return NULL;
310 }
311
312 void CrosSettings::FireObservers(const std::string& path) {
313   DCHECK(CalledOnValidThread());
314   SettingsObserverMap::iterator observer_iterator =
315       settings_observers_.find(path);
316   if (observer_iterator == settings_observers_.end())
317     return;
318
319   observer_iterator->second->Notify();
320 }
321
322 ScopedTestCrosSettings::ScopedTestCrosSettings() {
323   CrosSettings::Initialize();
324 }
325
326 ScopedTestCrosSettings::~ScopedTestCrosSettings() {
327   CrosSettings::Shutdown();
328 }
329
330 }  // namespace chromeos