blob: 0e55f31a2a25ff552e26aeb49f61e7b3788dab2c [file] [log] [blame]
[email protected]9a8c4022011-01-25 14:25:331// Copyright (c) 2011 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]aa4dc5e22010-06-16 11:32:5410#include "base/command_line.h"
[email protected]c02c853d72010-08-07 06:23:2411#include "base/file_path.h"
[email protected]1d01d412010-08-20 00:36:0112#include "base/file_util.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/logging.h"
14#include "base/message_loop.h"
[email protected]835d7c82010-10-14 04:38:3815#include "base/metrics/histogram.h"
[email protected]807204142009-05-05 03:31:4416#include "base/stl_util-inl.h"
[email protected]e83326f2010-07-31 17:29:2517#include "base/string_number_conversions.h"
initial.commit09911bf2008-07-26 23:55:2918#include "base/string_util.h"
[email protected]66de4f092009-09-04 23:59:4019#include "base/sys_string_conversions.h"
[email protected]1cb92b82010-03-08 23:12:1520#include "base/utf_string_conversions.h"
[email protected]66de4f092009-09-04 23:59:4021#include "build/build_config.h"
[email protected]017a7a112010-10-12 16:38:2722#include "chrome/browser/browser_thread.h"
[email protected]9a8c4022011-01-25 14:25:3323#include "chrome/browser/extensions/extension_pref_store.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"
[email protected]f2d1f612010-12-09 15:10:1726#include "chrome/browser/prefs/default_pref_store.h"
[email protected]9a8c4022011-01-25 14:25:3327#include "chrome/browser/prefs/overlay_persistent_pref_store.h"
[email protected]acd78969c2010-12-08 09:49:1128#include "chrome/browser/prefs/pref_notifier_impl.h"
[email protected]39d9f62c2010-12-03 10:48:5029#include "chrome/browser/prefs/pref_value_store.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"
[email protected]c051a1b2011-01-21 23:30:1734#include "ui/base/l10n/l10n_util.h"
initial.commit09911bf2008-07-26 23:55:2935
36namespace {
37
initial.commit09911bf2008-07-26 23:55:2938// A helper function for RegisterLocalized*Pref that creates a Value* based on
39// the string value in the locale dll. Because we control the values in a
40// locale dll, this should always return a Value of the appropriate type.
41Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) {
[email protected]16b527162010-08-15 18:37:1042 std::string resource_string = l10n_util::GetStringUTF8(message_id);
initial.commit09911bf2008-07-26 23:55:2943 DCHECK(!resource_string.empty());
44 switch (type) {
45 case Value::TYPE_BOOLEAN: {
[email protected]16b527162010-08-15 18:37:1046 if ("true" == resource_string)
initial.commit09911bf2008-07-26 23:55:2947 return Value::CreateBooleanValue(true);
[email protected]16b527162010-08-15 18:37:1048 if ("false" == resource_string)
initial.commit09911bf2008-07-26 23:55:2949 return Value::CreateBooleanValue(false);
50 break;
51 }
52
53 case Value::TYPE_INTEGER: {
[email protected]e83326f2010-07-31 17:29:2554 int val;
[email protected]16b527162010-08-15 18:37:1055 base::StringToInt(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2556 return Value::CreateIntegerValue(val);
initial.commit09911bf2008-07-26 23:55:2957 }
58
[email protected]fb534c92011-02-01 01:02:0759 case Value::TYPE_DOUBLE: {
[email protected]e83326f2010-07-31 17:29:2560 double val;
[email protected]16b527162010-08-15 18:37:1061 base::StringToDouble(resource_string, &val);
[email protected]fb534c92011-02-01 01:02:0762 return Value::CreateDoubleValue(val);
initial.commit09911bf2008-07-26 23:55:2963 }
64
65 case Value::TYPE_STRING: {
66 return Value::CreateStringValue(resource_string);
initial.commit09911bf2008-07-26 23:55:2967 }
68
69 default: {
[email protected]b154e6f2009-03-06 01:52:4070 NOTREACHED() <<
[email protected]c3b54f372010-09-14 08:25:0771 "list and dictionary types cannot have default locale values";
initial.commit09911bf2008-07-26 23:55:2972 }
73 }
74 NOTREACHED();
75 return Value::CreateNullValue();
76}
77
[email protected]ba399672010-04-06 15:42:3978// Forwards a notification after a PostMessage so that we can wait for the
79// MessageLoop to run.
80void NotifyReadError(PrefService* pref, int message_id) {
81 Source<PrefService> source(pref);
82 NotificationService::current()->Notify(NotificationType::PROFILE_ERROR,
83 source, Details<int>(&message_id));
84}
85
initial.commit09911bf2008-07-26 23:55:2986} // namespace
87
[email protected]db198b22010-07-12 16:48:4988// static
[email protected]a9c23a52010-08-04 09:13:4489PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
[email protected]f2d1f612010-12-09 15:10:1790 PrefStore* extension_prefs,
[email protected]a9c23a52010-08-04 09:13:4491 Profile* profile) {
[email protected]acd78969c2010-12-08 09:49:1192 using policy::ConfigurationPolicyPrefStore;
93
[email protected]1d01d412010-08-20 00:36:0194#if defined(OS_LINUX)
95 // We'd like to see what fraction of our users have the preferences
96 // stored on a network file system, as we've had no end of troubles
97 // with NFS/AFS.
98 // TODO(evanm): remove this once we've collected state.
99 file_util::FileSystemType fstype;
100 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
101 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
102 static_cast<int>(fstype),
103 file_util::FILE_SYSTEM_TYPE_COUNT);
104 }
105#endif
106
[email protected]887288f02011-02-04 22:52:46107 ConfigurationPolicyPrefStore* managed_platform =
[email protected]acd78969c2010-12-08 09:49:11108 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore();
[email protected]887288f02011-02-04 22:52:46109 ConfigurationPolicyPrefStore* managed_cloud =
110 ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(profile);
[email protected]acd78969c2010-12-08 09:49:11111 CommandLinePrefStore* command_line =
112 new CommandLinePrefStore(CommandLine::ForCurrentProcess());
113 JsonPrefStore* user = new JsonPrefStore(
114 pref_filename,
115 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
[email protected]887288f02011-02-04 22:52:46116 ConfigurationPolicyPrefStore* recommended_platform =
117 ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore();
118 ConfigurationPolicyPrefStore* recommended_cloud =
119 ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
120 profile);
[email protected]9a8c4022011-01-25 14:25:33121 DefaultPrefStore* default_pref_store = new DefaultPrefStore();
[email protected]acd78969c2010-12-08 09:49:11122
[email protected]887288f02011-02-04 22:52:46123 return new PrefService(managed_platform, managed_cloud, extension_prefs,
124 command_line, user, recommended_platform,
125 recommended_cloud, default_pref_store);
[email protected]9a8c4022011-01-25 14:25:33126}
127
128PrefService* PrefService::CreateIncognitoPrefService(
129 PrefStore* incognito_extension_prefs) {
130 return new PrefService(*this, incognito_extension_prefs);
[email protected]d8b08c92010-06-07 13:13:28131}
132
[email protected]acd78969c2010-12-08 09:49:11133PrefService::PrefService(PrefStore* managed_platform_prefs,
[email protected]887288f02011-02-04 22:52:46134 PrefStore* managed_cloud_prefs,
[email protected]acd78969c2010-12-08 09:49:11135 PrefStore* extension_prefs,
136 PrefStore* command_line_prefs,
[email protected]f2d1f612010-12-09 15:10:17137 PersistentPrefStore* user_prefs,
[email protected]887288f02011-02-04 22:52:46138 PrefStore* recommended_platform_prefs,
139 PrefStore* recommended_cloud_prefs,
[email protected]9a8c4022011-01-25 14:25:33140 DefaultPrefStore* default_store)
141 : user_pref_store_(user_prefs),
142 default_store_(default_store) {
[email protected]acd78969c2010-12-08 09:49:11143 pref_notifier_.reset(new PrefNotifierImpl(this));
[email protected]a98ce1262011-01-28 13:20:23144 pref_value_store_.reset(
[email protected]acd78969c2010-12-08 09:49:11145 new PrefValueStore(managed_platform_prefs,
[email protected]887288f02011-02-04 22:52:46146 managed_cloud_prefs,
[email protected]f2d1f612010-12-09 15:10:17147 extension_prefs,
[email protected]acd78969c2010-12-08 09:49:11148 command_line_prefs,
[email protected]f2d1f612010-12-09 15:10:17149 user_pref_store_,
[email protected]887288f02011-02-04 22:52:46150 recommended_platform_prefs,
151 recommended_cloud_prefs,
[email protected]9a8c4022011-01-25 14:25:33152 default_store,
[email protected]a98ce1262011-01-28 13:20:23153 pref_notifier_.get()));
[email protected]277404c22010-04-22 13:09:45154 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29155}
156
[email protected]9a8c4022011-01-25 14:25:33157PrefService::PrefService(const PrefService& original,
158 PrefStore* incognito_extension_prefs)
159 : user_pref_store_(
160 new OverlayPersistentPrefStore(original.user_pref_store_.get())),
161 default_store_(original.default_store_.get()){
162 pref_notifier_.reset(new PrefNotifierImpl(this));
[email protected]a98ce1262011-01-28 13:20:23163 pref_value_store_.reset(original.pref_value_store_->CloneAndSpecialize(
[email protected]9a8c4022011-01-25 14:25:33164 NULL, // managed_platform_prefs
[email protected]887288f02011-02-04 22:52:46165 NULL, // managed_cloud_prefs
[email protected]9a8c4022011-01-25 14:25:33166 incognito_extension_prefs,
167 NULL, // command_line_prefs
168 user_pref_store_.get(),
[email protected]887288f02011-02-04 22:52:46169 NULL, // recommended_platform_prefs
170 NULL, // recommended_cloud_prefs
[email protected]9a8c4022011-01-25 14:25:33171 default_store_.get(),
[email protected]a98ce1262011-01-28 13:20:23172 pref_notifier_.get()));
[email protected]9a8c4022011-01-25 14:25:33173 InitFromStorage();
174}
175
initial.commit09911bf2008-07-26 23:55:29176PrefService::~PrefService() {
177 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29178 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
179 prefs_.clear();
[email protected]a98ce1262011-01-28 13:20:23180
181 // Reset pointers so accesses after destruction reliably crash.
182 pref_value_store_.reset();
183 user_pref_store_ = NULL;
184 default_store_ = NULL;
initial.commit09911bf2008-07-26 23:55:29185}
186
[email protected]277404c22010-04-22 13:09:45187void PrefService::InitFromStorage() {
[email protected]f2d1f612010-12-09 15:10:17188 const PersistentPrefStore::PrefReadError error =
189 user_pref_store_->ReadPrefs();
190 if (error == PersistentPrefStore::PREF_READ_ERROR_NONE)
[email protected]ba399672010-04-06 15:42:39191 return;
initial.commit09911bf2008-07-26 23:55:29192
[email protected]ba399672010-04-06 15:42:39193 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
194 // an example problem that this can cause.
195 // Do some diagnosis and try to avoid losing data.
196 int message_id = 0;
[email protected]f2d1f612010-12-09 15:10:17197 if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
[email protected]ba399672010-04-06 15:42:39198 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
[email protected]f2d1f612010-12-09 15:10:17199 } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
[email protected]ba399672010-04-06 15:42:39200 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
201 }
202
203 if (message_id) {
[email protected]8bac2352010-10-10 18:53:21204 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
[email protected]ba399672010-04-06 15:42:39205 NewRunnableFunction(&NotifyReadError, this, message_id));
206 }
207 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
208}
209
210bool PrefService::ReloadPersistentPrefs() {
[email protected]f2d1f612010-12-09 15:10:17211 return user_pref_store_->ReadPrefs() ==
212 PersistentPrefStore::PREF_READ_ERROR_NONE;
initial.commit09911bf2008-07-26 23:55:29213}
214
[email protected]6faa0e0d2009-04-28 06:50:36215bool PrefService::SavePersistentPrefs() {
216 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29217
[email protected]f2d1f612010-12-09 15:10:17218 return user_pref_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36219}
220
[email protected]6c1164042009-05-08 14:41:08221void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36222 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39223
[email protected]f2d1f612010-12-09 15:10:17224 user_pref_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29225}
226
[email protected]57ecc4b2010-08-11 03:02:51227void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29228 bool default_value) {
[email protected]c3b54f372010-09-14 08:25:07229 RegisterPreference(path, Value::CreateBooleanValue(default_value));
initial.commit09911bf2008-07-26 23:55:29230}
231
[email protected]57ecc4b2010-08-11 03:02:51232void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]c3b54f372010-09-14 08:25:07233 RegisterPreference(path, Value::CreateIntegerValue(default_value));
initial.commit09911bf2008-07-26 23:55:29234}
235
[email protected]fb534c92011-02-01 01:02:07236void PrefService::RegisterDoublePref(const char* path, double default_value) {
237 RegisterPreference(path, Value::CreateDoubleValue(default_value));
initial.commit09911bf2008-07-26 23:55:29238}
239
[email protected]57ecc4b2010-08-11 03:02:51240void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04241 const std::string& default_value) {
[email protected]c3b54f372010-09-14 08:25:07242 RegisterPreference(path, Value::CreateStringValue(default_value));
initial.commit09911bf2008-07-26 23:55:29243}
244
[email protected]57ecc4b2010-08-11 03:02:51245void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25246 const FilePath& default_value) {
[email protected]c3b54f372010-09-14 08:25:07247 RegisterPreference(path, Value::CreateStringValue(default_value.value()));
[email protected]b9636002009-03-04 00:05:25248}
249
[email protected]57ecc4b2010-08-11 03:02:51250void PrefService::RegisterListPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07251 RegisterPreference(path, new ListValue());
initial.commit09911bf2008-07-26 23:55:29252}
253
[email protected]c2f23d012011-02-09 14:52:17254void PrefService::RegisterListPref(const char* path, ListValue* default_value) {
255 RegisterPreference(path, default_value);
256}
257
[email protected]57ecc4b2010-08-11 03:02:51258void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07259 RegisterPreference(path, new DictionaryValue());
initial.commit09911bf2008-07-26 23:55:29260}
261
[email protected]c2f23d012011-02-09 14:52:17262void PrefService::RegisterDictionaryPref(const char* path,
263 DictionaryValue* default_value) {
264 RegisterPreference(path, default_value);
265}
266
[email protected]57ecc4b2010-08-11 03:02:51267void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29268 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07269 RegisterPreference(
270 path,
initial.commit09911bf2008-07-26 23:55:29271 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29272}
273
[email protected]57ecc4b2010-08-11 03:02:51274void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29275 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07276 RegisterPreference(
277 path,
initial.commit09911bf2008-07-26 23:55:29278 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29279}
280
[email protected]fb534c92011-02-01 01:02:07281void PrefService::RegisterLocalizedDoublePref(const char* path,
282 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07283 RegisterPreference(
284 path,
[email protected]fb534c92011-02-01 01:02:07285 CreateLocaleDefaultValue(Value::TYPE_DOUBLE, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29286}
287
[email protected]57ecc4b2010-08-11 03:02:51288void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29289 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07290 RegisterPreference(
291 path,
initial.commit09911bf2008-07-26 23:55:29292 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29293}
294
[email protected]57ecc4b2010-08-11 03:02:51295bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29296 DCHECK(CalledOnValidThread());
297
298 bool result = false;
initial.commit09911bf2008-07-26 23:55:29299
300 const Preference* pref = FindPreference(path);
301 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40302 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29303 return result;
304 }
305 bool rv = pref->GetValue()->GetAsBoolean(&result);
306 DCHECK(rv);
307 return result;
308}
309
[email protected]57ecc4b2010-08-11 03:02:51310int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29311 DCHECK(CalledOnValidThread());
312
313 int result = 0;
initial.commit09911bf2008-07-26 23:55:29314
315 const Preference* pref = FindPreference(path);
316 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40317 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29318 return result;
319 }
320 bool rv = pref->GetValue()->GetAsInteger(&result);
321 DCHECK(rv);
322 return result;
323}
324
[email protected]fb534c92011-02-01 01:02:07325double PrefService::GetDouble(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29326 DCHECK(CalledOnValidThread());
327
328 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29329
330 const Preference* pref = FindPreference(path);
331 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40332 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29333 return result;
334 }
[email protected]fb534c92011-02-01 01:02:07335 bool rv = pref->GetValue()->GetAsDouble(&result);
initial.commit09911bf2008-07-26 23:55:29336 DCHECK(rv);
337 return result;
338}
339
[email protected]57ecc4b2010-08-11 03:02:51340std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29341 DCHECK(CalledOnValidThread());
342
[email protected]ddd231e2010-06-29 20:35:19343 std::string result;
[email protected]8e50b602009-03-03 22:59:43344
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 result;
349 }
350 bool rv = pref->GetValue()->GetAsString(&result);
351 DCHECK(rv);
352 return result;
353}
354
[email protected]57ecc4b2010-08-11 03:02:51355FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25356 DCHECK(CalledOnValidThread());
357
[email protected]68d9d352011-02-21 16:35:04358 FilePath result;
[email protected]b9636002009-03-04 00:05:25359
360 const Preference* pref = FindPreference(path);
361 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40362 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25363 return FilePath(result);
364 }
[email protected]68d9d352011-02-21 16:35:04365 bool rv = pref->GetValue()->GetAsFilePath(&result);
[email protected]b9636002009-03-04 00:05:25366 DCHECK(rv);
[email protected]68d9d352011-02-21 16:35:04367 return result;
[email protected]b9636002009-03-04 00:05:25368}
369
[email protected]57ecc4b2010-08-11 03:02:51370bool PrefService::HasPrefPath(const char* path) const {
[email protected]9a8c4022011-01-25 14:25:33371 const Preference* pref = FindPreference(path);
372 return pref && !pref->IsDefaultValue();
initial.commit09911bf2008-07-26 23:55:29373}
374
[email protected]ebd0b022011-01-27 13:24:14375DictionaryValue* PrefService::GetPreferenceValues() const {
376 DCHECK(CalledOnValidThread());
377 DictionaryValue* out = new DictionaryValue;
378 DefaultPrefStore::const_iterator i = default_store_->begin();
379 for (; i != default_store_->end(); ++i) {
380 const Value* value = FindPreference(i->first.c_str())->GetValue();
381 out->Set(i->first, value->DeepCopy());
382 }
383 return out;
384}
385
initial.commit09911bf2008-07-26 23:55:29386const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51387 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29388 DCHECK(CalledOnValidThread());
[email protected]9a8c4022011-01-25 14:25:33389 Preference p(this, pref_name, Value::TYPE_NULL);
initial.commit09911bf2008-07-26 23:55:29390 PreferenceSet::const_iterator it = prefs_.find(&p);
[email protected]9a8c4022011-01-25 14:25:33391 if (it != prefs_.end())
392 return *it;
393 const Value::ValueType type = default_store_->GetType(pref_name);
394 if (type == Value::TYPE_NULL)
395 return NULL;
396 Preference* new_pref = new Preference(this, pref_name, type);
397 prefs_.insert(new_pref);
398 return new_pref;
initial.commit09911bf2008-07-26 23:55:29399}
400
[email protected]acd78969c2010-12-08 09:49:11401bool PrefService::ReadOnly() const {
[email protected]f2d1f612010-12-09 15:10:17402 return user_pref_store_->ReadOnly();
[email protected]acd78969c2010-12-08 09:49:11403}
404
405PrefNotifier* PrefService::pref_notifier() const {
406 return pref_notifier_.get();
407}
408
[email protected]57ecc4b2010-08-11 03:02:51409bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48410 const Preference* pref = FindPreference(pref_name);
[email protected]9a8c4022011-01-25 14:25:33411 return pref && pref->IsManaged();
[email protected]d90de1c02010-07-19 19:50:48412}
413
[email protected]57ecc4b2010-08-11 03:02:51414const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29415 DCHECK(CalledOnValidThread());
416
initial.commit09911bf2008-07-26 23:55:29417 const Preference* pref = FindPreference(path);
418 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40419 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29420 return NULL;
421 }
422 const Value* value = pref->GetValue();
[email protected]11b040b2011-02-02 12:42:25423 if (value->GetType() != Value::TYPE_DICTIONARY) {
424 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29425 return NULL;
[email protected]11b040b2011-02-02 12:42:25426 }
initial.commit09911bf2008-07-26 23:55:29427 return static_cast<const DictionaryValue*>(value);
428}
429
[email protected]57ecc4b2010-08-11 03:02:51430const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29431 DCHECK(CalledOnValidThread());
432
initial.commit09911bf2008-07-26 23:55:29433 const Preference* pref = FindPreference(path);
434 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40435 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29436 return NULL;
437 }
438 const Value* value = pref->GetValue();
[email protected]11b040b2011-02-02 12:42:25439 if (value->GetType() != Value::TYPE_LIST) {
440 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29441 return NULL;
[email protected]11b040b2011-02-02 12:42:25442 }
initial.commit09911bf2008-07-26 23:55:29443 return static_cast<const ListValue*>(value);
444}
445
[email protected]57ecc4b2010-08-11 03:02:51446void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29447 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50448 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29449}
450
[email protected]57ecc4b2010-08-11 03:02:51451void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29452 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50453 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29454}
455
[email protected]c3b54f372010-09-14 08:25:07456void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29457 DCHECK(CalledOnValidThread());
458
[email protected]c3b54f372010-09-14 08:25:07459 // The main code path takes ownership, but most don't. We'll be safe.
460 scoped_ptr<Value> scoped_value(default_value);
461
462 if (FindPreference(path)) {
463 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29464 return;
465 }
[email protected]c3b54f372010-09-14 08:25:07466
[email protected]99cc9a02010-09-17 07:53:28467 Value::ValueType orig_type = default_value->GetType();
468 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
469 "invalid preference type: " << orig_type;
470
[email protected]9a8c4022011-01-25 14:25:33471 // Hand off ownership.
472 default_store_->SetDefaultValue(path, scoped_value.release());
initial.commit09911bf2008-07-26 23:55:29473}
474
[email protected]57ecc4b2010-08-11 03:02:51475void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29476 DCHECK(CalledOnValidThread());
477
478 const Preference* pref = FindPreference(path);
479 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40480 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29481 return;
482 }
[email protected]f2d1f612010-12-09 15:10:17483 user_pref_store_->RemoveValue(path);
initial.commit09911bf2008-07-26 23:55:29484}
485
[email protected]57ecc4b2010-08-11 03:02:51486void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39487 DCHECK(CalledOnValidThread());
488
489 const Preference* pref = FindPreference(path);
490 if (!pref) {
491 NOTREACHED() << "Trying to write an unregistered pref: " << path;
492 return;
493 }
[email protected]ecde2742010-04-02 17:36:18494
[email protected]9a8c4022011-01-25 14:25:33495 if (pref->GetType() != value.GetType()) {
[email protected]99cc9a02010-09-17 07:53:28496 NOTREACHED() << "Trying to set pref " << path
497 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07498 << " to value of type " << value.GetType();
499 } else {
[email protected]f2d1f612010-12-09 15:10:17500 user_pref_store_->SetValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18501 }
[email protected]a048d7e42009-12-01 01:02:39502}
503
[email protected]57ecc4b2010-08-11 03:02:51504void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07505 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29506}
507
[email protected]57ecc4b2010-08-11 03:02:51508void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07509 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29510}
511
[email protected]fb534c92011-02-01 01:02:07512void PrefService::SetDouble(const char* path, double value) {
513 SetUserPrefValue(path, Value::CreateDoubleValue(value));
initial.commit09911bf2008-07-26 23:55:29514}
515
[email protected]57ecc4b2010-08-11 03:02:51516void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07517 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29518}
519
[email protected]57ecc4b2010-08-11 03:02:51520void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]68d9d352011-02-21 16:35:04521 SetUserPrefValue(path, Value::CreateFilePathValue(value));
[email protected]b9636002009-03-04 00:05:25522}
523
[email protected]57ecc4b2010-08-11 03:02:51524void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07525 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32526}
527
[email protected]57ecc4b2010-08-11 03:02:51528int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32529 DCHECK(CalledOnValidThread());
530
[email protected]0bb1a622009-03-04 03:22:32531 const Preference* pref = FindPreference(path);
532 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40533 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08534 return 0;
[email protected]0bb1a622009-03-04 03:22:32535 }
[email protected]dc9a6762010-08-16 07:13:53536 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32537 bool rv = pref->GetValue()->GetAsString(&result);
538 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25539
540 int64 val;
[email protected]dc9a6762010-08-16 07:13:53541 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25542 return val;
[email protected]0bb1a622009-03-04 03:22:32543}
544
[email protected]57ecc4b2010-08-11 03:02:51545void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07546 RegisterPreference(
547 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32548}
549
[email protected]57ecc4b2010-08-11 03:02:51550DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29551 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11552 DLOG_IF(WARNING, IsManagedPreference(path)) <<
553 "Attempt to change managed preference " << path;
initial.commit09911bf2008-07-26 23:55:29554
555 const Preference* pref = FindPreference(path);
556 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40557 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29558 return NULL;
559 }
[email protected]99cc9a02010-09-17 07:53:28560 if (pref->GetType() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40561 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29562 return NULL;
563 }
564
565 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28566 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53567 // Look for an existing preference in the user store. If it doesn't
568 // exist or isn't the correct type, create a new user preference.
[email protected]f2d1f612010-12-09 15:10:17569 if (user_pref_store_->GetValue(path, &tmp_value)
570 != PersistentPrefStore::READ_OK ||
[email protected]91761242010-06-10 15:35:37571 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29572 dict = new DictionaryValue;
[email protected]f2d1f612010-12-09 15:10:17573 user_pref_store_->SetValueSilently(path, dict);
[email protected]d8b08c92010-06-07 13:13:28574 } else {
575 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29576 }
577 return dict;
578}
579
[email protected]57ecc4b2010-08-11 03:02:51580ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29581 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11582 DLOG_IF(WARNING, IsManagedPreference(path)) <<
583 "Attempt to change managed preference " << path;
initial.commit09911bf2008-07-26 23:55:29584
585 const Preference* pref = FindPreference(path);
586 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40587 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29588 return NULL;
589 }
[email protected]99cc9a02010-09-17 07:53:28590 if (pref->GetType() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40591 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29592 return NULL;
593 }
594
595 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28596 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53597 // Look for an existing preference in the user store. If it doesn't
598 // exist or isn't the correct type, create a new user preference.
[email protected]f2d1f612010-12-09 15:10:17599 if (user_pref_store_->GetValue(path, &tmp_value)
600 != PersistentPrefStore::READ_OK ||
[email protected]c3b54f372010-09-14 08:25:07601 !tmp_value->IsType(Value::TYPE_LIST)) {
initial.commit09911bf2008-07-26 23:55:29602 list = new ListValue;
[email protected]f2d1f612010-12-09 15:10:17603 user_pref_store_->SetValueSilently(path, list);
[email protected]d8b08c92010-06-07 13:13:28604 } else {
605 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29606 }
607 return list;
608}
609
[email protected]c3b54f372010-09-14 08:25:07610void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
611 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11612 DLOG_IF(WARNING, IsManagedPreference(path)) <<
613 "Attempt to change managed preference " << path;
[email protected]c3b54f372010-09-14 08:25:07614
615 const Preference* pref = FindPreference(path);
616 if (!pref) {
617 NOTREACHED() << "Trying to write an unregistered pref: " << path;
618 return;
619 }
[email protected]99cc9a02010-09-17 07:53:28620 if (pref->GetType() != new_value->GetType()) {
621 NOTREACHED() << "Trying to set pref " << path
622 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07623 << " to value of type " << new_value->GetType();
624 return;
625 }
626
[email protected]f2d1f612010-12-09 15:10:17627 user_pref_store_->SetValue(path, new_value);
[email protected]73c47932010-12-06 18:13:43628}
629
initial.commit09911bf2008-07-26 23:55:29630///////////////////////////////////////////////////////////////////////////////
631// PrefService::Preference
632
[email protected]c3b54f372010-09-14 08:25:07633PrefService::Preference::Preference(const PrefService* service,
[email protected]9a8c4022011-01-25 14:25:33634 const char* name,
635 Value::ValueType type)
[email protected]99cc9a02010-09-17 07:53:28636 : name_(name),
[email protected]9a8c4022011-01-25 14:25:33637 type_(type),
[email protected]c3b54f372010-09-14 08:25:07638 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29639 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07640 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28641}
642
643Value::ValueType PrefService::Preference::GetType() const {
[email protected]9a8c4022011-01-25 14:25:33644 return type_;
initial.commit09911bf2008-07-26 23:55:29645}
646
647const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07648 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29649 "Must register pref before getting its value";
650
[email protected]c3b54f372010-09-14 08:25:07651 Value* found_value = NULL;
[email protected]887288f02011-02-04 22:52:46652 if (pref_value_store()->GetValue(name_, type_, &found_value)) {
[email protected]9a8c4022011-01-25 14:25:33653 DCHECK(found_value->IsType(type_));
[email protected]99cc9a02010-09-17 07:53:28654 return found_value;
[email protected]9a8c4022011-01-25 14:25:33655 }
initial.commit09911bf2008-07-26 23:55:29656
[email protected]c3b54f372010-09-14 08:25:07657 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28658 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07659 return NULL;
[email protected]40a47c162010-09-09 11:14:01660}
661
662bool PrefService::Preference::IsManaged() const {
[email protected]887288f02011-02-04 22:52:46663 return pref_value_store()->PrefValueInManagedStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01664}
665
666bool PrefService::Preference::HasExtensionSetting() const {
[email protected]887288f02011-02-04 22:52:46667 return pref_value_store()->PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01668}
669
670bool PrefService::Preference::HasUserSetting() const {
[email protected]887288f02011-02-04 22:52:46671 return pref_value_store()->PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01672}
673
674bool PrefService::Preference::IsExtensionControlled() const {
[email protected]887288f02011-02-04 22:52:46675 return pref_value_store()->PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01676}
677
678bool PrefService::Preference::IsUserControlled() const {
[email protected]887288f02011-02-04 22:52:46679 return pref_value_store()->PrefValueFromUserStore(name_.c_str());
[email protected]c3b54f372010-09-14 08:25:07680}
681
682bool PrefService::Preference::IsDefaultValue() const {
[email protected]887288f02011-02-04 22:52:46683 return pref_value_store()->PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35684}
[email protected]74379bc52010-07-21 13:54:08685
686bool PrefService::Preference::IsUserModifiable() const {
[email protected]887288f02011-02-04 22:52:46687 return pref_value_store()->PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08688}