blob: fda53a7cca864b36439e715d657d934409a6e723 [file] [log] [blame]
[email protected]c0858b02010-05-12 15:03:321// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]37858e52010-08-26 00:22:025#include "chrome/browser/prefs/pref_service.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]1cb92b82010-03-08 23:12:157#include <algorithm>
8#include <string>
9
[email protected]a92b8642009-05-05 23:38:5610#include "app/l10n_util.h"
[email protected]aa4dc5e22010-06-16 11:32:5411#include "base/command_line.h"
[email protected]c02c853d72010-08-07 06:23:2412#include "base/file_path.h"
[email protected]1d01d412010-08-20 00:36:0113#include "base/file_util.h"
initial.commit09911bf2008-07-26 23:55:2914#include "base/logging.h"
15#include "base/message_loop.h"
[email protected]835d7c82010-10-14 04:38:3816#include "base/metrics/histogram.h"
[email protected]807204142009-05-05 03:31:4417#include "base/stl_util-inl.h"
[email protected]e83326f2010-07-31 17:29:2518#include "base/string_number_conversions.h"
initial.commit09911bf2008-07-26 23:55:2919#include "base/string_util.h"
[email protected]66de4f092009-09-04 23:59:4020#include "base/sys_string_conversions.h"
[email protected]1cb92b82010-03-08 23:12:1521#include "base/utf_string_conversions.h"
[email protected]66de4f092009-09-04 23:59:4022#include "build/build_config.h"
[email protected]017a7a112010-10-12 16:38:2723#include "chrome/browser/browser_thread.h"
[email protected]39d9f62c2010-12-03 10:48:5024#include "chrome/browser/prefs/pref_notifier.h"
25#include "chrome/browser/prefs/pref_value_store.h"
[email protected]8ecad5e2010-12-02 21:18:3326#include "chrome/browser/profiles/profile.h"
initial.commit09911bf2008-07-26 23:55:2927#include "chrome/common/notification_service.h"
[email protected]ba399672010-04-06 15:42:3928#include "grit/chromium_strings.h"
[email protected]34ac8f32009-02-22 23:03:2729#include "grit/generated_resources.h"
initial.commit09911bf2008-07-26 23:55:2930
31namespace {
32
initial.commit09911bf2008-07-26 23:55:2933// A helper function for RegisterLocalized*Pref that creates a Value* based on
34// the string value in the locale dll. Because we control the values in a
35// locale dll, this should always return a Value of the appropriate type.
36Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) {
[email protected]16b527162010-08-15 18:37:1037 std::string resource_string = l10n_util::GetStringUTF8(message_id);
initial.commit09911bf2008-07-26 23:55:2938 DCHECK(!resource_string.empty());
39 switch (type) {
40 case Value::TYPE_BOOLEAN: {
[email protected]16b527162010-08-15 18:37:1041 if ("true" == resource_string)
initial.commit09911bf2008-07-26 23:55:2942 return Value::CreateBooleanValue(true);
[email protected]16b527162010-08-15 18:37:1043 if ("false" == resource_string)
initial.commit09911bf2008-07-26 23:55:2944 return Value::CreateBooleanValue(false);
45 break;
46 }
47
48 case Value::TYPE_INTEGER: {
[email protected]e83326f2010-07-31 17:29:2549 int val;
[email protected]16b527162010-08-15 18:37:1050 base::StringToInt(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2551 return Value::CreateIntegerValue(val);
initial.commit09911bf2008-07-26 23:55:2952 }
53
54 case Value::TYPE_REAL: {
[email protected]e83326f2010-07-31 17:29:2555 double val;
[email protected]16b527162010-08-15 18:37:1056 base::StringToDouble(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2557 return Value::CreateRealValue(val);
initial.commit09911bf2008-07-26 23:55:2958 }
59
60 case Value::TYPE_STRING: {
61 return Value::CreateStringValue(resource_string);
initial.commit09911bf2008-07-26 23:55:2962 }
63
64 default: {
[email protected]b154e6f2009-03-06 01:52:4065 NOTREACHED() <<
[email protected]c3b54f372010-09-14 08:25:0766 "list and dictionary types cannot have default locale values";
initial.commit09911bf2008-07-26 23:55:2967 }
68 }
69 NOTREACHED();
70 return Value::CreateNullValue();
71}
72
[email protected]ba399672010-04-06 15:42:3973// Forwards a notification after a PostMessage so that we can wait for the
74// MessageLoop to run.
75void NotifyReadError(PrefService* pref, int message_id) {
76 Source<PrefService> source(pref);
77 NotificationService::current()->Notify(NotificationType::PROFILE_ERROR,
78 source, Details<int>(&message_id));
79}
80
initial.commit09911bf2008-07-26 23:55:2981} // namespace
82
[email protected]db198b22010-07-12 16:48:4983// static
[email protected]a9c23a52010-08-04 09:13:4484PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
85 Profile* profile) {
[email protected]1d01d412010-08-20 00:36:0186#if defined(OS_LINUX)
87 // We'd like to see what fraction of our users have the preferences
88 // stored on a network file system, as we've had no end of troubles
89 // with NFS/AFS.
90 // TODO(evanm): remove this once we've collected state.
91 file_util::FileSystemType fstype;
92 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
93 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
94 static_cast<int>(fstype),
95 file_util::FILE_SYSTEM_TYPE_COUNT);
96 }
97#endif
98
[email protected]fa26b3d52010-08-06 08:51:5099 return new PrefService(
100 PrefValueStore::CreatePrefValueStore(pref_filename, profile, false));
[email protected]db198b22010-07-12 16:48:49101}
102
103// static
[email protected]fa26b3d52010-08-06 08:51:50104PrefService* PrefService::CreateUserPrefService(const FilePath& pref_filename) {
105 return new PrefService(
106 PrefValueStore::CreatePrefValueStore(pref_filename, NULL, true));
[email protected]d8b08c92010-06-07 13:13:28107}
108
109PrefService::PrefService(PrefValueStore* pref_value_store)
110 : pref_value_store_(pref_value_store) {
[email protected]d81288a02010-08-18 07:25:50111 pref_notifier_.reset(new PrefNotifier(this, pref_value_store));
[email protected]277404c22010-04-22 13:09:45112 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29113}
114
115PrefService::~PrefService() {
116 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29117 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
118 prefs_.clear();
initial.commit09911bf2008-07-26 23:55:29119}
120
[email protected]277404c22010-04-22 13:09:45121void PrefService::InitFromStorage() {
122 PrefStore::PrefReadError error = LoadPersistentPrefs();
123 if (error == PrefStore::PREF_READ_ERROR_NONE)
[email protected]ba399672010-04-06 15:42:39124 return;
initial.commit09911bf2008-07-26 23:55:29125
[email protected]ba399672010-04-06 15:42:39126 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
127 // an example problem that this can cause.
128 // Do some diagnosis and try to avoid losing data.
129 int message_id = 0;
[email protected]277404c22010-04-22 13:09:45130 if (error <= PrefStore::PREF_READ_ERROR_JSON_TYPE) {
[email protected]ba399672010-04-06 15:42:39131 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
[email protected]277404c22010-04-22 13:09:45132 } else if (error != PrefStore::PREF_READ_ERROR_NO_FILE) {
[email protected]ba399672010-04-06 15:42:39133 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
134 }
135
136 if (message_id) {
[email protected]8bac2352010-10-10 18:53:21137 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
[email protected]ba399672010-04-06 15:42:39138 NewRunnableFunction(&NotifyReadError, this, message_id));
139 }
140 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
141}
142
143bool PrefService::ReloadPersistentPrefs() {
[email protected]277404c22010-04-22 13:09:45144 return (LoadPersistentPrefs() == PrefStore::PREF_READ_ERROR_NONE);
[email protected]ba399672010-04-06 15:42:39145}
146
[email protected]277404c22010-04-22 13:09:45147PrefStore::PrefReadError PrefService::LoadPersistentPrefs() {
[email protected]ba399672010-04-06 15:42:39148 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39149
[email protected]d8b08c92010-06-07 13:13:28150 PrefStore::PrefReadError pref_error = pref_value_store_->ReadPrefs();
[email protected]7aa0a962010-04-21 17:24:42151
[email protected]7aa0a962010-04-21 17:24:42152 for (PreferenceSet::iterator it = prefs_.begin();
153 it != prefs_.end(); ++it) {
[email protected]c3b54f372010-09-14 08:25:07154 (*it)->pref_service_ = this;
[email protected]7aa0a962010-04-21 17:24:42155 }
156
[email protected]277404c22010-04-22 13:09:45157 return pref_error;
initial.commit09911bf2008-07-26 23:55:29158}
159
[email protected]6faa0e0d2009-04-28 06:50:36160bool PrefService::SavePersistentPrefs() {
161 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29162
[email protected]d8b08c92010-06-07 13:13:28163 return pref_value_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36164}
165
[email protected]6c1164042009-05-08 14:41:08166void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36167 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39168
[email protected]d8b08c92010-06-07 13:13:28169 pref_value_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29170}
171
[email protected]57ecc4b2010-08-11 03:02:51172void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29173 bool default_value) {
[email protected]c3b54f372010-09-14 08:25:07174 RegisterPreference(path, Value::CreateBooleanValue(default_value));
initial.commit09911bf2008-07-26 23:55:29175}
176
[email protected]57ecc4b2010-08-11 03:02:51177void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]c3b54f372010-09-14 08:25:07178 RegisterPreference(path, Value::CreateIntegerValue(default_value));
initial.commit09911bf2008-07-26 23:55:29179}
180
[email protected]57ecc4b2010-08-11 03:02:51181void PrefService::RegisterRealPref(const char* path, double default_value) {
[email protected]c3b54f372010-09-14 08:25:07182 RegisterPreference(path, Value::CreateRealValue(default_value));
initial.commit09911bf2008-07-26 23:55:29183}
184
[email protected]57ecc4b2010-08-11 03:02:51185void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04186 const std::string& default_value) {
[email protected]c3b54f372010-09-14 08:25:07187 RegisterPreference(path, Value::CreateStringValue(default_value));
initial.commit09911bf2008-07-26 23:55:29188}
189
[email protected]57ecc4b2010-08-11 03:02:51190void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25191 const FilePath& default_value) {
[email protected]c3b54f372010-09-14 08:25:07192 RegisterPreference(path, Value::CreateStringValue(default_value.value()));
[email protected]b9636002009-03-04 00:05:25193}
194
[email protected]57ecc4b2010-08-11 03:02:51195void PrefService::RegisterListPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07196 RegisterPreference(path, new ListValue());
initial.commit09911bf2008-07-26 23:55:29197}
198
[email protected]57ecc4b2010-08-11 03:02:51199void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07200 RegisterPreference(path, new DictionaryValue());
initial.commit09911bf2008-07-26 23:55:29201}
202
[email protected]57ecc4b2010-08-11 03:02:51203void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29204 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07205 RegisterPreference(
206 path,
initial.commit09911bf2008-07-26 23:55:29207 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29208}
209
[email protected]57ecc4b2010-08-11 03:02:51210void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29211 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07212 RegisterPreference(
213 path,
initial.commit09911bf2008-07-26 23:55:29214 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29215}
216
[email protected]57ecc4b2010-08-11 03:02:51217void PrefService::RegisterLocalizedRealPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29218 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07219 RegisterPreference(
220 path,
initial.commit09911bf2008-07-26 23:55:29221 CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29222}
223
[email protected]57ecc4b2010-08-11 03:02:51224void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29225 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07226 RegisterPreference(
227 path,
initial.commit09911bf2008-07-26 23:55:29228 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29229}
230
[email protected]57ecc4b2010-08-11 03:02:51231bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29232 DCHECK(CalledOnValidThread());
233
234 bool result = false;
initial.commit09911bf2008-07-26 23:55:29235
236 const Preference* pref = FindPreference(path);
237 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40238 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29239 return result;
240 }
241 bool rv = pref->GetValue()->GetAsBoolean(&result);
242 DCHECK(rv);
243 return result;
244}
245
[email protected]57ecc4b2010-08-11 03:02:51246int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29247 DCHECK(CalledOnValidThread());
248
249 int result = 0;
initial.commit09911bf2008-07-26 23:55:29250
251 const Preference* pref = FindPreference(path);
252 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40253 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29254 return result;
255 }
256 bool rv = pref->GetValue()->GetAsInteger(&result);
257 DCHECK(rv);
258 return result;
259}
260
[email protected]57ecc4b2010-08-11 03:02:51261double PrefService::GetReal(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29262 DCHECK(CalledOnValidThread());
263
264 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29265
266 const Preference* pref = FindPreference(path);
267 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40268 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29269 return result;
270 }
271 bool rv = pref->GetValue()->GetAsReal(&result);
272 DCHECK(rv);
273 return result;
274}
275
[email protected]57ecc4b2010-08-11 03:02:51276std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29277 DCHECK(CalledOnValidThread());
278
[email protected]ddd231e2010-06-29 20:35:19279 std::string result;
[email protected]8e50b602009-03-03 22:59:43280
initial.commit09911bf2008-07-26 23:55:29281 const Preference* pref = FindPreference(path);
282 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40283 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29284 return result;
285 }
286 bool rv = pref->GetValue()->GetAsString(&result);
287 DCHECK(rv);
288 return result;
289}
290
[email protected]57ecc4b2010-08-11 03:02:51291FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25292 DCHECK(CalledOnValidThread());
293
294 FilePath::StringType result;
[email protected]b9636002009-03-04 00:05:25295
296 const Preference* pref = FindPreference(path);
297 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40298 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25299 return FilePath(result);
300 }
301 bool rv = pref->GetValue()->GetAsString(&result);
302 DCHECK(rv);
[email protected]66de4f092009-09-04 23:59:40303#if defined(OS_POSIX)
304 // We store filepaths as UTF8, so convert it back to the system type.
305 result = base::SysWideToNativeMB(UTF8ToWide(result));
306#endif
[email protected]b9636002009-03-04 00:05:25307 return FilePath(result);
308}
309
[email protected]57ecc4b2010-08-11 03:02:51310bool PrefService::HasPrefPath(const char* path) const {
[email protected]d8b08c92010-06-07 13:13:28311 return pref_value_store_->HasPrefPath(path);
initial.commit09911bf2008-07-26 23:55:29312}
313
314const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51315 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29316 DCHECK(CalledOnValidThread());
[email protected]99cc9a02010-09-17 07:53:28317 Preference p(this, pref_name);
initial.commit09911bf2008-07-26 23:55:29318 PreferenceSet::const_iterator it = prefs_.find(&p);
319 return it == prefs_.end() ? NULL : *it;
320}
321
[email protected]57ecc4b2010-08-11 03:02:51322bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48323 const Preference* pref = FindPreference(pref_name);
324 if (pref && pref->IsManaged()) {
325 return true;
326 }
327 return false;
328}
329
[email protected]57ecc4b2010-08-11 03:02:51330const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29331 DCHECK(CalledOnValidThread());
332
initial.commit09911bf2008-07-26 23:55:29333 const Preference* pref = FindPreference(path);
334 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40335 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29336 return NULL;
337 }
338 const Value* value = pref->GetValue();
339 if (value->GetType() == Value::TYPE_NULL)
340 return NULL;
341 return static_cast<const DictionaryValue*>(value);
342}
343
[email protected]57ecc4b2010-08-11 03:02:51344const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29345 DCHECK(CalledOnValidThread());
346
initial.commit09911bf2008-07-26 23:55:29347 const Preference* pref = FindPreference(path);
348 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40349 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29350 return NULL;
351 }
352 const Value* value = pref->GetValue();
353 if (value->GetType() == Value::TYPE_NULL)
354 return NULL;
355 return static_cast<const ListValue*>(value);
356}
357
[email protected]39d9f62c2010-12-03 10:48:50358bool PrefService::ReadOnly() const {
359 return pref_value_store_->ReadOnly();
360}
361
[email protected]57ecc4b2010-08-11 03:02:51362void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29363 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50364 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29365}
366
[email protected]57ecc4b2010-08-11 03:02:51367void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29368 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50369 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29370}
371
[email protected]c3b54f372010-09-14 08:25:07372void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29373 DCHECK(CalledOnValidThread());
374
[email protected]c3b54f372010-09-14 08:25:07375 // The main code path takes ownership, but most don't. We'll be safe.
376 scoped_ptr<Value> scoped_value(default_value);
377
378 if (FindPreference(path)) {
379 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29380 return;
381 }
[email protected]c3b54f372010-09-14 08:25:07382
[email protected]99cc9a02010-09-17 07:53:28383 Value::ValueType orig_type = default_value->GetType();
384 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
385 "invalid preference type: " << orig_type;
386
[email protected]c3b54f372010-09-14 08:25:07387 // We set the default value of dictionaries and lists to be null so it's
388 // easier for callers to check for empty dict/list prefs. The PrefValueStore
389 // accepts ownership of the value (null or default_value).
[email protected]c3b54f372010-09-14 08:25:07390 if (Value::TYPE_LIST == orig_type || Value::TYPE_DICTIONARY == orig_type) {
391 pref_value_store_->SetDefaultPrefValue(path, Value::CreateNullValue());
392 } else {
393 // Hand off ownership.
[email protected]ce1850e92010-10-15 08:40:58394 DCHECK(!PrefStore::IsUseDefaultSentinelValue(default_value));
[email protected]c3b54f372010-09-14 08:25:07395 pref_value_store_->SetDefaultPrefValue(path, scoped_value.release());
396 }
397
[email protected]99cc9a02010-09-17 07:53:28398 pref_value_store_->RegisterPreferenceType(path, orig_type);
399 prefs_.insert(new Preference(this, path));
initial.commit09911bf2008-07-26 23:55:29400}
401
[email protected]57ecc4b2010-08-11 03:02:51402void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29403 DCHECK(CalledOnValidThread());
404
405 const Preference* pref = FindPreference(path);
406 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40407 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29408 return;
409 }
[email protected]c3b54f372010-09-14 08:25:07410 if (pref_value_store_->RemoveUserPrefValue(path))
411 pref_notifier_->OnUserPreferenceSet(path);
initial.commit09911bf2008-07-26 23:55:29412}
413
[email protected]57ecc4b2010-08-11 03:02:51414void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39415 DCHECK(CalledOnValidThread());
416
417 const Preference* pref = FindPreference(path);
418 if (!pref) {
419 NOTREACHED() << "Trying to write an unregistered pref: " << path;
420 return;
421 }
[email protected]ecde2742010-04-02 17:36:18422
[email protected]c3b54f372010-09-14 08:25:07423 // Allow dictionary and list types to be set to null, which removes their
424 // user values.
425 bool value_changed = false;
[email protected]ecde2742010-04-02 17:36:18426 if (value.GetType() == Value::TYPE_NULL &&
[email protected]99cc9a02010-09-17 07:53:28427 (pref->GetType() == Value::TYPE_DICTIONARY ||
428 pref->GetType() == Value::TYPE_LIST)) {
[email protected]c3b54f372010-09-14 08:25:07429 value_changed = pref_value_store_->RemoveUserPrefValue(path);
[email protected]99cc9a02010-09-17 07:53:28430 } else if (pref->GetType() != value.GetType()) {
431 NOTREACHED() << "Trying to set pref " << path
432 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07433 << " to value of type " << value.GetType();
434 } else {
435 value_changed = pref_value_store_->SetUserPrefValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18436 }
437
[email protected]c3b54f372010-09-14 08:25:07438 if (value_changed)
439 pref_notifier_->OnUserPreferenceSet(path);
[email protected]a048d7e42009-12-01 01:02:39440}
441
[email protected]57ecc4b2010-08-11 03:02:51442void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07443 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29444}
445
[email protected]57ecc4b2010-08-11 03:02:51446void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07447 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29448}
449
[email protected]57ecc4b2010-08-11 03:02:51450void PrefService::SetReal(const char* path, double value) {
[email protected]c3b54f372010-09-14 08:25:07451 SetUserPrefValue(path, Value::CreateRealValue(value));
initial.commit09911bf2008-07-26 23:55:29452}
453
[email protected]57ecc4b2010-08-11 03:02:51454void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07455 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29456}
457
[email protected]57ecc4b2010-08-11 03:02:51458void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]66de4f092009-09-04 23:59:40459#if defined(OS_POSIX)
460 // Value::SetString only knows about UTF8 strings, so convert the path from
461 // the system native value to UTF8.
462 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value()));
[email protected]d8b08c92010-06-07 13:13:28463 Value* new_value = Value::CreateStringValue(path_utf8);
[email protected]66de4f092009-09-04 23:59:40464#else
[email protected]d8b08c92010-06-07 13:13:28465 Value* new_value = Value::CreateStringValue(value.value());
[email protected]66de4f092009-09-04 23:59:40466#endif
[email protected]b9636002009-03-04 00:05:25467
[email protected]c3b54f372010-09-14 08:25:07468 SetUserPrefValue(path, new_value);
[email protected]b9636002009-03-04 00:05:25469}
470
[email protected]57ecc4b2010-08-11 03:02:51471void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07472 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32473}
474
[email protected]57ecc4b2010-08-11 03:02:51475int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32476 DCHECK(CalledOnValidThread());
477
[email protected]0bb1a622009-03-04 03:22:32478 const Preference* pref = FindPreference(path);
479 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40480 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08481 return 0;
[email protected]0bb1a622009-03-04 03:22:32482 }
[email protected]dc9a6762010-08-16 07:13:53483 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32484 bool rv = pref->GetValue()->GetAsString(&result);
485 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25486
487 int64 val;
[email protected]dc9a6762010-08-16 07:13:53488 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25489 return val;
[email protected]0bb1a622009-03-04 03:22:32490}
491
[email protected]57ecc4b2010-08-11 03:02:51492void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07493 RegisterPreference(
494 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32495}
496
[email protected]57ecc4b2010-08-11 03:02:51497DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29498 DCHECK(CalledOnValidThread());
499
500 const Preference* pref = FindPreference(path);
501 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40502 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29503 return NULL;
504 }
[email protected]99cc9a02010-09-17 07:53:28505 if (pref->GetType() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40506 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29507 return NULL;
508 }
509
510 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28511 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53512 // Look for an existing preference in the user store. If it doesn't
513 // exist or isn't the correct type, create a new user preference.
514 if (!pref_value_store_->GetUserValue(path, &tmp_value) ||
[email protected]91761242010-06-10 15:35:37515 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29516 dict = new DictionaryValue;
[email protected]d8b08c92010-06-07 13:13:28517 pref_value_store_->SetUserPrefValue(path, dict);
518 } else {
519 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29520 }
521 return dict;
522}
523
[email protected]57ecc4b2010-08-11 03:02:51524ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29525 DCHECK(CalledOnValidThread());
526
527 const Preference* pref = FindPreference(path);
528 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40529 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29530 return NULL;
531 }
[email protected]99cc9a02010-09-17 07:53:28532 if (pref->GetType() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40533 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29534 return NULL;
535 }
536
537 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28538 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53539 // Look for an existing preference in the user store. If it doesn't
540 // exist or isn't the correct type, create a new user preference.
541 if (!pref_value_store_->GetUserValue(path, &tmp_value) ||
[email protected]c3b54f372010-09-14 08:25:07542 !tmp_value->IsType(Value::TYPE_LIST)) {
initial.commit09911bf2008-07-26 23:55:29543 list = new ListValue;
[email protected]d8b08c92010-06-07 13:13:28544 pref_value_store_->SetUserPrefValue(path, list);
545 } else {
546 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29547 }
548 return list;
549}
550
[email protected]57ecc4b2010-08-11 03:02:51551Value* PrefService::GetPrefCopy(const char* path) {
initial.commit09911bf2008-07-26 23:55:29552 DCHECK(CalledOnValidThread());
553
554 const Preference* pref = FindPreference(path);
555 DCHECK(pref);
556 return pref->GetValue()->DeepCopy();
557}
558
[email protected]c3b54f372010-09-14 08:25:07559void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
560 DCHECK(CalledOnValidThread());
561
562 const Preference* pref = FindPreference(path);
563 if (!pref) {
564 NOTREACHED() << "Trying to write an unregistered pref: " << path;
565 return;
566 }
567 if (pref->IsManaged()) {
568 NOTREACHED() << "Preference is managed: " << path;
569 return;
570 }
[email protected]99cc9a02010-09-17 07:53:28571 if (pref->GetType() != new_value->GetType()) {
572 NOTREACHED() << "Trying to set pref " << path
573 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07574 << " to value of type " << new_value->GetType();
575 return;
576 }
577
578 if (pref_value_store_->SetUserPrefValue(path, new_value))
579 pref_notifier_->OnUserPreferenceSet(path);
580}
581
initial.commit09911bf2008-07-26 23:55:29582///////////////////////////////////////////////////////////////////////////////
583// PrefService::Preference
584
[email protected]c3b54f372010-09-14 08:25:07585PrefService::Preference::Preference(const PrefService* service,
[email protected]99cc9a02010-09-17 07:53:28586 const char* name)
587 : name_(name),
[email protected]c3b54f372010-09-14 08:25:07588 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29589 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07590 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28591}
592
593Value::ValueType PrefService::Preference::GetType() const {
594 return pref_service_->pref_value_store_->GetRegisteredType(name_);
initial.commit09911bf2008-07-26 23:55:29595}
596
597const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07598 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29599 "Must register pref before getting its value";
600
[email protected]c3b54f372010-09-14 08:25:07601 Value* found_value = NULL;
[email protected]99cc9a02010-09-17 07:53:28602 if (pref_service_->pref_value_store_->GetValue(name_, &found_value))
603 return found_value;
initial.commit09911bf2008-07-26 23:55:29604
[email protected]c3b54f372010-09-14 08:25:07605 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28606 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07607 return NULL;
[email protected]40a47c162010-09-09 11:14:01608}
609
610bool PrefService::Preference::IsManaged() const {
[email protected]be1c6e922010-11-17 12:49:17611 PrefValueStore* pref_value_store =
612 pref_service_->pref_value_store_;
613 return pref_value_store->PrefValueInManagedPlatformStore(name_.c_str()) ||
614 pref_value_store->PrefValueInDeviceManagementStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01615}
616
617bool PrefService::Preference::HasExtensionSetting() const {
[email protected]c3b54f372010-09-14 08:25:07618 return pref_service_->pref_value_store_->
619 PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01620}
621
622bool PrefService::Preference::HasUserSetting() const {
[email protected]c3b54f372010-09-14 08:25:07623 return pref_service_->pref_value_store_->
624 PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01625}
626
627bool PrefService::Preference::IsExtensionControlled() const {
[email protected]c3b54f372010-09-14 08:25:07628 return pref_service_->pref_value_store_->
629 PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01630}
631
632bool PrefService::Preference::IsUserControlled() const {
[email protected]c3b54f372010-09-14 08:25:07633 return pref_service_->pref_value_store_->
634 PrefValueFromUserStore(name_.c_str());
635}
636
637bool PrefService::Preference::IsDefaultValue() const {
638 return pref_service_->pref_value_store_->
639 PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35640}
[email protected]74379bc52010-07-21 13:54:08641
642bool PrefService::Preference::IsUserModifiable() const {
[email protected]c3b54f372010-09-14 08:25:07643 return pref_service_->pref_value_store_->
644 PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08645}