blob: 1df38ee77811a8e82145ac854ffd88945aeb21d0 [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
358 FilePath::StringType 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 }
365 bool rv = pref->GetValue()->GetAsString(&result);
366 DCHECK(rv);
[email protected]66de4f092009-09-04 23:59:40367#if defined(OS_POSIX)
368 // We store filepaths as UTF8, so convert it back to the system type.
369 result = base::SysWideToNativeMB(UTF8ToWide(result));
370#endif
[email protected]b9636002009-03-04 00:05:25371 return FilePath(result);
372}
373
[email protected]57ecc4b2010-08-11 03:02:51374bool PrefService::HasPrefPath(const char* path) const {
[email protected]9a8c4022011-01-25 14:25:33375 const Preference* pref = FindPreference(path);
376 return pref && !pref->IsDefaultValue();
initial.commit09911bf2008-07-26 23:55:29377}
378
[email protected]ebd0b022011-01-27 13:24:14379DictionaryValue* PrefService::GetPreferenceValues() const {
380 DCHECK(CalledOnValidThread());
381 DictionaryValue* out = new DictionaryValue;
382 DefaultPrefStore::const_iterator i = default_store_->begin();
383 for (; i != default_store_->end(); ++i) {
384 const Value* value = FindPreference(i->first.c_str())->GetValue();
385 out->Set(i->first, value->DeepCopy());
386 }
387 return out;
388}
389
initial.commit09911bf2008-07-26 23:55:29390const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51391 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29392 DCHECK(CalledOnValidThread());
[email protected]9a8c4022011-01-25 14:25:33393 Preference p(this, pref_name, Value::TYPE_NULL);
initial.commit09911bf2008-07-26 23:55:29394 PreferenceSet::const_iterator it = prefs_.find(&p);
[email protected]9a8c4022011-01-25 14:25:33395 if (it != prefs_.end())
396 return *it;
397 const Value::ValueType type = default_store_->GetType(pref_name);
398 if (type == Value::TYPE_NULL)
399 return NULL;
400 Preference* new_pref = new Preference(this, pref_name, type);
401 prefs_.insert(new_pref);
402 return new_pref;
initial.commit09911bf2008-07-26 23:55:29403}
404
[email protected]acd78969c2010-12-08 09:49:11405bool PrefService::ReadOnly() const {
[email protected]f2d1f612010-12-09 15:10:17406 return user_pref_store_->ReadOnly();
[email protected]acd78969c2010-12-08 09:49:11407}
408
409PrefNotifier* PrefService::pref_notifier() const {
410 return pref_notifier_.get();
411}
412
[email protected]57ecc4b2010-08-11 03:02:51413bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48414 const Preference* pref = FindPreference(pref_name);
[email protected]9a8c4022011-01-25 14:25:33415 return pref && pref->IsManaged();
[email protected]d90de1c02010-07-19 19:50:48416}
417
[email protected]57ecc4b2010-08-11 03:02:51418const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29419 DCHECK(CalledOnValidThread());
420
initial.commit09911bf2008-07-26 23:55:29421 const Preference* pref = FindPreference(path);
422 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40423 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29424 return NULL;
425 }
426 const Value* value = pref->GetValue();
[email protected]11b040b2011-02-02 12:42:25427 if (value->GetType() != Value::TYPE_DICTIONARY) {
428 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29429 return NULL;
[email protected]11b040b2011-02-02 12:42:25430 }
initial.commit09911bf2008-07-26 23:55:29431 return static_cast<const DictionaryValue*>(value);
432}
433
[email protected]57ecc4b2010-08-11 03:02:51434const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29435 DCHECK(CalledOnValidThread());
436
initial.commit09911bf2008-07-26 23:55:29437 const Preference* pref = FindPreference(path);
438 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40439 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29440 return NULL;
441 }
442 const Value* value = pref->GetValue();
[email protected]11b040b2011-02-02 12:42:25443 if (value->GetType() != Value::TYPE_LIST) {
444 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29445 return NULL;
[email protected]11b040b2011-02-02 12:42:25446 }
initial.commit09911bf2008-07-26 23:55:29447 return static_cast<const ListValue*>(value);
448}
449
[email protected]57ecc4b2010-08-11 03:02:51450void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29451 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50452 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29453}
454
[email protected]57ecc4b2010-08-11 03:02:51455void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29456 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50457 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29458}
459
[email protected]c3b54f372010-09-14 08:25:07460void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29461 DCHECK(CalledOnValidThread());
462
[email protected]c3b54f372010-09-14 08:25:07463 // The main code path takes ownership, but most don't. We'll be safe.
464 scoped_ptr<Value> scoped_value(default_value);
465
466 if (FindPreference(path)) {
467 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29468 return;
469 }
[email protected]c3b54f372010-09-14 08:25:07470
[email protected]99cc9a02010-09-17 07:53:28471 Value::ValueType orig_type = default_value->GetType();
472 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
473 "invalid preference type: " << orig_type;
474
[email protected]9a8c4022011-01-25 14:25:33475 // Hand off ownership.
476 default_store_->SetDefaultValue(path, scoped_value.release());
initial.commit09911bf2008-07-26 23:55:29477}
478
[email protected]57ecc4b2010-08-11 03:02:51479void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29480 DCHECK(CalledOnValidThread());
481
482 const Preference* pref = FindPreference(path);
483 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40484 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29485 return;
486 }
[email protected]f2d1f612010-12-09 15:10:17487 user_pref_store_->RemoveValue(path);
initial.commit09911bf2008-07-26 23:55:29488}
489
[email protected]57ecc4b2010-08-11 03:02:51490void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39491 DCHECK(CalledOnValidThread());
492
493 const Preference* pref = FindPreference(path);
494 if (!pref) {
495 NOTREACHED() << "Trying to write an unregistered pref: " << path;
496 return;
497 }
[email protected]ecde2742010-04-02 17:36:18498
[email protected]9a8c4022011-01-25 14:25:33499 if (pref->GetType() != value.GetType()) {
[email protected]99cc9a02010-09-17 07:53:28500 NOTREACHED() << "Trying to set pref " << path
501 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07502 << " to value of type " << value.GetType();
503 } else {
[email protected]f2d1f612010-12-09 15:10:17504 user_pref_store_->SetValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18505 }
[email protected]a048d7e42009-12-01 01:02:39506}
507
[email protected]57ecc4b2010-08-11 03:02:51508void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07509 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29510}
511
[email protected]57ecc4b2010-08-11 03:02:51512void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07513 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29514}
515
[email protected]fb534c92011-02-01 01:02:07516void PrefService::SetDouble(const char* path, double value) {
517 SetUserPrefValue(path, Value::CreateDoubleValue(value));
initial.commit09911bf2008-07-26 23:55:29518}
519
[email protected]57ecc4b2010-08-11 03:02:51520void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07521 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29522}
523
[email protected]57ecc4b2010-08-11 03:02:51524void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]66de4f092009-09-04 23:59:40525#if defined(OS_POSIX)
526 // Value::SetString only knows about UTF8 strings, so convert the path from
527 // the system native value to UTF8.
528 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value()));
[email protected]d8b08c92010-06-07 13:13:28529 Value* new_value = Value::CreateStringValue(path_utf8);
[email protected]66de4f092009-09-04 23:59:40530#else
[email protected]d8b08c92010-06-07 13:13:28531 Value* new_value = Value::CreateStringValue(value.value());
[email protected]66de4f092009-09-04 23:59:40532#endif
[email protected]b9636002009-03-04 00:05:25533
[email protected]c3b54f372010-09-14 08:25:07534 SetUserPrefValue(path, new_value);
[email protected]b9636002009-03-04 00:05:25535}
536
[email protected]57ecc4b2010-08-11 03:02:51537void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07538 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32539}
540
[email protected]57ecc4b2010-08-11 03:02:51541int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32542 DCHECK(CalledOnValidThread());
543
[email protected]0bb1a622009-03-04 03:22:32544 const Preference* pref = FindPreference(path);
545 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40546 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08547 return 0;
[email protected]0bb1a622009-03-04 03:22:32548 }
[email protected]dc9a6762010-08-16 07:13:53549 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32550 bool rv = pref->GetValue()->GetAsString(&result);
551 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25552
553 int64 val;
[email protected]dc9a6762010-08-16 07:13:53554 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25555 return val;
[email protected]0bb1a622009-03-04 03:22:32556}
557
[email protected]57ecc4b2010-08-11 03:02:51558void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07559 RegisterPreference(
560 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32561}
562
[email protected]57ecc4b2010-08-11 03:02:51563DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29564 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11565 DLOG_IF(WARNING, IsManagedPreference(path)) <<
566 "Attempt to change managed preference " << path;
initial.commit09911bf2008-07-26 23:55:29567
568 const Preference* pref = FindPreference(path);
569 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40570 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29571 return NULL;
572 }
[email protected]99cc9a02010-09-17 07:53:28573 if (pref->GetType() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40574 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29575 return NULL;
576 }
577
578 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28579 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53580 // Look for an existing preference in the user store. If it doesn't
581 // exist or isn't the correct type, create a new user preference.
[email protected]f2d1f612010-12-09 15:10:17582 if (user_pref_store_->GetValue(path, &tmp_value)
583 != PersistentPrefStore::READ_OK ||
[email protected]91761242010-06-10 15:35:37584 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29585 dict = new DictionaryValue;
[email protected]f2d1f612010-12-09 15:10:17586 user_pref_store_->SetValueSilently(path, dict);
[email protected]d8b08c92010-06-07 13:13:28587 } else {
588 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29589 }
590 return dict;
591}
592
[email protected]57ecc4b2010-08-11 03:02:51593ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29594 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11595 DLOG_IF(WARNING, IsManagedPreference(path)) <<
596 "Attempt to change managed preference " << path;
initial.commit09911bf2008-07-26 23:55:29597
598 const Preference* pref = FindPreference(path);
599 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40600 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29601 return NULL;
602 }
[email protected]99cc9a02010-09-17 07:53:28603 if (pref->GetType() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40604 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29605 return NULL;
606 }
607
608 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28609 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53610 // Look for an existing preference in the user store. If it doesn't
611 // exist or isn't the correct type, create a new user preference.
[email protected]f2d1f612010-12-09 15:10:17612 if (user_pref_store_->GetValue(path, &tmp_value)
613 != PersistentPrefStore::READ_OK ||
[email protected]c3b54f372010-09-14 08:25:07614 !tmp_value->IsType(Value::TYPE_LIST)) {
initial.commit09911bf2008-07-26 23:55:29615 list = new ListValue;
[email protected]f2d1f612010-12-09 15:10:17616 user_pref_store_->SetValueSilently(path, list);
[email protected]d8b08c92010-06-07 13:13:28617 } else {
618 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29619 }
620 return list;
621}
622
[email protected]c3b54f372010-09-14 08:25:07623void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
624 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11625 DLOG_IF(WARNING, IsManagedPreference(path)) <<
626 "Attempt to change managed preference " << path;
[email protected]c3b54f372010-09-14 08:25:07627
628 const Preference* pref = FindPreference(path);
629 if (!pref) {
630 NOTREACHED() << "Trying to write an unregistered pref: " << path;
631 return;
632 }
[email protected]99cc9a02010-09-17 07:53:28633 if (pref->GetType() != new_value->GetType()) {
634 NOTREACHED() << "Trying to set pref " << path
635 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07636 << " to value of type " << new_value->GetType();
637 return;
638 }
639
[email protected]f2d1f612010-12-09 15:10:17640 user_pref_store_->SetValue(path, new_value);
[email protected]73c47932010-12-06 18:13:43641}
642
initial.commit09911bf2008-07-26 23:55:29643///////////////////////////////////////////////////////////////////////////////
644// PrefService::Preference
645
[email protected]c3b54f372010-09-14 08:25:07646PrefService::Preference::Preference(const PrefService* service,
[email protected]9a8c4022011-01-25 14:25:33647 const char* name,
648 Value::ValueType type)
[email protected]99cc9a02010-09-17 07:53:28649 : name_(name),
[email protected]9a8c4022011-01-25 14:25:33650 type_(type),
[email protected]c3b54f372010-09-14 08:25:07651 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29652 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07653 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28654}
655
656Value::ValueType PrefService::Preference::GetType() const {
[email protected]9a8c4022011-01-25 14:25:33657 return type_;
initial.commit09911bf2008-07-26 23:55:29658}
659
660const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07661 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29662 "Must register pref before getting its value";
663
[email protected]c3b54f372010-09-14 08:25:07664 Value* found_value = NULL;
[email protected]887288f02011-02-04 22:52:46665 if (pref_value_store()->GetValue(name_, type_, &found_value)) {
[email protected]9a8c4022011-01-25 14:25:33666 DCHECK(found_value->IsType(type_));
[email protected]99cc9a02010-09-17 07:53:28667 return found_value;
[email protected]9a8c4022011-01-25 14:25:33668 }
initial.commit09911bf2008-07-26 23:55:29669
[email protected]c3b54f372010-09-14 08:25:07670 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28671 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07672 return NULL;
[email protected]40a47c162010-09-09 11:14:01673}
674
675bool PrefService::Preference::IsManaged() const {
[email protected]887288f02011-02-04 22:52:46676 return pref_value_store()->PrefValueInManagedStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01677}
678
679bool PrefService::Preference::HasExtensionSetting() const {
[email protected]887288f02011-02-04 22:52:46680 return pref_value_store()->PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01681}
682
683bool PrefService::Preference::HasUserSetting() const {
[email protected]887288f02011-02-04 22:52:46684 return pref_value_store()->PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01685}
686
687bool PrefService::Preference::IsExtensionControlled() const {
[email protected]887288f02011-02-04 22:52:46688 return pref_value_store()->PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01689}
690
691bool PrefService::Preference::IsUserControlled() const {
[email protected]887288f02011-02-04 22:52:46692 return pref_value_store()->PrefValueFromUserStore(name_.c_str());
[email protected]c3b54f372010-09-14 08:25:07693}
694
695bool PrefService::Preference::IsDefaultValue() const {
[email protected]887288f02011-02-04 22:52:46696 return pref_value_store()->PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35697}
[email protected]74379bc52010-07-21 13:54:08698
699bool PrefService::Preference::IsUserModifiable() const {
[email protected]887288f02011-02-04 22:52:46700 return pref_value_store()->PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08701}