blob: 2ab04f89704f96059a3865a67e7bf74fe2f95917 [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
59 case Value::TYPE_REAL: {
[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]e83326f2010-07-31 17:29:2562 return Value::CreateRealValue(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]acd78969c2010-12-08 09:49:11107 ConfigurationPolicyPrefStore* managed =
108 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore();
109 ConfigurationPolicyPrefStore* device_management =
110 ConfigurationPolicyPrefStore::CreateDeviceManagementPolicyPrefStore(
111 profile);
[email protected]acd78969c2010-12-08 09:49:11112 CommandLinePrefStore* command_line =
113 new CommandLinePrefStore(CommandLine::ForCurrentProcess());
114 JsonPrefStore* user = new JsonPrefStore(
115 pref_filename,
116 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
117 ConfigurationPolicyPrefStore* recommended =
118 ConfigurationPolicyPrefStore::CreateRecommendedPolicyPrefStore();
[email protected]9a8c4022011-01-25 14:25:33119 DefaultPrefStore* default_pref_store = new DefaultPrefStore();
[email protected]acd78969c2010-12-08 09:49:11120
[email protected]f2d1f612010-12-09 15:10:17121 return new PrefService(managed, device_management, extension_prefs,
[email protected]9a8c4022011-01-25 14:25:33122 command_line, user, recommended, default_pref_store);
123}
124
125PrefService* PrefService::CreateIncognitoPrefService(
126 PrefStore* incognito_extension_prefs) {
127 return new PrefService(*this, incognito_extension_prefs);
[email protected]d8b08c92010-06-07 13:13:28128}
129
[email protected]acd78969c2010-12-08 09:49:11130PrefService::PrefService(PrefStore* managed_platform_prefs,
131 PrefStore* device_management_prefs,
132 PrefStore* extension_prefs,
133 PrefStore* command_line_prefs,
[email protected]f2d1f612010-12-09 15:10:17134 PersistentPrefStore* user_prefs,
[email protected]9a8c4022011-01-25 14:25:33135 PrefStore* recommended_prefs,
136 DefaultPrefStore* default_store)
137 : user_pref_store_(user_prefs),
138 default_store_(default_store) {
[email protected]acd78969c2010-12-08 09:49:11139 pref_notifier_.reset(new PrefNotifierImpl(this));
[email protected]acd78969c2010-12-08 09:49:11140 pref_value_store_ =
141 new PrefValueStore(managed_platform_prefs,
142 device_management_prefs,
[email protected]f2d1f612010-12-09 15:10:17143 extension_prefs,
[email protected]acd78969c2010-12-08 09:49:11144 command_line_prefs,
[email protected]f2d1f612010-12-09 15:10:17145 user_pref_store_,
[email protected]acd78969c2010-12-08 09:49:11146 recommended_prefs,
[email protected]9a8c4022011-01-25 14:25:33147 default_store,
[email protected]f00768e2010-12-23 12:39:01148 pref_notifier_.get());
[email protected]277404c22010-04-22 13:09:45149 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29150}
151
[email protected]9a8c4022011-01-25 14:25:33152PrefService::PrefService(const PrefService& original,
153 PrefStore* incognito_extension_prefs)
154 : user_pref_store_(
155 new OverlayPersistentPrefStore(original.user_pref_store_.get())),
156 default_store_(original.default_store_.get()){
157 pref_notifier_.reset(new PrefNotifierImpl(this));
158 pref_value_store_ = original.pref_value_store_->CloneAndSpecialize(
159 NULL, // managed_platform_prefs
160 NULL, // device_management_prefs
161 incognito_extension_prefs,
162 NULL, // command_line_prefs
163 user_pref_store_.get(),
164 NULL, // recommended_prefs
165 default_store_.get(),
166 pref_notifier_.get() );
167 InitFromStorage();
168}
169
initial.commit09911bf2008-07-26 23:55:29170PrefService::~PrefService() {
171 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29172 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
173 prefs_.clear();
initial.commit09911bf2008-07-26 23:55:29174}
175
[email protected]277404c22010-04-22 13:09:45176void PrefService::InitFromStorage() {
[email protected]f2d1f612010-12-09 15:10:17177 const PersistentPrefStore::PrefReadError error =
178 user_pref_store_->ReadPrefs();
179 if (error == PersistentPrefStore::PREF_READ_ERROR_NONE)
[email protected]ba399672010-04-06 15:42:39180 return;
initial.commit09911bf2008-07-26 23:55:29181
[email protected]ba399672010-04-06 15:42:39182 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
183 // an example problem that this can cause.
184 // Do some diagnosis and try to avoid losing data.
185 int message_id = 0;
[email protected]f2d1f612010-12-09 15:10:17186 if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
[email protected]ba399672010-04-06 15:42:39187 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
[email protected]f2d1f612010-12-09 15:10:17188 } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
[email protected]ba399672010-04-06 15:42:39189 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
190 }
191
192 if (message_id) {
[email protected]8bac2352010-10-10 18:53:21193 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
[email protected]ba399672010-04-06 15:42:39194 NewRunnableFunction(&NotifyReadError, this, message_id));
195 }
196 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
197}
198
199bool PrefService::ReloadPersistentPrefs() {
[email protected]f2d1f612010-12-09 15:10:17200 return user_pref_store_->ReadPrefs() ==
201 PersistentPrefStore::PREF_READ_ERROR_NONE;
initial.commit09911bf2008-07-26 23:55:29202}
203
[email protected]6faa0e0d2009-04-28 06:50:36204bool PrefService::SavePersistentPrefs() {
205 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29206
[email protected]f2d1f612010-12-09 15:10:17207 return user_pref_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36208}
209
[email protected]6c1164042009-05-08 14:41:08210void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36211 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39212
[email protected]f2d1f612010-12-09 15:10:17213 user_pref_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29214}
215
[email protected]57ecc4b2010-08-11 03:02:51216void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29217 bool default_value) {
[email protected]c3b54f372010-09-14 08:25:07218 RegisterPreference(path, Value::CreateBooleanValue(default_value));
initial.commit09911bf2008-07-26 23:55:29219}
220
[email protected]57ecc4b2010-08-11 03:02:51221void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]c3b54f372010-09-14 08:25:07222 RegisterPreference(path, Value::CreateIntegerValue(default_value));
initial.commit09911bf2008-07-26 23:55:29223}
224
[email protected]57ecc4b2010-08-11 03:02:51225void PrefService::RegisterRealPref(const char* path, double default_value) {
[email protected]c3b54f372010-09-14 08:25:07226 RegisterPreference(path, Value::CreateRealValue(default_value));
initial.commit09911bf2008-07-26 23:55:29227}
228
[email protected]57ecc4b2010-08-11 03:02:51229void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04230 const std::string& default_value) {
[email protected]c3b54f372010-09-14 08:25:07231 RegisterPreference(path, Value::CreateStringValue(default_value));
initial.commit09911bf2008-07-26 23:55:29232}
233
[email protected]57ecc4b2010-08-11 03:02:51234void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25235 const FilePath& default_value) {
[email protected]c3b54f372010-09-14 08:25:07236 RegisterPreference(path, Value::CreateStringValue(default_value.value()));
[email protected]b9636002009-03-04 00:05:25237}
238
[email protected]57ecc4b2010-08-11 03:02:51239void PrefService::RegisterListPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07240 RegisterPreference(path, new ListValue());
initial.commit09911bf2008-07-26 23:55:29241}
242
[email protected]57ecc4b2010-08-11 03:02:51243void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07244 RegisterPreference(path, new DictionaryValue());
initial.commit09911bf2008-07-26 23:55:29245}
246
[email protected]57ecc4b2010-08-11 03:02:51247void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29248 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07249 RegisterPreference(
250 path,
initial.commit09911bf2008-07-26 23:55:29251 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29252}
253
[email protected]57ecc4b2010-08-11 03:02:51254void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29255 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07256 RegisterPreference(
257 path,
initial.commit09911bf2008-07-26 23:55:29258 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29259}
260
[email protected]57ecc4b2010-08-11 03:02:51261void PrefService::RegisterLocalizedRealPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29262 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07263 RegisterPreference(
264 path,
initial.commit09911bf2008-07-26 23:55:29265 CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29266}
267
[email protected]57ecc4b2010-08-11 03:02:51268void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29269 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07270 RegisterPreference(
271 path,
initial.commit09911bf2008-07-26 23:55:29272 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29273}
274
[email protected]57ecc4b2010-08-11 03:02:51275bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29276 DCHECK(CalledOnValidThread());
277
278 bool result = false;
initial.commit09911bf2008-07-26 23:55:29279
280 const Preference* pref = FindPreference(path);
281 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40282 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29283 return result;
284 }
285 bool rv = pref->GetValue()->GetAsBoolean(&result);
286 DCHECK(rv);
287 return result;
288}
289
[email protected]57ecc4b2010-08-11 03:02:51290int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29291 DCHECK(CalledOnValidThread());
292
293 int result = 0;
initial.commit09911bf2008-07-26 23:55:29294
295 const Preference* pref = FindPreference(path);
296 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40297 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29298 return result;
299 }
300 bool rv = pref->GetValue()->GetAsInteger(&result);
301 DCHECK(rv);
302 return result;
303}
304
[email protected]57ecc4b2010-08-11 03:02:51305double PrefService::GetReal(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29306 DCHECK(CalledOnValidThread());
307
308 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29309
310 const Preference* pref = FindPreference(path);
311 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40312 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29313 return result;
314 }
315 bool rv = pref->GetValue()->GetAsReal(&result);
316 DCHECK(rv);
317 return result;
318}
319
[email protected]57ecc4b2010-08-11 03:02:51320std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29321 DCHECK(CalledOnValidThread());
322
[email protected]ddd231e2010-06-29 20:35:19323 std::string result;
[email protected]8e50b602009-03-03 22:59:43324
initial.commit09911bf2008-07-26 23:55:29325 const Preference* pref = FindPreference(path);
326 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40327 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29328 return result;
329 }
330 bool rv = pref->GetValue()->GetAsString(&result);
331 DCHECK(rv);
332 return result;
333}
334
[email protected]57ecc4b2010-08-11 03:02:51335FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25336 DCHECK(CalledOnValidThread());
337
338 FilePath::StringType result;
[email protected]b9636002009-03-04 00:05:25339
340 const Preference* pref = FindPreference(path);
341 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40342 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25343 return FilePath(result);
344 }
345 bool rv = pref->GetValue()->GetAsString(&result);
346 DCHECK(rv);
[email protected]66de4f092009-09-04 23:59:40347#if defined(OS_POSIX)
348 // We store filepaths as UTF8, so convert it back to the system type.
349 result = base::SysWideToNativeMB(UTF8ToWide(result));
350#endif
[email protected]b9636002009-03-04 00:05:25351 return FilePath(result);
352}
353
[email protected]57ecc4b2010-08-11 03:02:51354bool PrefService::HasPrefPath(const char* path) const {
[email protected]9a8c4022011-01-25 14:25:33355 const Preference* pref = FindPreference(path);
356 return pref && !pref->IsDefaultValue();
initial.commit09911bf2008-07-26 23:55:29357}
358
359const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51360 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29361 DCHECK(CalledOnValidThread());
[email protected]9a8c4022011-01-25 14:25:33362 Preference p(this, pref_name, Value::TYPE_NULL);
initial.commit09911bf2008-07-26 23:55:29363 PreferenceSet::const_iterator it = prefs_.find(&p);
[email protected]9a8c4022011-01-25 14:25:33364 if (it != prefs_.end())
365 return *it;
366 const Value::ValueType type = default_store_->GetType(pref_name);
367 if (type == Value::TYPE_NULL)
368 return NULL;
369 Preference* new_pref = new Preference(this, pref_name, type);
370 prefs_.insert(new_pref);
371 return new_pref;
initial.commit09911bf2008-07-26 23:55:29372}
373
[email protected]acd78969c2010-12-08 09:49:11374bool PrefService::ReadOnly() const {
[email protected]f2d1f612010-12-09 15:10:17375 return user_pref_store_->ReadOnly();
[email protected]acd78969c2010-12-08 09:49:11376}
377
378PrefNotifier* PrefService::pref_notifier() const {
379 return pref_notifier_.get();
380}
381
[email protected]57ecc4b2010-08-11 03:02:51382bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48383 const Preference* pref = FindPreference(pref_name);
[email protected]9a8c4022011-01-25 14:25:33384 return pref && pref->IsManaged();
[email protected]d90de1c02010-07-19 19:50:48385}
386
[email protected]57ecc4b2010-08-11 03:02:51387const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29388 DCHECK(CalledOnValidThread());
389
initial.commit09911bf2008-07-26 23:55:29390 const Preference* pref = FindPreference(path);
391 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40392 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29393 return NULL;
394 }
395 const Value* value = pref->GetValue();
396 if (value->GetType() == Value::TYPE_NULL)
397 return NULL;
398 return static_cast<const DictionaryValue*>(value);
399}
400
[email protected]57ecc4b2010-08-11 03:02:51401const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29402 DCHECK(CalledOnValidThread());
403
initial.commit09911bf2008-07-26 23:55:29404 const Preference* pref = FindPreference(path);
405 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40406 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29407 return NULL;
408 }
409 const Value* value = pref->GetValue();
410 if (value->GetType() == Value::TYPE_NULL)
411 return NULL;
412 return static_cast<const ListValue*>(value);
413}
414
[email protected]57ecc4b2010-08-11 03:02:51415void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29416 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50417 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29418}
419
[email protected]57ecc4b2010-08-11 03:02:51420void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29421 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50422 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29423}
424
[email protected]c3b54f372010-09-14 08:25:07425void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29426 DCHECK(CalledOnValidThread());
427
[email protected]c3b54f372010-09-14 08:25:07428 // The main code path takes ownership, but most don't. We'll be safe.
429 scoped_ptr<Value> scoped_value(default_value);
430
431 if (FindPreference(path)) {
432 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29433 return;
434 }
[email protected]c3b54f372010-09-14 08:25:07435
[email protected]99cc9a02010-09-17 07:53:28436 Value::ValueType orig_type = default_value->GetType();
437 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
438 "invalid preference type: " << orig_type;
439
[email protected]9a8c4022011-01-25 14:25:33440 // Hand off ownership.
441 default_store_->SetDefaultValue(path, scoped_value.release());
initial.commit09911bf2008-07-26 23:55:29442}
443
[email protected]57ecc4b2010-08-11 03:02:51444void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29445 DCHECK(CalledOnValidThread());
446
447 const Preference* pref = FindPreference(path);
448 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40449 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29450 return;
451 }
[email protected]f2d1f612010-12-09 15:10:17452 user_pref_store_->RemoveValue(path);
initial.commit09911bf2008-07-26 23:55:29453}
454
[email protected]57ecc4b2010-08-11 03:02:51455void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39456 DCHECK(CalledOnValidThread());
457
458 const Preference* pref = FindPreference(path);
459 if (!pref) {
460 NOTREACHED() << "Trying to write an unregistered pref: " << path;
461 return;
462 }
[email protected]ecde2742010-04-02 17:36:18463
[email protected]9a8c4022011-01-25 14:25:33464 if (pref->GetType() != value.GetType()) {
[email protected]99cc9a02010-09-17 07:53:28465 NOTREACHED() << "Trying to set pref " << path
466 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07467 << " to value of type " << value.GetType();
468 } else {
[email protected]f2d1f612010-12-09 15:10:17469 user_pref_store_->SetValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18470 }
[email protected]a048d7e42009-12-01 01:02:39471}
472
[email protected]57ecc4b2010-08-11 03:02:51473void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07474 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29475}
476
[email protected]57ecc4b2010-08-11 03:02:51477void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07478 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29479}
480
[email protected]57ecc4b2010-08-11 03:02:51481void PrefService::SetReal(const char* path, double value) {
[email protected]c3b54f372010-09-14 08:25:07482 SetUserPrefValue(path, Value::CreateRealValue(value));
initial.commit09911bf2008-07-26 23:55:29483}
484
[email protected]57ecc4b2010-08-11 03:02:51485void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07486 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29487}
488
[email protected]57ecc4b2010-08-11 03:02:51489void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]66de4f092009-09-04 23:59:40490#if defined(OS_POSIX)
491 // Value::SetString only knows about UTF8 strings, so convert the path from
492 // the system native value to UTF8.
493 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value()));
[email protected]d8b08c92010-06-07 13:13:28494 Value* new_value = Value::CreateStringValue(path_utf8);
[email protected]66de4f092009-09-04 23:59:40495#else
[email protected]d8b08c92010-06-07 13:13:28496 Value* new_value = Value::CreateStringValue(value.value());
[email protected]66de4f092009-09-04 23:59:40497#endif
[email protected]b9636002009-03-04 00:05:25498
[email protected]c3b54f372010-09-14 08:25:07499 SetUserPrefValue(path, new_value);
[email protected]b9636002009-03-04 00:05:25500}
501
[email protected]57ecc4b2010-08-11 03:02:51502void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07503 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32504}
505
[email protected]57ecc4b2010-08-11 03:02:51506int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32507 DCHECK(CalledOnValidThread());
508
[email protected]0bb1a622009-03-04 03:22:32509 const Preference* pref = FindPreference(path);
510 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40511 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08512 return 0;
[email protected]0bb1a622009-03-04 03:22:32513 }
[email protected]dc9a6762010-08-16 07:13:53514 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32515 bool rv = pref->GetValue()->GetAsString(&result);
516 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25517
518 int64 val;
[email protected]dc9a6762010-08-16 07:13:53519 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25520 return val;
[email protected]0bb1a622009-03-04 03:22:32521}
522
[email protected]57ecc4b2010-08-11 03:02:51523void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07524 RegisterPreference(
525 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32526}
527
[email protected]57ecc4b2010-08-11 03:02:51528DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29529 DCHECK(CalledOnValidThread());
530
531 const Preference* pref = FindPreference(path);
532 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40533 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29534 return NULL;
535 }
[email protected]99cc9a02010-09-17 07:53:28536 if (pref->GetType() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40537 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29538 return NULL;
539 }
540
541 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28542 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53543 // Look for an existing preference in the user store. If it doesn't
544 // exist or isn't the correct type, create a new user preference.
[email protected]f2d1f612010-12-09 15:10:17545 if (user_pref_store_->GetValue(path, &tmp_value)
546 != PersistentPrefStore::READ_OK ||
[email protected]91761242010-06-10 15:35:37547 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29548 dict = new DictionaryValue;
[email protected]f2d1f612010-12-09 15:10:17549 user_pref_store_->SetValueSilently(path, dict);
[email protected]d8b08c92010-06-07 13:13:28550 } else {
551 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29552 }
553 return dict;
554}
555
[email protected]57ecc4b2010-08-11 03:02:51556ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29557 DCHECK(CalledOnValidThread());
558
559 const Preference* pref = FindPreference(path);
560 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40561 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29562 return NULL;
563 }
[email protected]99cc9a02010-09-17 07:53:28564 if (pref->GetType() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40565 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29566 return NULL;
567 }
568
569 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28570 Value* tmp_value = NULL;
[email protected]e0250892010-10-01 18:57:53571 // Look for an existing preference in the user store. If it doesn't
572 // exist or isn't the correct type, create a new user preference.
[email protected]f2d1f612010-12-09 15:10:17573 if (user_pref_store_->GetValue(path, &tmp_value)
574 != PersistentPrefStore::READ_OK ||
[email protected]c3b54f372010-09-14 08:25:07575 !tmp_value->IsType(Value::TYPE_LIST)) {
initial.commit09911bf2008-07-26 23:55:29576 list = new ListValue;
[email protected]f2d1f612010-12-09 15:10:17577 user_pref_store_->SetValueSilently(path, list);
[email protected]d8b08c92010-06-07 13:13:28578 } else {
579 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29580 }
581 return list;
582}
583
[email protected]c3b54f372010-09-14 08:25:07584void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
585 DCHECK(CalledOnValidThread());
586
587 const Preference* pref = FindPreference(path);
588 if (!pref) {
589 NOTREACHED() << "Trying to write an unregistered pref: " << path;
590 return;
591 }
[email protected]99cc9a02010-09-17 07:53:28592 if (pref->GetType() != new_value->GetType()) {
593 NOTREACHED() << "Trying to set pref " << path
594 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07595 << " to value of type " << new_value->GetType();
596 return;
597 }
598
[email protected]f2d1f612010-12-09 15:10:17599 user_pref_store_->SetValue(path, new_value);
[email protected]73c47932010-12-06 18:13:43600}
601
initial.commit09911bf2008-07-26 23:55:29602///////////////////////////////////////////////////////////////////////////////
603// PrefService::Preference
604
[email protected]c3b54f372010-09-14 08:25:07605PrefService::Preference::Preference(const PrefService* service,
[email protected]9a8c4022011-01-25 14:25:33606 const char* name,
607 Value::ValueType type)
[email protected]99cc9a02010-09-17 07:53:28608 : name_(name),
[email protected]9a8c4022011-01-25 14:25:33609 type_(type),
[email protected]c3b54f372010-09-14 08:25:07610 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29611 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07612 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28613}
614
615Value::ValueType PrefService::Preference::GetType() const {
[email protected]9a8c4022011-01-25 14:25:33616 return type_;
initial.commit09911bf2008-07-26 23:55:29617}
618
619const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07620 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29621 "Must register pref before getting its value";
622
[email protected]c3b54f372010-09-14 08:25:07623 Value* found_value = NULL;
[email protected]9a8c4022011-01-25 14:25:33624 if (pref_service_->pref_value_store_->GetValue(name_, type_, &found_value)) {
625 DCHECK(found_value->IsType(type_));
[email protected]99cc9a02010-09-17 07:53:28626 return found_value;
[email protected]9a8c4022011-01-25 14:25:33627 }
initial.commit09911bf2008-07-26 23:55:29628
[email protected]c3b54f372010-09-14 08:25:07629 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28630 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07631 return NULL;
[email protected]40a47c162010-09-09 11:14:01632}
633
634bool PrefService::Preference::IsManaged() const {
[email protected]f2d1f612010-12-09 15:10:17635 PrefValueStore* pref_value_store = pref_service_->pref_value_store_;
[email protected]be1c6e922010-11-17 12:49:17636 return pref_value_store->PrefValueInManagedPlatformStore(name_.c_str()) ||
637 pref_value_store->PrefValueInDeviceManagementStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01638}
639
640bool PrefService::Preference::HasExtensionSetting() const {
[email protected]c3b54f372010-09-14 08:25:07641 return pref_service_->pref_value_store_->
642 PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01643}
644
645bool PrefService::Preference::HasUserSetting() const {
[email protected]c3b54f372010-09-14 08:25:07646 return pref_service_->pref_value_store_->
647 PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01648}
649
650bool PrefService::Preference::IsExtensionControlled() const {
[email protected]c3b54f372010-09-14 08:25:07651 return pref_service_->pref_value_store_->
652 PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01653}
654
655bool PrefService::Preference::IsUserControlled() const {
[email protected]c3b54f372010-09-14 08:25:07656 return pref_service_->pref_value_store_->
657 PrefValueFromUserStore(name_.c_str());
658}
659
660bool PrefService::Preference::IsDefaultValue() const {
661 return pref_service_->pref_value_store_->
662 PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35663}
[email protected]74379bc52010-07-21 13:54:08664
665bool PrefService::Preference::IsUserModifiable() const {
[email protected]c3b54f372010-09-14 08:25:07666 return pref_service_->pref_value_store_->
667 PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08668}