blob: 524a858dfc901172ac0e3a59a594d916ccc30b4e [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]acd78969c2010-12-08 09:49:1124#include "chrome/browser/policy/configuration_policy_pref_store.h"
25#include "chrome/browser/prefs/command_line_pref_store.h"
26#include "chrome/browser/prefs/in_memory_pref_store.h"
27#include "chrome/browser/prefs/pref_notifier_impl.h"
[email protected]39d9f62c2010-12-03 10:48:5028#include "chrome/browser/prefs/pref_value_store.h"
[email protected]8ecad5e2010-12-02 21:18:3329#include "chrome/browser/profiles/profile.h"
[email protected]acd78969c2010-12-08 09:49:1130#include "chrome/common/json_pref_store.h"
initial.commit09911bf2008-07-26 23:55:2931#include "chrome/common/notification_service.h"
[email protected]ba399672010-04-06 15:42:3932#include "grit/chromium_strings.h"
[email protected]34ac8f32009-02-22 23:03:2733#include "grit/generated_resources.h"
initial.commit09911bf2008-07-26 23:55:2934
35namespace {
36
initial.commit09911bf2008-07-26 23:55:2937// A helper function for RegisterLocalized*Pref that creates a Value* based on
38// the string value in the locale dll. Because we control the values in a
39// locale dll, this should always return a Value of the appropriate type.
40Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) {
[email protected]16b527162010-08-15 18:37:1041 std::string resource_string = l10n_util::GetStringUTF8(message_id);
initial.commit09911bf2008-07-26 23:55:2942 DCHECK(!resource_string.empty());
43 switch (type) {
44 case Value::TYPE_BOOLEAN: {
[email protected]16b527162010-08-15 18:37:1045 if ("true" == resource_string)
initial.commit09911bf2008-07-26 23:55:2946 return Value::CreateBooleanValue(true);
[email protected]16b527162010-08-15 18:37:1047 if ("false" == resource_string)
initial.commit09911bf2008-07-26 23:55:2948 return Value::CreateBooleanValue(false);
49 break;
50 }
51
52 case Value::TYPE_INTEGER: {
[email protected]e83326f2010-07-31 17:29:2553 int val;
[email protected]16b527162010-08-15 18:37:1054 base::StringToInt(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2555 return Value::CreateIntegerValue(val);
initial.commit09911bf2008-07-26 23:55:2956 }
57
58 case Value::TYPE_REAL: {
[email protected]e83326f2010-07-31 17:29:2559 double val;
[email protected]16b527162010-08-15 18:37:1060 base::StringToDouble(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2561 return Value::CreateRealValue(val);
initial.commit09911bf2008-07-26 23:55:2962 }
63
64 case Value::TYPE_STRING: {
65 return Value::CreateStringValue(resource_string);
initial.commit09911bf2008-07-26 23:55:2966 }
67
68 default: {
[email protected]b154e6f2009-03-06 01:52:4069 NOTREACHED() <<
[email protected]c3b54f372010-09-14 08:25:0770 "list and dictionary types cannot have default locale values";
initial.commit09911bf2008-07-26 23:55:2971 }
72 }
73 NOTREACHED();
74 return Value::CreateNullValue();
75}
76
[email protected]ba399672010-04-06 15:42:3977// Forwards a notification after a PostMessage so that we can wait for the
78// MessageLoop to run.
79void NotifyReadError(PrefService* pref, int message_id) {
80 Source<PrefService> source(pref);
81 NotificationService::current()->Notify(NotificationType::PROFILE_ERROR,
82 source, Details<int>(&message_id));
83}
84
initial.commit09911bf2008-07-26 23:55:2985} // namespace
86
[email protected]db198b22010-07-12 16:48:4987// static
[email protected]a9c23a52010-08-04 09:13:4488PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
89 Profile* profile) {
[email protected]acd78969c2010-12-08 09:49:1190 using policy::ConfigurationPolicyPrefStore;
91
[email protected]1d01d412010-08-20 00:36:0192#if defined(OS_LINUX)
93 // We'd like to see what fraction of our users have the preferences
94 // stored on a network file system, as we've had no end of troubles
95 // with NFS/AFS.
96 // TODO(evanm): remove this once we've collected state.
97 file_util::FileSystemType fstype;
98 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
99 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
100 static_cast<int>(fstype),
101 file_util::FILE_SYSTEM_TYPE_COUNT);
102 }
103#endif
104
[email protected]acd78969c2010-12-08 09:49:11105 ConfigurationPolicyPrefStore* managed =
106 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore();
107 ConfigurationPolicyPrefStore* device_management =
108 ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
109 profile);
110 InMemoryPrefStore* extension = new InMemoryPrefStore();
111 CommandLinePrefStore* command_line =
112 new CommandLinePrefStore(CommandLine::ForCurrentProcess());
113 JsonPrefStore* user = new JsonPrefStore(
114 pref_filename,
115 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
116 ConfigurationPolicyPrefStore* recommended =
117 ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore();
118
119 return new PrefService(managed, device_management, extension, command_line,
120 user, recommended, profile);
[email protected]db198b22010-07-12 16:48:49121}
122
123// static
[email protected]fa26b3d52010-08-06 08:51:50124PrefService* PrefService::CreateUserPrefService(const FilePath& pref_filename) {
[email protected]acd78969c2010-12-08 09:49:11125 JsonPrefStore* user = new JsonPrefStore(
126 pref_filename,
127 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
128 InMemoryPrefStore* extension = new InMemoryPrefStore();
129
130 return new PrefService(NULL, NULL, extension, NULL, user, NULL, NULL);
[email protected]d8b08c92010-06-07 13:13:28131}
132
[email protected]acd78969c2010-12-08 09:49:11133PrefService::PrefService(PrefStore* managed_platform_prefs,
134 PrefStore* device_management_prefs,
135 PrefStore* extension_prefs,
136 PrefStore* command_line_prefs,
137 PrefStore* user_prefs,
138 PrefStore* recommended_prefs,
139 Profile* profile) {
140 pref_notifier_.reset(new PrefNotifierImpl(this));
141 extension_store_ = extension_prefs;
142 default_store_ = new InMemoryPrefStore();
143 pref_value_store_ =
144 new PrefValueStore(managed_platform_prefs,
145 device_management_prefs,
146 extension_store_,
147 command_line_prefs,
148 user_prefs,
149 recommended_prefs,
150 default_store_,
151 pref_notifier_.get(),
152 profile);
[email protected]277404c22010-04-22 13:09:45153 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29154}
155
156PrefService::~PrefService() {
157 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29158 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
159 prefs_.clear();
initial.commit09911bf2008-07-26 23:55:29160}
161
[email protected]277404c22010-04-22 13:09:45162void PrefService::InitFromStorage() {
163 PrefStore::PrefReadError error = LoadPersistentPrefs();
164 if (error == PrefStore::PREF_READ_ERROR_NONE)
[email protected]ba399672010-04-06 15:42:39165 return;
initial.commit09911bf2008-07-26 23:55:29166
[email protected]ba399672010-04-06 15:42:39167 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
168 // an example problem that this can cause.
169 // Do some diagnosis and try to avoid losing data.
170 int message_id = 0;
[email protected]277404c22010-04-22 13:09:45171 if (error <= PrefStore::PREF_READ_ERROR_JSON_TYPE) {
[email protected]ba399672010-04-06 15:42:39172 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
[email protected]277404c22010-04-22 13:09:45173 } else if (error != PrefStore::PREF_READ_ERROR_NO_FILE) {
[email protected]ba399672010-04-06 15:42:39174 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
175 }
176
177 if (message_id) {
[email protected]8bac2352010-10-10 18:53:21178 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
[email protected]ba399672010-04-06 15:42:39179 NewRunnableFunction(&NotifyReadError, this, message_id));
180 }
181 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
182}
183
184bool PrefService::ReloadPersistentPrefs() {
[email protected]277404c22010-04-22 13:09:45185 return (LoadPersistentPrefs() == PrefStore::PREF_READ_ERROR_NONE);
[email protected]ba399672010-04-06 15:42:39186}
187
[email protected]277404c22010-04-22 13:09:45188PrefStore::PrefReadError PrefService::LoadPersistentPrefs() {
[email protected]ba399672010-04-06 15:42:39189 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39190
[email protected]d8b08c92010-06-07 13:13:28191 PrefStore::PrefReadError pref_error = pref_value_store_->ReadPrefs();
[email protected]7aa0a962010-04-21 17:24:42192
[email protected]7aa0a962010-04-21 17:24:42193 for (PreferenceSet::iterator it = prefs_.begin();
194 it != prefs_.end(); ++it) {
[email protected]c3b54f372010-09-14 08:25:07195 (*it)->pref_service_ = this;
[email protected]7aa0a962010-04-21 17:24:42196 }
197
[email protected]277404c22010-04-22 13:09:45198 return pref_error;
initial.commit09911bf2008-07-26 23:55:29199}
200
[email protected]6faa0e0d2009-04-28 06:50:36201bool PrefService::SavePersistentPrefs() {
202 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29203
[email protected]d8b08c92010-06-07 13:13:28204 return pref_value_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36205}
206
[email protected]6c1164042009-05-08 14:41:08207void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36208 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39209
[email protected]d8b08c92010-06-07 13:13:28210 pref_value_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29211}
212
[email protected]57ecc4b2010-08-11 03:02:51213void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29214 bool default_value) {
[email protected]c3b54f372010-09-14 08:25:07215 RegisterPreference(path, Value::CreateBooleanValue(default_value));
initial.commit09911bf2008-07-26 23:55:29216}
217
[email protected]57ecc4b2010-08-11 03:02:51218void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]c3b54f372010-09-14 08:25:07219 RegisterPreference(path, Value::CreateIntegerValue(default_value));
initial.commit09911bf2008-07-26 23:55:29220}
221
[email protected]57ecc4b2010-08-11 03:02:51222void PrefService::RegisterRealPref(const char* path, double default_value) {
[email protected]c3b54f372010-09-14 08:25:07223 RegisterPreference(path, Value::CreateRealValue(default_value));
initial.commit09911bf2008-07-26 23:55:29224}
225
[email protected]57ecc4b2010-08-11 03:02:51226void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04227 const std::string& default_value) {
[email protected]c3b54f372010-09-14 08:25:07228 RegisterPreference(path, Value::CreateStringValue(default_value));
initial.commit09911bf2008-07-26 23:55:29229}
230
[email protected]57ecc4b2010-08-11 03:02:51231void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25232 const FilePath& default_value) {
[email protected]c3b54f372010-09-14 08:25:07233 RegisterPreference(path, Value::CreateStringValue(default_value.value()));
[email protected]b9636002009-03-04 00:05:25234}
235
[email protected]57ecc4b2010-08-11 03:02:51236void PrefService::RegisterListPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07237 RegisterPreference(path, new ListValue());
initial.commit09911bf2008-07-26 23:55:29238}
239
[email protected]57ecc4b2010-08-11 03:02:51240void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07241 RegisterPreference(path, new DictionaryValue());
initial.commit09911bf2008-07-26 23:55:29242}
243
[email protected]57ecc4b2010-08-11 03:02:51244void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29245 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07246 RegisterPreference(
247 path,
initial.commit09911bf2008-07-26 23:55:29248 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29249}
250
[email protected]57ecc4b2010-08-11 03:02:51251void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29252 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07253 RegisterPreference(
254 path,
initial.commit09911bf2008-07-26 23:55:29255 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29256}
257
[email protected]57ecc4b2010-08-11 03:02:51258void PrefService::RegisterLocalizedRealPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29259 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07260 RegisterPreference(
261 path,
initial.commit09911bf2008-07-26 23:55:29262 CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29263}
264
[email protected]57ecc4b2010-08-11 03:02:51265void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29266 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07267 RegisterPreference(
268 path,
initial.commit09911bf2008-07-26 23:55:29269 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29270}
271
[email protected]57ecc4b2010-08-11 03:02:51272bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29273 DCHECK(CalledOnValidThread());
274
275 bool result = false;
initial.commit09911bf2008-07-26 23:55:29276
277 const Preference* pref = FindPreference(path);
278 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40279 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29280 return result;
281 }
282 bool rv = pref->GetValue()->GetAsBoolean(&result);
283 DCHECK(rv);
284 return result;
285}
286
[email protected]57ecc4b2010-08-11 03:02:51287int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29288 DCHECK(CalledOnValidThread());
289
290 int result = 0;
initial.commit09911bf2008-07-26 23:55:29291
292 const Preference* pref = FindPreference(path);
293 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40294 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29295 return result;
296 }
297 bool rv = pref->GetValue()->GetAsInteger(&result);
298 DCHECK(rv);
299 return result;
300}
301
[email protected]57ecc4b2010-08-11 03:02:51302double PrefService::GetReal(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29303 DCHECK(CalledOnValidThread());
304
305 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29306
307 const Preference* pref = FindPreference(path);
308 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40309 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29310 return result;
311 }
312 bool rv = pref->GetValue()->GetAsReal(&result);
313 DCHECK(rv);
314 return result;
315}
316
[email protected]57ecc4b2010-08-11 03:02:51317std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29318 DCHECK(CalledOnValidThread());
319
[email protected]ddd231e2010-06-29 20:35:19320 std::string result;
[email protected]8e50b602009-03-03 22:59:43321
initial.commit09911bf2008-07-26 23:55:29322 const Preference* pref = FindPreference(path);
323 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40324 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29325 return result;
326 }
327 bool rv = pref->GetValue()->GetAsString(&result);
328 DCHECK(rv);
329 return result;
330}
331
[email protected]57ecc4b2010-08-11 03:02:51332FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25333 DCHECK(CalledOnValidThread());
334
335 FilePath::StringType result;
[email protected]b9636002009-03-04 00:05:25336
337 const Preference* pref = FindPreference(path);
338 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40339 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25340 return FilePath(result);
341 }
342 bool rv = pref->GetValue()->GetAsString(&result);
343 DCHECK(rv);
[email protected]66de4f092009-09-04 23:59:40344#if defined(OS_POSIX)
345 // We store filepaths as UTF8, so convert it back to the system type.
346 result = base::SysWideToNativeMB(UTF8ToWide(result));
347#endif
[email protected]b9636002009-03-04 00:05:25348 return FilePath(result);
349}
350
[email protected]57ecc4b2010-08-11 03:02:51351bool PrefService::HasPrefPath(const char* path) const {
[email protected]d8b08c92010-06-07 13:13:28352 return pref_value_store_->HasPrefPath(path);
initial.commit09911bf2008-07-26 23:55:29353}
354
355const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51356 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29357 DCHECK(CalledOnValidThread());
[email protected]99cc9a02010-09-17 07:53:28358 Preference p(this, pref_name);
initial.commit09911bf2008-07-26 23:55:29359 PreferenceSet::const_iterator it = prefs_.find(&p);
360 return it == prefs_.end() ? NULL : *it;
361}
362
[email protected]acd78969c2010-12-08 09:49:11363bool PrefService::ReadOnly() const {
364 return pref_value_store_->ReadOnly();
365}
366
367PrefNotifier* PrefService::pref_notifier() const {
368 return pref_notifier_.get();
369}
370
371PrefStore* PrefService::GetExtensionPrefStore() {
372 return extension_store_;
373}
374
[email protected]57ecc4b2010-08-11 03:02:51375bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48376 const Preference* pref = FindPreference(pref_name);
377 if (pref && pref->IsManaged()) {
378 return true;
379 }
380 return false;
381}
382
[email protected]57ecc4b2010-08-11 03:02:51383const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29384 DCHECK(CalledOnValidThread());
385
initial.commit09911bf2008-07-26 23:55:29386 const Preference* pref = FindPreference(path);
387 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40388 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29389 return NULL;
390 }
391 const Value* value = pref->GetValue();
392 if (value->GetType() == Value::TYPE_NULL)
393 return NULL;
394 return static_cast<const DictionaryValue*>(value);
395}
396
[email protected]57ecc4b2010-08-11 03:02:51397const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29398 DCHECK(CalledOnValidThread());
399
initial.commit09911bf2008-07-26 23:55:29400 const Preference* pref = FindPreference(path);
401 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40402 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29403 return NULL;
404 }
405 const Value* value = pref->GetValue();
406 if (value->GetType() == Value::TYPE_NULL)
407 return NULL;
408 return static_cast<const ListValue*>(value);
409}
410
[email protected]57ecc4b2010-08-11 03:02:51411void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29412 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50413 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29414}
415
[email protected]57ecc4b2010-08-11 03:02:51416void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29417 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50418 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29419}
420
[email protected]c3b54f372010-09-14 08:25:07421void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29422 DCHECK(CalledOnValidThread());
423
[email protected]c3b54f372010-09-14 08:25:07424 // The main code path takes ownership, but most don't. We'll be safe.
425 scoped_ptr<Value> scoped_value(default_value);
426
427 if (FindPreference(path)) {
428 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29429 return;
430 }
[email protected]c3b54f372010-09-14 08:25:07431
[email protected]99cc9a02010-09-17 07:53:28432 Value::ValueType orig_type = default_value->GetType();
433 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
434 "invalid preference type: " << orig_type;
435
[email protected]c3b54f372010-09-14 08:25:07436 // We set the default value of dictionaries and lists to be null so it's
437 // easier for callers to check for empty dict/list prefs. The PrefValueStore
438 // accepts ownership of the value (null or default_value).
[email protected]c3b54f372010-09-14 08:25:07439 if (Value::TYPE_LIST == orig_type || Value::TYPE_DICTIONARY == orig_type) {
[email protected]acd78969c2010-12-08 09:49:11440 default_store_->prefs()->Set(path, Value::CreateNullValue());
[email protected]c3b54f372010-09-14 08:25:07441 } else {
442 // Hand off ownership.
[email protected]ce1850e92010-10-15 08:40:58443 DCHECK(!PrefStore::IsUseDefaultSentinelValue(default_value));
[email protected]acd78969c2010-12-08 09:49:11444 default_store_->prefs()->Set(path, scoped_value.release());
[email protected]c3b54f372010-09-14 08:25:07445 }
446
[email protected]99cc9a02010-09-17 07:53:28447 pref_value_store_->RegisterPreferenceType(path, orig_type);
448 prefs_.insert(new Preference(this, path));
initial.commit09911bf2008-07-26 23:55:29449}
450
[email protected]57ecc4b2010-08-11 03:02:51451void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29452 DCHECK(CalledOnValidThread());
453
454 const Preference* pref = FindPreference(path);
455 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40456 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29457 return;
458 }
[email protected]acd78969c2010-12-08 09:49:11459 pref_value_store_->RemoveUserPrefValue(path);
initial.commit09911bf2008-07-26 23:55:29460}
461
[email protected]57ecc4b2010-08-11 03:02:51462void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39463 DCHECK(CalledOnValidThread());
464
465 const Preference* pref = FindPreference(path);
466 if (!pref) {
467 NOTREACHED() << "Trying to write an unregistered pref: " << path;
468 return;
469 }
[email protected]ecde2742010-04-02 17:36:18470
[email protected]c3b54f372010-09-14 08:25:07471 // Allow dictionary and list types to be set to null, which removes their
472 // user values.
[email protected]ecde2742010-04-02 17:36:18473 if (value.GetType() == Value::TYPE_NULL &&
[email protected]99cc9a02010-09-17 07:53:28474 (pref->GetType() == Value::TYPE_DICTIONARY ||
475 pref->GetType() == Value::TYPE_LIST)) {
[email protected]acd78969c2010-12-08 09:49:11476 pref_value_store_->RemoveUserPrefValue(path);
[email protected]99cc9a02010-09-17 07:53:28477 } else if (pref->GetType() != value.GetType()) {
478 NOTREACHED() << "Trying to set pref " << path
479 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07480 << " to value of type " << value.GetType();
481 } else {
[email protected]acd78969c2010-12-08 09:49:11482 pref_value_store_->SetUserPrefValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18483 }
[email protected]a048d7e42009-12-01 01:02:39484}
485
[email protected]57ecc4b2010-08-11 03:02:51486void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07487 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29488}
489
[email protected]57ecc4b2010-08-11 03:02:51490void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07491 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29492}
493
[email protected]57ecc4b2010-08-11 03:02:51494void PrefService::SetReal(const char* path, double value) {
[email protected]c3b54f372010-09-14 08:25:07495 SetUserPrefValue(path, Value::CreateRealValue(value));
initial.commit09911bf2008-07-26 23:55:29496}
497
[email protected]57ecc4b2010-08-11 03:02:51498void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07499 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29500}
501
[email protected]57ecc4b2010-08-11 03:02:51502void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]66de4f092009-09-04 23:59:40503#if defined(OS_POSIX)
504 // Value::SetString only knows about UTF8 strings, so convert the path from
505 // the system native value to UTF8.
506 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value()));
[email protected]d8b08c92010-06-07 13:13:28507 Value* new_value = Value::CreateStringValue(path_utf8);
[email protected]66de4f092009-09-04 23:59:40508#else
[email protected]d8b08c92010-06-07 13:13:28509 Value* new_value = Value::CreateStringValue(value.value());
[email protected]66de4f092009-09-04 23:59:40510#endif
[email protected]b9636002009-03-04 00:05:25511
[email protected]c3b54f372010-09-14 08:25:07512 SetUserPrefValue(path, new_value);
[email protected]b9636002009-03-04 00:05:25513}
514
[email protected]57ecc4b2010-08-11 03:02:51515void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07516 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32517}
518
[email protected]57ecc4b2010-08-11 03:02:51519int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32520 DCHECK(CalledOnValidThread());
521
[email protected]0bb1a622009-03-04 03:22:32522 const Preference* pref = FindPreference(path);
523 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40524 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08525 return 0;
[email protected]0bb1a622009-03-04 03:22:32526 }
[email protected]dc9a6762010-08-16 07:13:53527 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32528 bool rv = pref->GetValue()->GetAsString(&result);
529 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25530
531 int64 val;
[email protected]dc9a6762010-08-16 07:13:53532 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25533 return val;
[email protected]0bb1a622009-03-04 03:22:32534}
535
[email protected]57ecc4b2010-08-11 03:02:51536void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07537 RegisterPreference(
538 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32539}
540
[email protected]57ecc4b2010-08-11 03:02:51541DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29542 DCHECK(CalledOnValidThread());
543
544 const Preference* pref = FindPreference(path);
545 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40546 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29547 return NULL;
548 }
[email protected]99cc9a02010-09-17 07:53:28549 if (pref->GetType() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40550 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29551 return NULL;
552 }
553
554 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28555 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53556 // Look for an existing preference in the user store. If it doesn't
557 // exist or isn't the correct type, create a new user preference.
558 if (!pref_value_store_->GetUserValue(path, &tmp_value) ||
[email protected]91761242010-06-10 15:35:37559 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29560 dict = new DictionaryValue;
[email protected]acd78969c2010-12-08 09:49:11561 pref_value_store_->SetUserPrefValueSilently(path, dict);
[email protected]d8b08c92010-06-07 13:13:28562 } else {
563 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29564 }
565 return dict;
566}
567
[email protected]57ecc4b2010-08-11 03:02:51568ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29569 DCHECK(CalledOnValidThread());
570
571 const Preference* pref = FindPreference(path);
572 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40573 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29574 return NULL;
575 }
[email protected]99cc9a02010-09-17 07:53:28576 if (pref->GetType() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40577 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29578 return NULL;
579 }
580
581 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28582 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53583 // Look for an existing preference in the user store. If it doesn't
584 // exist or isn't the correct type, create a new user preference.
585 if (!pref_value_store_->GetUserValue(path, &tmp_value) ||
[email protected]c3b54f372010-09-14 08:25:07586 !tmp_value->IsType(Value::TYPE_LIST)) {
initial.commit09911bf2008-07-26 23:55:29587 list = new ListValue;
[email protected]acd78969c2010-12-08 09:49:11588 pref_value_store_->SetUserPrefValueSilently(path, list);
[email protected]d8b08c92010-06-07 13:13:28589 } else {
590 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29591 }
592 return list;
593}
594
[email protected]57ecc4b2010-08-11 03:02:51595Value* PrefService::GetPrefCopy(const char* path) {
initial.commit09911bf2008-07-26 23:55:29596 DCHECK(CalledOnValidThread());
597
598 const Preference* pref = FindPreference(path);
599 DCHECK(pref);
600 return pref->GetValue()->DeepCopy();
601}
602
[email protected]c3b54f372010-09-14 08:25:07603void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
604 DCHECK(CalledOnValidThread());
605
606 const Preference* pref = FindPreference(path);
607 if (!pref) {
608 NOTREACHED() << "Trying to write an unregistered pref: " << path;
609 return;
610 }
611 if (pref->IsManaged()) {
612 NOTREACHED() << "Preference is managed: " << path;
613 return;
614 }
[email protected]99cc9a02010-09-17 07:53:28615 if (pref->GetType() != new_value->GetType()) {
616 NOTREACHED() << "Trying to set pref " << path
617 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07618 << " to value of type " << new_value->GetType();
619 return;
620 }
621
[email protected]acd78969c2010-12-08 09:49:11622 pref_value_store_->SetUserPrefValue(path, new_value);
[email protected]73c47932010-12-06 18:13:43623}
624
initial.commit09911bf2008-07-26 23:55:29625///////////////////////////////////////////////////////////////////////////////
626// PrefService::Preference
627
[email protected]c3b54f372010-09-14 08:25:07628PrefService::Preference::Preference(const PrefService* service,
[email protected]99cc9a02010-09-17 07:53:28629 const char* name)
630 : name_(name),
[email protected]c3b54f372010-09-14 08:25:07631 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29632 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07633 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28634}
635
636Value::ValueType PrefService::Preference::GetType() const {
637 return pref_service_->pref_value_store_->GetRegisteredType(name_);
initial.commit09911bf2008-07-26 23:55:29638}
639
640const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07641 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29642 "Must register pref before getting its value";
643
[email protected]c3b54f372010-09-14 08:25:07644 Value* found_value = NULL;
[email protected]99cc9a02010-09-17 07:53:28645 if (pref_service_->pref_value_store_->GetValue(name_, &found_value))
646 return found_value;
initial.commit09911bf2008-07-26 23:55:29647
[email protected]c3b54f372010-09-14 08:25:07648 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28649 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07650 return NULL;
[email protected]40a47c162010-09-09 11:14:01651}
652
653bool PrefService::Preference::IsManaged() const {
[email protected]be1c6e922010-11-17 12:49:17654 PrefValueStore* pref_value_store =
655 pref_service_->pref_value_store_;
656 return pref_value_store->PrefValueInManagedPlatformStore(name_.c_str()) ||
657 pref_value_store->PrefValueInDeviceManagementStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01658}
659
660bool PrefService::Preference::HasExtensionSetting() const {
[email protected]c3b54f372010-09-14 08:25:07661 return pref_service_->pref_value_store_->
662 PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01663}
664
665bool PrefService::Preference::HasUserSetting() const {
[email protected]c3b54f372010-09-14 08:25:07666 return pref_service_->pref_value_store_->
667 PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01668}
669
670bool PrefService::Preference::IsExtensionControlled() const {
[email protected]c3b54f372010-09-14 08:25:07671 return pref_service_->pref_value_store_->
672 PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01673}
674
675bool PrefService::Preference::IsUserControlled() const {
[email protected]c3b54f372010-09-14 08:25:07676 return pref_service_->pref_value_store_->
677 PrefValueFromUserStore(name_.c_str());
678}
679
680bool PrefService::Preference::IsDefaultValue() const {
681 return pref_service_->pref_value_store_->
682 PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35683}
[email protected]74379bc52010-07-21 13:54:08684
685bool PrefService::Preference::IsUserModifiable() const {
[email protected]c3b54f372010-09-14 08:25:07686 return pref_service_->pref_value_store_->
687 PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08688}