blob: 80b3d38c064aefc3fa5cb29000e78fbb115ec22b [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]fa26b3d52010-08-06 08:51:5024#include "chrome/browser/profile.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/notification_service.h"
[email protected]ba399672010-04-06 15:42:3926#include "grit/chromium_strings.h"
[email protected]34ac8f32009-02-22 23:03:2727#include "grit/generated_resources.h"
initial.commit09911bf2008-07-26 23:55:2928
29namespace {
30
initial.commit09911bf2008-07-26 23:55:2931// A helper function for RegisterLocalized*Pref that creates a Value* based on
32// the string value in the locale dll. Because we control the values in a
33// locale dll, this should always return a Value of the appropriate type.
34Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) {
[email protected]16b527162010-08-15 18:37:1035 std::string resource_string = l10n_util::GetStringUTF8(message_id);
initial.commit09911bf2008-07-26 23:55:2936 DCHECK(!resource_string.empty());
37 switch (type) {
38 case Value::TYPE_BOOLEAN: {
[email protected]16b527162010-08-15 18:37:1039 if ("true" == resource_string)
initial.commit09911bf2008-07-26 23:55:2940 return Value::CreateBooleanValue(true);
[email protected]16b527162010-08-15 18:37:1041 if ("false" == resource_string)
initial.commit09911bf2008-07-26 23:55:2942 return Value::CreateBooleanValue(false);
43 break;
44 }
45
46 case Value::TYPE_INTEGER: {
[email protected]e83326f2010-07-31 17:29:2547 int val;
[email protected]16b527162010-08-15 18:37:1048 base::StringToInt(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2549 return Value::CreateIntegerValue(val);
initial.commit09911bf2008-07-26 23:55:2950 }
51
52 case Value::TYPE_REAL: {
[email protected]e83326f2010-07-31 17:29:2553 double val;
[email protected]16b527162010-08-15 18:37:1054 base::StringToDouble(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2555 return Value::CreateRealValue(val);
initial.commit09911bf2008-07-26 23:55:2956 }
57
58 case Value::TYPE_STRING: {
59 return Value::CreateStringValue(resource_string);
initial.commit09911bf2008-07-26 23:55:2960 }
61
62 default: {
[email protected]b154e6f2009-03-06 01:52:4063 NOTREACHED() <<
[email protected]c3b54f372010-09-14 08:25:0764 "list and dictionary types cannot have default locale values";
initial.commit09911bf2008-07-26 23:55:2965 }
66 }
67 NOTREACHED();
68 return Value::CreateNullValue();
69}
70
[email protected]ba399672010-04-06 15:42:3971// Forwards a notification after a PostMessage so that we can wait for the
72// MessageLoop to run.
73void NotifyReadError(PrefService* pref, int message_id) {
74 Source<PrefService> source(pref);
75 NotificationService::current()->Notify(NotificationType::PROFILE_ERROR,
76 source, Details<int>(&message_id));
77}
78
initial.commit09911bf2008-07-26 23:55:2979} // namespace
80
[email protected]db198b22010-07-12 16:48:4981// static
[email protected]a9c23a52010-08-04 09:13:4482PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
83 Profile* profile) {
[email protected]1d01d412010-08-20 00:36:0184#if defined(OS_LINUX)
85 // We'd like to see what fraction of our users have the preferences
86 // stored on a network file system, as we've had no end of troubles
87 // with NFS/AFS.
88 // TODO(evanm): remove this once we've collected state.
89 file_util::FileSystemType fstype;
90 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
91 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
92 static_cast<int>(fstype),
93 file_util::FILE_SYSTEM_TYPE_COUNT);
94 }
95#endif
96
[email protected]fa26b3d52010-08-06 08:51:5097 return new PrefService(
98 PrefValueStore::CreatePrefValueStore(pref_filename, profile, false));
[email protected]db198b22010-07-12 16:48:4999}
100
101// static
[email protected]fa26b3d52010-08-06 08:51:50102PrefService* PrefService::CreateUserPrefService(const FilePath& pref_filename) {
103 return new PrefService(
104 PrefValueStore::CreatePrefValueStore(pref_filename, NULL, true));
[email protected]d8b08c92010-06-07 13:13:28105}
106
107PrefService::PrefService(PrefValueStore* pref_value_store)
108 : pref_value_store_(pref_value_store) {
[email protected]d81288a02010-08-18 07:25:50109 pref_notifier_.reset(new PrefNotifier(this, pref_value_store));
[email protected]277404c22010-04-22 13:09:45110 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29111}
112
113PrefService::~PrefService() {
114 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29115 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
116 prefs_.clear();
initial.commit09911bf2008-07-26 23:55:29117}
118
[email protected]277404c22010-04-22 13:09:45119void PrefService::InitFromStorage() {
120 PrefStore::PrefReadError error = LoadPersistentPrefs();
121 if (error == PrefStore::PREF_READ_ERROR_NONE)
[email protected]ba399672010-04-06 15:42:39122 return;
initial.commit09911bf2008-07-26 23:55:29123
[email protected]ba399672010-04-06 15:42:39124 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
125 // an example problem that this can cause.
126 // Do some diagnosis and try to avoid losing data.
127 int message_id = 0;
[email protected]277404c22010-04-22 13:09:45128 if (error <= PrefStore::PREF_READ_ERROR_JSON_TYPE) {
[email protected]ba399672010-04-06 15:42:39129 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
[email protected]277404c22010-04-22 13:09:45130 } else if (error != PrefStore::PREF_READ_ERROR_NO_FILE) {
[email protected]ba399672010-04-06 15:42:39131 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
132 }
133
134 if (message_id) {
[email protected]8bac2352010-10-10 18:53:21135 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
[email protected]ba399672010-04-06 15:42:39136 NewRunnableFunction(&NotifyReadError, this, message_id));
137 }
138 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
139}
140
141bool PrefService::ReloadPersistentPrefs() {
[email protected]277404c22010-04-22 13:09:45142 return (LoadPersistentPrefs() == PrefStore::PREF_READ_ERROR_NONE);
[email protected]ba399672010-04-06 15:42:39143}
144
[email protected]277404c22010-04-22 13:09:45145PrefStore::PrefReadError PrefService::LoadPersistentPrefs() {
[email protected]ba399672010-04-06 15:42:39146 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39147
[email protected]d8b08c92010-06-07 13:13:28148 PrefStore::PrefReadError pref_error = pref_value_store_->ReadPrefs();
[email protected]7aa0a962010-04-21 17:24:42149
[email protected]7aa0a962010-04-21 17:24:42150 for (PreferenceSet::iterator it = prefs_.begin();
151 it != prefs_.end(); ++it) {
[email protected]c3b54f372010-09-14 08:25:07152 (*it)->pref_service_ = this;
[email protected]7aa0a962010-04-21 17:24:42153 }
154
[email protected]277404c22010-04-22 13:09:45155 return pref_error;
initial.commit09911bf2008-07-26 23:55:29156}
157
[email protected]6faa0e0d2009-04-28 06:50:36158bool PrefService::SavePersistentPrefs() {
159 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29160
[email protected]d8b08c92010-06-07 13:13:28161 return pref_value_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36162}
163
[email protected]6c1164042009-05-08 14:41:08164void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36165 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39166
[email protected]d8b08c92010-06-07 13:13:28167 pref_value_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29168}
169
[email protected]57ecc4b2010-08-11 03:02:51170void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29171 bool default_value) {
[email protected]c3b54f372010-09-14 08:25:07172 RegisterPreference(path, Value::CreateBooleanValue(default_value));
initial.commit09911bf2008-07-26 23:55:29173}
174
[email protected]57ecc4b2010-08-11 03:02:51175void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]c3b54f372010-09-14 08:25:07176 RegisterPreference(path, Value::CreateIntegerValue(default_value));
initial.commit09911bf2008-07-26 23:55:29177}
178
[email protected]57ecc4b2010-08-11 03:02:51179void PrefService::RegisterRealPref(const char* path, double default_value) {
[email protected]c3b54f372010-09-14 08:25:07180 RegisterPreference(path, Value::CreateRealValue(default_value));
initial.commit09911bf2008-07-26 23:55:29181}
182
[email protected]57ecc4b2010-08-11 03:02:51183void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04184 const std::string& default_value) {
[email protected]c3b54f372010-09-14 08:25:07185 RegisterPreference(path, Value::CreateStringValue(default_value));
initial.commit09911bf2008-07-26 23:55:29186}
187
[email protected]57ecc4b2010-08-11 03:02:51188void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25189 const FilePath& default_value) {
[email protected]c3b54f372010-09-14 08:25:07190 RegisterPreference(path, Value::CreateStringValue(default_value.value()));
[email protected]b9636002009-03-04 00:05:25191}
192
[email protected]57ecc4b2010-08-11 03:02:51193void PrefService::RegisterListPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07194 RegisterPreference(path, new ListValue());
initial.commit09911bf2008-07-26 23:55:29195}
196
[email protected]57ecc4b2010-08-11 03:02:51197void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07198 RegisterPreference(path, new DictionaryValue());
initial.commit09911bf2008-07-26 23:55:29199}
200
[email protected]57ecc4b2010-08-11 03:02:51201void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29202 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07203 RegisterPreference(
204 path,
initial.commit09911bf2008-07-26 23:55:29205 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29206}
207
[email protected]57ecc4b2010-08-11 03:02:51208void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29209 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07210 RegisterPreference(
211 path,
initial.commit09911bf2008-07-26 23:55:29212 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29213}
214
[email protected]57ecc4b2010-08-11 03:02:51215void PrefService::RegisterLocalizedRealPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29216 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07217 RegisterPreference(
218 path,
initial.commit09911bf2008-07-26 23:55:29219 CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29220}
221
[email protected]57ecc4b2010-08-11 03:02:51222void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29223 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07224 RegisterPreference(
225 path,
initial.commit09911bf2008-07-26 23:55:29226 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29227}
228
[email protected]57ecc4b2010-08-11 03:02:51229bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29230 DCHECK(CalledOnValidThread());
231
232 bool result = false;
initial.commit09911bf2008-07-26 23:55:29233
234 const Preference* pref = FindPreference(path);
235 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40236 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29237 return result;
238 }
239 bool rv = pref->GetValue()->GetAsBoolean(&result);
240 DCHECK(rv);
241 return result;
242}
243
[email protected]57ecc4b2010-08-11 03:02:51244int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29245 DCHECK(CalledOnValidThread());
246
247 int result = 0;
initial.commit09911bf2008-07-26 23:55:29248
249 const Preference* pref = FindPreference(path);
250 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40251 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29252 return result;
253 }
254 bool rv = pref->GetValue()->GetAsInteger(&result);
255 DCHECK(rv);
256 return result;
257}
258
[email protected]57ecc4b2010-08-11 03:02:51259double PrefService::GetReal(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29260 DCHECK(CalledOnValidThread());
261
262 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29263
264 const Preference* pref = FindPreference(path);
265 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40266 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29267 return result;
268 }
269 bool rv = pref->GetValue()->GetAsReal(&result);
270 DCHECK(rv);
271 return result;
272}
273
[email protected]57ecc4b2010-08-11 03:02:51274std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29275 DCHECK(CalledOnValidThread());
276
[email protected]ddd231e2010-06-29 20:35:19277 std::string result;
[email protected]8e50b602009-03-03 22:59:43278
initial.commit09911bf2008-07-26 23:55:29279 const Preference* pref = FindPreference(path);
280 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40281 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29282 return result;
283 }
284 bool rv = pref->GetValue()->GetAsString(&result);
285 DCHECK(rv);
286 return result;
287}
288
[email protected]57ecc4b2010-08-11 03:02:51289FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25290 DCHECK(CalledOnValidThread());
291
292 FilePath::StringType result;
[email protected]b9636002009-03-04 00:05:25293
294 const Preference* pref = FindPreference(path);
295 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40296 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25297 return FilePath(result);
298 }
299 bool rv = pref->GetValue()->GetAsString(&result);
300 DCHECK(rv);
[email protected]66de4f092009-09-04 23:59:40301#if defined(OS_POSIX)
302 // We store filepaths as UTF8, so convert it back to the system type.
303 result = base::SysWideToNativeMB(UTF8ToWide(result));
304#endif
[email protected]b9636002009-03-04 00:05:25305 return FilePath(result);
306}
307
[email protected]57ecc4b2010-08-11 03:02:51308bool PrefService::HasPrefPath(const char* path) const {
[email protected]d8b08c92010-06-07 13:13:28309 return pref_value_store_->HasPrefPath(path);
initial.commit09911bf2008-07-26 23:55:29310}
311
312const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51313 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29314 DCHECK(CalledOnValidThread());
[email protected]99cc9a02010-09-17 07:53:28315 Preference p(this, pref_name);
initial.commit09911bf2008-07-26 23:55:29316 PreferenceSet::const_iterator it = prefs_.find(&p);
317 return it == prefs_.end() ? NULL : *it;
318}
319
[email protected]57ecc4b2010-08-11 03:02:51320bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48321 const Preference* pref = FindPreference(pref_name);
322 if (pref && pref->IsManaged()) {
323 return true;
324 }
325 return false;
326}
327
[email protected]57ecc4b2010-08-11 03:02:51328const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29329 DCHECK(CalledOnValidThread());
330
initial.commit09911bf2008-07-26 23:55:29331 const Preference* pref = FindPreference(path);
332 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40333 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29334 return NULL;
335 }
336 const Value* value = pref->GetValue();
337 if (value->GetType() == Value::TYPE_NULL)
338 return NULL;
339 return static_cast<const DictionaryValue*>(value);
340}
341
[email protected]57ecc4b2010-08-11 03:02:51342const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29343 DCHECK(CalledOnValidThread());
344
initial.commit09911bf2008-07-26 23:55:29345 const Preference* pref = FindPreference(path);
346 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40347 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29348 return NULL;
349 }
350 const Value* value = pref->GetValue();
351 if (value->GetType() == Value::TYPE_NULL)
352 return NULL;
353 return static_cast<const ListValue*>(value);
354}
355
[email protected]57ecc4b2010-08-11 03:02:51356void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29357 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50358 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29359}
360
[email protected]57ecc4b2010-08-11 03:02:51361void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29362 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50363 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29364}
365
[email protected]c3b54f372010-09-14 08:25:07366void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29367 DCHECK(CalledOnValidThread());
368
[email protected]c3b54f372010-09-14 08:25:07369 // The main code path takes ownership, but most don't. We'll be safe.
370 scoped_ptr<Value> scoped_value(default_value);
371
372 if (FindPreference(path)) {
373 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29374 return;
375 }
[email protected]c3b54f372010-09-14 08:25:07376
[email protected]99cc9a02010-09-17 07:53:28377 Value::ValueType orig_type = default_value->GetType();
378 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
379 "invalid preference type: " << orig_type;
380
[email protected]c3b54f372010-09-14 08:25:07381 // We set the default value of dictionaries and lists to be null so it's
382 // easier for callers to check for empty dict/list prefs. The PrefValueStore
383 // accepts ownership of the value (null or default_value).
[email protected]c3b54f372010-09-14 08:25:07384 if (Value::TYPE_LIST == orig_type || Value::TYPE_DICTIONARY == orig_type) {
385 pref_value_store_->SetDefaultPrefValue(path, Value::CreateNullValue());
386 } else {
387 // Hand off ownership.
388 pref_value_store_->SetDefaultPrefValue(path, scoped_value.release());
389 }
390
[email protected]99cc9a02010-09-17 07:53:28391 pref_value_store_->RegisterPreferenceType(path, orig_type);
392 prefs_.insert(new Preference(this, path));
initial.commit09911bf2008-07-26 23:55:29393}
394
[email protected]57ecc4b2010-08-11 03:02:51395void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29396 DCHECK(CalledOnValidThread());
397
398 const Preference* pref = FindPreference(path);
399 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40400 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29401 return;
402 }
[email protected]c3b54f372010-09-14 08:25:07403 if (pref_value_store_->RemoveUserPrefValue(path))
404 pref_notifier_->OnUserPreferenceSet(path);
initial.commit09911bf2008-07-26 23:55:29405}
406
[email protected]57ecc4b2010-08-11 03:02:51407void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39408 DCHECK(CalledOnValidThread());
409
410 const Preference* pref = FindPreference(path);
411 if (!pref) {
412 NOTREACHED() << "Trying to write an unregistered pref: " << path;
413 return;
414 }
[email protected]ecde2742010-04-02 17:36:18415
[email protected]c3b54f372010-09-14 08:25:07416 // Allow dictionary and list types to be set to null, which removes their
417 // user values.
418 bool value_changed = false;
[email protected]ecde2742010-04-02 17:36:18419 if (value.GetType() == Value::TYPE_NULL &&
[email protected]99cc9a02010-09-17 07:53:28420 (pref->GetType() == Value::TYPE_DICTIONARY ||
421 pref->GetType() == Value::TYPE_LIST)) {
[email protected]c3b54f372010-09-14 08:25:07422 value_changed = pref_value_store_->RemoveUserPrefValue(path);
[email protected]99cc9a02010-09-17 07:53:28423 } else if (pref->GetType() != value.GetType()) {
424 NOTREACHED() << "Trying to set pref " << path
425 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07426 << " to value of type " << value.GetType();
427 } else {
428 value_changed = pref_value_store_->SetUserPrefValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18429 }
430
[email protected]c3b54f372010-09-14 08:25:07431 if (value_changed)
432 pref_notifier_->OnUserPreferenceSet(path);
[email protected]a048d7e42009-12-01 01:02:39433}
434
[email protected]57ecc4b2010-08-11 03:02:51435void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07436 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29437}
438
[email protected]57ecc4b2010-08-11 03:02:51439void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07440 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29441}
442
[email protected]57ecc4b2010-08-11 03:02:51443void PrefService::SetReal(const char* path, double value) {
[email protected]c3b54f372010-09-14 08:25:07444 SetUserPrefValue(path, Value::CreateRealValue(value));
initial.commit09911bf2008-07-26 23:55:29445}
446
[email protected]57ecc4b2010-08-11 03:02:51447void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07448 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29449}
450
[email protected]57ecc4b2010-08-11 03:02:51451void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]66de4f092009-09-04 23:59:40452#if defined(OS_POSIX)
453 // Value::SetString only knows about UTF8 strings, so convert the path from
454 // the system native value to UTF8.
455 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value()));
[email protected]d8b08c92010-06-07 13:13:28456 Value* new_value = Value::CreateStringValue(path_utf8);
[email protected]66de4f092009-09-04 23:59:40457#else
[email protected]d8b08c92010-06-07 13:13:28458 Value* new_value = Value::CreateStringValue(value.value());
[email protected]66de4f092009-09-04 23:59:40459#endif
[email protected]b9636002009-03-04 00:05:25460
[email protected]c3b54f372010-09-14 08:25:07461 SetUserPrefValue(path, new_value);
[email protected]b9636002009-03-04 00:05:25462}
463
[email protected]57ecc4b2010-08-11 03:02:51464void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07465 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32466}
467
[email protected]57ecc4b2010-08-11 03:02:51468int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32469 DCHECK(CalledOnValidThread());
470
[email protected]0bb1a622009-03-04 03:22:32471 const Preference* pref = FindPreference(path);
472 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40473 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08474 return 0;
[email protected]0bb1a622009-03-04 03:22:32475 }
[email protected]dc9a6762010-08-16 07:13:53476 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32477 bool rv = pref->GetValue()->GetAsString(&result);
478 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25479
480 int64 val;
[email protected]dc9a6762010-08-16 07:13:53481 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25482 return val;
[email protected]0bb1a622009-03-04 03:22:32483}
484
[email protected]57ecc4b2010-08-11 03:02:51485void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07486 RegisterPreference(
487 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32488}
489
[email protected]57ecc4b2010-08-11 03:02:51490DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29491 DCHECK(CalledOnValidThread());
492
493 const Preference* pref = FindPreference(path);
494 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40495 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29496 return NULL;
497 }
[email protected]99cc9a02010-09-17 07:53:28498 if (pref->GetType() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40499 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29500 return NULL;
501 }
502
503 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28504 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53505 // Look for an existing preference in the user store. If it doesn't
506 // exist or isn't the correct type, create a new user preference.
507 if (!pref_value_store_->GetUserValue(path, &tmp_value) ||
[email protected]91761242010-06-10 15:35:37508 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29509 dict = new DictionaryValue;
[email protected]d8b08c92010-06-07 13:13:28510 pref_value_store_->SetUserPrefValue(path, dict);
511 } else {
512 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29513 }
514 return dict;
515}
516
[email protected]57ecc4b2010-08-11 03:02:51517ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29518 DCHECK(CalledOnValidThread());
519
520 const Preference* pref = FindPreference(path);
521 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40522 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29523 return NULL;
524 }
[email protected]99cc9a02010-09-17 07:53:28525 if (pref->GetType() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40526 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29527 return NULL;
528 }
529
530 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28531 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53532 // Look for an existing preference in the user store. If it doesn't
533 // exist or isn't the correct type, create a new user preference.
534 if (!pref_value_store_->GetUserValue(path, &tmp_value) ||
[email protected]c3b54f372010-09-14 08:25:07535 !tmp_value->IsType(Value::TYPE_LIST)) {
initial.commit09911bf2008-07-26 23:55:29536 list = new ListValue;
[email protected]d8b08c92010-06-07 13:13:28537 pref_value_store_->SetUserPrefValue(path, list);
538 } else {
539 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29540 }
541 return list;
542}
543
[email protected]57ecc4b2010-08-11 03:02:51544Value* PrefService::GetPrefCopy(const char* path) {
initial.commit09911bf2008-07-26 23:55:29545 DCHECK(CalledOnValidThread());
546
547 const Preference* pref = FindPreference(path);
548 DCHECK(pref);
549 return pref->GetValue()->DeepCopy();
550}
551
[email protected]c3b54f372010-09-14 08:25:07552void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
553 DCHECK(CalledOnValidThread());
554
555 const Preference* pref = FindPreference(path);
556 if (!pref) {
557 NOTREACHED() << "Trying to write an unregistered pref: " << path;
558 return;
559 }
560 if (pref->IsManaged()) {
561 NOTREACHED() << "Preference is managed: " << path;
562 return;
563 }
[email protected]99cc9a02010-09-17 07:53:28564 if (pref->GetType() != new_value->GetType()) {
565 NOTREACHED() << "Trying to set pref " << path
566 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07567 << " to value of type " << new_value->GetType();
568 return;
569 }
570
571 if (pref_value_store_->SetUserPrefValue(path, new_value))
572 pref_notifier_->OnUserPreferenceSet(path);
573}
574
initial.commit09911bf2008-07-26 23:55:29575///////////////////////////////////////////////////////////////////////////////
576// PrefService::Preference
577
[email protected]c3b54f372010-09-14 08:25:07578PrefService::Preference::Preference(const PrefService* service,
[email protected]99cc9a02010-09-17 07:53:28579 const char* name)
580 : name_(name),
[email protected]c3b54f372010-09-14 08:25:07581 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29582 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07583 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28584}
585
586Value::ValueType PrefService::Preference::GetType() const {
587 return pref_service_->pref_value_store_->GetRegisteredType(name_);
initial.commit09911bf2008-07-26 23:55:29588}
589
590const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07591 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29592 "Must register pref before getting its value";
593
[email protected]c3b54f372010-09-14 08:25:07594 Value* found_value = NULL;
[email protected]99cc9a02010-09-17 07:53:28595 if (pref_service_->pref_value_store_->GetValue(name_, &found_value))
596 return found_value;
initial.commit09911bf2008-07-26 23:55:29597
[email protected]c3b54f372010-09-14 08:25:07598 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28599 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07600 return NULL;
[email protected]40a47c162010-09-09 11:14:01601}
602
603bool PrefService::Preference::IsManaged() const {
[email protected]c3b54f372010-09-14 08:25:07604 return pref_service_->pref_value_store_->
605 PrefValueInManagedStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01606}
607
608bool PrefService::Preference::HasExtensionSetting() const {
[email protected]c3b54f372010-09-14 08:25:07609 return pref_service_->pref_value_store_->
610 PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01611}
612
613bool PrefService::Preference::HasUserSetting() const {
[email protected]c3b54f372010-09-14 08:25:07614 return pref_service_->pref_value_store_->
615 PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01616}
617
618bool PrefService::Preference::IsExtensionControlled() const {
[email protected]c3b54f372010-09-14 08:25:07619 return pref_service_->pref_value_store_->
620 PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01621}
622
623bool PrefService::Preference::IsUserControlled() const {
[email protected]c3b54f372010-09-14 08:25:07624 return pref_service_->pref_value_store_->
625 PrefValueFromUserStore(name_.c_str());
626}
627
628bool PrefService::Preference::IsDefaultValue() const {
629 return pref_service_->pref_value_store_->
630 PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35631}
[email protected]74379bc52010-07-21 13:54:08632
633bool PrefService::Preference::IsUserModifiable() const {
[email protected]c3b54f372010-09-14 08:25:07634 return pref_service_->pref_value_store_->
635 PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08636}