blob: aa71108d0a21a0e1193dd9d6e0902cdc8c7f59b4 [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]8703b2b2011-03-15 09:51:5019#include "base/value_conversions.h"
[email protected]66de4f092009-09-04 23:59:4020#include "build/build_config.h"
[email protected]9a8c4022011-01-25 14:25:3321#include "chrome/browser/extensions/extension_pref_store.h"
[email protected]acd78969c2010-12-08 09:49:1122#include "chrome/browser/policy/configuration_policy_pref_store.h"
23#include "chrome/browser/prefs/command_line_pref_store.h"
[email protected]f2d1f612010-12-09 15:10:1724#include "chrome/browser/prefs/default_pref_store.h"
[email protected]9a8c4022011-01-25 14:25:3325#include "chrome/browser/prefs/overlay_persistent_pref_store.h"
[email protected]acd78969c2010-12-08 09:49:1126#include "chrome/browser/prefs/pref_notifier_impl.h"
[email protected]39d9f62c2010-12-03 10:48:5027#include "chrome/browser/prefs/pref_value_store.h"
[email protected]c7fb2da32011-04-14 20:47:1028#include "chrome/browser/ui/profile_error_dialog.h"
[email protected]e4f86492011-04-13 12:23:5329#include "chrome/common/json_pref_store.h"
[email protected]5f945a0e2011-03-01 17:47:5330#include "content/browser/browser_thread.h"
[email protected]ebbbb9f2011-03-09 13:16:1431#include "content/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) {
[email protected]c7fb2da32011-04-14 20:47:1081 ShowProfileErrorDialog(message_id);
[email protected]ba399672010-04-06 15:42:3982}
83
initial.commit09911bf2008-07-26 23:55:2984} // namespace
85
[email protected]db198b22010-07-12 16:48:4986// static
[email protected]a9c23a52010-08-04 09:13:4487PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
[email protected]f2d1f612010-12-09 15:10:1788 PrefStore* extension_prefs,
[email protected]a9c23a52010-08-04 09:13:4489 Profile* profile) {
[email protected]844a1002011-04-19 11:37:2190 return CreatePrefServiceAsync(pref_filename, extension_prefs, profile, NULL);
91}
92
93// static
94PrefService* PrefService::CreatePrefServiceAsync(
95 const FilePath& pref_filename,
96 PrefStore* extension_prefs,
97 Profile* profile,
98 PrefService::Delegate* delegate) {
[email protected]acd78969c2010-12-08 09:49:1199 using policy::ConfigurationPolicyPrefStore;
100
[email protected]1d01d412010-08-20 00:36:01101#if defined(OS_LINUX)
102 // We'd like to see what fraction of our users have the preferences
103 // stored on a network file system, as we've had no end of troubles
104 // with NFS/AFS.
105 // TODO(evanm): remove this once we've collected state.
106 file_util::FileSystemType fstype;
107 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
108 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
109 static_cast<int>(fstype),
110 file_util::FILE_SYSTEM_TYPE_COUNT);
111 }
112#endif
113
[email protected]887288f02011-02-04 22:52:46114 ConfigurationPolicyPrefStore* managed_platform =
[email protected]acd78969c2010-12-08 09:49:11115 ConfigurationPolicyPrefStore::CreateManagedPlatformPolicyPrefStore();
[email protected]887288f02011-02-04 22:52:46116 ConfigurationPolicyPrefStore* managed_cloud =
117 ConfigurationPolicyPrefStore::CreateManagedCloudPolicyPrefStore(profile);
[email protected]acd78969c2010-12-08 09:49:11118 CommandLinePrefStore* command_line =
119 new CommandLinePrefStore(CommandLine::ForCurrentProcess());
120 JsonPrefStore* user = new JsonPrefStore(
121 pref_filename,
122 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
[email protected]887288f02011-02-04 22:52:46123 ConfigurationPolicyPrefStore* recommended_platform =
124 ConfigurationPolicyPrefStore::CreateRecommendedPlatformPolicyPrefStore();
125 ConfigurationPolicyPrefStore* recommended_cloud =
126 ConfigurationPolicyPrefStore::CreateRecommendedCloudPolicyPrefStore(
127 profile);
[email protected]9a8c4022011-01-25 14:25:33128 DefaultPrefStore* default_pref_store = new DefaultPrefStore();
[email protected]acd78969c2010-12-08 09:49:11129
[email protected]887288f02011-02-04 22:52:46130 return new PrefService(managed_platform, managed_cloud, extension_prefs,
131 command_line, user, recommended_platform,
[email protected]844a1002011-04-19 11:37:21132 recommended_cloud, default_pref_store, delegate);
[email protected]9a8c4022011-01-25 14:25:33133}
134
135PrefService* PrefService::CreateIncognitoPrefService(
136 PrefStore* incognito_extension_prefs) {
137 return new PrefService(*this, incognito_extension_prefs);
[email protected]d8b08c92010-06-07 13:13:28138}
139
[email protected]acd78969c2010-12-08 09:49:11140PrefService::PrefService(PrefStore* managed_platform_prefs,
[email protected]887288f02011-02-04 22:52:46141 PrefStore* managed_cloud_prefs,
[email protected]acd78969c2010-12-08 09:49:11142 PrefStore* extension_prefs,
143 PrefStore* command_line_prefs,
[email protected]f2d1f612010-12-09 15:10:17144 PersistentPrefStore* user_prefs,
[email protected]887288f02011-02-04 22:52:46145 PrefStore* recommended_platform_prefs,
146 PrefStore* recommended_cloud_prefs,
[email protected]844a1002011-04-19 11:37:21147 DefaultPrefStore* default_store,
148 PrefService::Delegate* delegate)
[email protected]9a8c4022011-01-25 14:25:33149 : user_pref_store_(user_prefs),
[email protected]844a1002011-04-19 11:37:21150 default_store_(default_store),
151 delegate_(delegate) {
[email protected]acd78969c2010-12-08 09:49:11152 pref_notifier_.reset(new PrefNotifierImpl(this));
[email protected]a98ce1262011-01-28 13:20:23153 pref_value_store_.reset(
[email protected]acd78969c2010-12-08 09:49:11154 new PrefValueStore(managed_platform_prefs,
[email protected]887288f02011-02-04 22:52:46155 managed_cloud_prefs,
[email protected]f2d1f612010-12-09 15:10:17156 extension_prefs,
[email protected]acd78969c2010-12-08 09:49:11157 command_line_prefs,
[email protected]f2d1f612010-12-09 15:10:17158 user_pref_store_,
[email protected]887288f02011-02-04 22:52:46159 recommended_platform_prefs,
160 recommended_cloud_prefs,
[email protected]9a8c4022011-01-25 14:25:33161 default_store,
[email protected]a98ce1262011-01-28 13:20:23162 pref_notifier_.get()));
[email protected]277404c22010-04-22 13:09:45163 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29164}
165
[email protected]9a8c4022011-01-25 14:25:33166PrefService::PrefService(const PrefService& original,
167 PrefStore* incognito_extension_prefs)
168 : user_pref_store_(
169 new OverlayPersistentPrefStore(original.user_pref_store_.get())),
[email protected]844a1002011-04-19 11:37:21170 default_store_(original.default_store_.get()),
171 delegate_(NULL) {
[email protected]9a8c4022011-01-25 14:25:33172 pref_notifier_.reset(new PrefNotifierImpl(this));
[email protected]a98ce1262011-01-28 13:20:23173 pref_value_store_.reset(original.pref_value_store_->CloneAndSpecialize(
[email protected]9a8c4022011-01-25 14:25:33174 NULL, // managed_platform_prefs
[email protected]887288f02011-02-04 22:52:46175 NULL, // managed_cloud_prefs
[email protected]9a8c4022011-01-25 14:25:33176 incognito_extension_prefs,
177 NULL, // command_line_prefs
178 user_pref_store_.get(),
[email protected]887288f02011-02-04 22:52:46179 NULL, // recommended_platform_prefs
180 NULL, // recommended_cloud_prefs
[email protected]9a8c4022011-01-25 14:25:33181 default_store_.get(),
[email protected]a98ce1262011-01-28 13:20:23182 pref_notifier_.get()));
[email protected]9a8c4022011-01-25 14:25:33183 InitFromStorage();
184}
185
initial.commit09911bf2008-07-26 23:55:29186PrefService::~PrefService() {
187 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29188 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
189 prefs_.clear();
[email protected]a98ce1262011-01-28 13:20:23190
191 // Reset pointers so accesses after destruction reliably crash.
192 pref_value_store_.reset();
193 user_pref_store_ = NULL;
194 default_store_ = NULL;
initial.commit09911bf2008-07-26 23:55:29195}
196
[email protected]844a1002011-04-19 11:37:21197void PrefService::OnPrefsRead(PersistentPrefStore::PrefReadError error,
198 bool no_dir) {
199 if (no_dir) {
200 // Bad news. When profile is created, the process that creates the directory
201 // is explicitly started. So if directory is missing it probably means that
202 // Chromium hasn't sufficient privileges.
203 CHECK(delegate_);
204 delegate_->OnPrefsLoaded(this, false);
[email protected]e4f86492011-04-13 12:23:53205 return;
[email protected]334c59d92011-04-13 11:27:06206 }
[email protected]e4f86492011-04-13 12:23:53207
[email protected]844a1002011-04-19 11:37:21208 if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
209 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
210 // an example problem that this can cause.
211 // Do some diagnosis and try to avoid losing data.
212 int message_id = 0;
213 if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
214 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
215 } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
216 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
217 }
218
219 if (message_id) {
220 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
221 NewRunnableFunction(&NotifyReadError, this, message_id));
222 }
223 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
[email protected]e4f86492011-04-13 12:23:53224 }
[email protected]844a1002011-04-19 11:37:21225
226 if (delegate_)
227 delegate_->OnPrefsLoaded(this, true);
228}
229
230void PrefService::InitFromStorage() {
231 if (!delegate_) {
232 const PersistentPrefStore::PrefReadError error =
233 user_pref_store_->ReadPrefs();
234 OnPrefsRead(error, false);
235 } else {
236 // todo(altimofeev): move this method to PersistentPrefStore interface.
237 (static_cast<JsonPrefStore*>(user_pref_store_.get()))->ReadPrefs(this);
238 }
[email protected]ba399672010-04-06 15:42:39239}
240
241bool PrefService::ReloadPersistentPrefs() {
[email protected]f2d1f612010-12-09 15:10:17242 return user_pref_store_->ReadPrefs() ==
243 PersistentPrefStore::PREF_READ_ERROR_NONE;
initial.commit09911bf2008-07-26 23:55:29244}
245
[email protected]6faa0e0d2009-04-28 06:50:36246bool PrefService::SavePersistentPrefs() {
247 DCHECK(CalledOnValidThread());
[email protected]f2d1f612010-12-09 15:10:17248 return user_pref_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36249}
250
[email protected]6c1164042009-05-08 14:41:08251void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36252 DCHECK(CalledOnValidThread());
[email protected]f2d1f612010-12-09 15:10:17253 user_pref_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29254}
255
[email protected]3826fed2011-03-25 10:59:56256void PrefService::CommitPendingWrite() {
257 DCHECK(CalledOnValidThread());
258 user_pref_store_->CommitPendingWrite();
259}
260
[email protected]57ecc4b2010-08-11 03:02:51261void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29262 bool default_value) {
[email protected]c3b54f372010-09-14 08:25:07263 RegisterPreference(path, Value::CreateBooleanValue(default_value));
initial.commit09911bf2008-07-26 23:55:29264}
265
[email protected]57ecc4b2010-08-11 03:02:51266void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]c3b54f372010-09-14 08:25:07267 RegisterPreference(path, Value::CreateIntegerValue(default_value));
initial.commit09911bf2008-07-26 23:55:29268}
269
[email protected]fb534c92011-02-01 01:02:07270void PrefService::RegisterDoublePref(const char* path, double default_value) {
271 RegisterPreference(path, Value::CreateDoubleValue(default_value));
initial.commit09911bf2008-07-26 23:55:29272}
273
[email protected]57ecc4b2010-08-11 03:02:51274void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04275 const std::string& default_value) {
[email protected]c3b54f372010-09-14 08:25:07276 RegisterPreference(path, Value::CreateStringValue(default_value));
initial.commit09911bf2008-07-26 23:55:29277}
278
[email protected]57ecc4b2010-08-11 03:02:51279void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25280 const FilePath& default_value) {
[email protected]c3b54f372010-09-14 08:25:07281 RegisterPreference(path, Value::CreateStringValue(default_value.value()));
[email protected]b9636002009-03-04 00:05:25282}
283
[email protected]57ecc4b2010-08-11 03:02:51284void PrefService::RegisterListPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07285 RegisterPreference(path, new ListValue());
initial.commit09911bf2008-07-26 23:55:29286}
287
[email protected]c2f23d012011-02-09 14:52:17288void PrefService::RegisterListPref(const char* path, ListValue* default_value) {
289 RegisterPreference(path, default_value);
290}
291
[email protected]57ecc4b2010-08-11 03:02:51292void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]c3b54f372010-09-14 08:25:07293 RegisterPreference(path, new DictionaryValue());
initial.commit09911bf2008-07-26 23:55:29294}
295
[email protected]c2f23d012011-02-09 14:52:17296void PrefService::RegisterDictionaryPref(const char* path,
297 DictionaryValue* default_value) {
298 RegisterPreference(path, default_value);
299}
300
[email protected]57ecc4b2010-08-11 03:02:51301void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29302 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07303 RegisterPreference(
304 path,
initial.commit09911bf2008-07-26 23:55:29305 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29306}
307
[email protected]57ecc4b2010-08-11 03:02:51308void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29309 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07310 RegisterPreference(
311 path,
initial.commit09911bf2008-07-26 23:55:29312 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29313}
314
[email protected]fb534c92011-02-01 01:02:07315void PrefService::RegisterLocalizedDoublePref(const char* path,
316 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07317 RegisterPreference(
318 path,
[email protected]fb534c92011-02-01 01:02:07319 CreateLocaleDefaultValue(Value::TYPE_DOUBLE, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29320}
321
[email protected]57ecc4b2010-08-11 03:02:51322void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29323 int locale_default_message_id) {
[email protected]c3b54f372010-09-14 08:25:07324 RegisterPreference(
325 path,
initial.commit09911bf2008-07-26 23:55:29326 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
initial.commit09911bf2008-07-26 23:55:29327}
328
[email protected]57ecc4b2010-08-11 03:02:51329bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29330 DCHECK(CalledOnValidThread());
331
332 bool result = false;
initial.commit09911bf2008-07-26 23:55:29333
334 const Preference* pref = FindPreference(path);
335 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40336 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29337 return result;
338 }
339 bool rv = pref->GetValue()->GetAsBoolean(&result);
340 DCHECK(rv);
341 return result;
342}
343
[email protected]57ecc4b2010-08-11 03:02:51344int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29345 DCHECK(CalledOnValidThread());
346
347 int result = 0;
initial.commit09911bf2008-07-26 23:55:29348
349 const Preference* pref = FindPreference(path);
350 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40351 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29352 return result;
353 }
354 bool rv = pref->GetValue()->GetAsInteger(&result);
355 DCHECK(rv);
356 return result;
357}
358
[email protected]fb534c92011-02-01 01:02:07359double PrefService::GetDouble(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29360 DCHECK(CalledOnValidThread());
361
362 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29363
364 const Preference* pref = FindPreference(path);
365 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40366 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29367 return result;
368 }
[email protected]fb534c92011-02-01 01:02:07369 bool rv = pref->GetValue()->GetAsDouble(&result);
initial.commit09911bf2008-07-26 23:55:29370 DCHECK(rv);
371 return result;
372}
373
[email protected]57ecc4b2010-08-11 03:02:51374std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29375 DCHECK(CalledOnValidThread());
376
[email protected]ddd231e2010-06-29 20:35:19377 std::string result;
[email protected]8e50b602009-03-03 22:59:43378
initial.commit09911bf2008-07-26 23:55:29379 const Preference* pref = FindPreference(path);
380 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40381 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29382 return result;
383 }
384 bool rv = pref->GetValue()->GetAsString(&result);
385 DCHECK(rv);
386 return result;
387}
388
[email protected]57ecc4b2010-08-11 03:02:51389FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25390 DCHECK(CalledOnValidThread());
391
[email protected]68d9d352011-02-21 16:35:04392 FilePath result;
[email protected]b9636002009-03-04 00:05:25393
394 const Preference* pref = FindPreference(path);
395 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40396 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25397 return FilePath(result);
398 }
[email protected]8703b2b2011-03-15 09:51:50399 bool rv = base::GetValueAsFilePath(*pref->GetValue(), &result);
[email protected]b9636002009-03-04 00:05:25400 DCHECK(rv);
[email protected]68d9d352011-02-21 16:35:04401 return result;
[email protected]b9636002009-03-04 00:05:25402}
403
[email protected]57ecc4b2010-08-11 03:02:51404bool PrefService::HasPrefPath(const char* path) const {
[email protected]9a8c4022011-01-25 14:25:33405 const Preference* pref = FindPreference(path);
406 return pref && !pref->IsDefaultValue();
initial.commit09911bf2008-07-26 23:55:29407}
408
[email protected]ebd0b022011-01-27 13:24:14409DictionaryValue* PrefService::GetPreferenceValues() const {
410 DCHECK(CalledOnValidThread());
411 DictionaryValue* out = new DictionaryValue;
412 DefaultPrefStore::const_iterator i = default_store_->begin();
413 for (; i != default_store_->end(); ++i) {
[email protected]8874e02172011-03-11 19:44:08414 const Preference* pref = FindPreference(i->first.c_str());
415 DCHECK(pref);
416 const Value* value = pref->GetValue();
417 DCHECK(value);
[email protected]ebd0b022011-01-27 13:24:14418 out->Set(i->first, value->DeepCopy());
419 }
420 return out;
421}
422
initial.commit09911bf2008-07-26 23:55:29423const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51424 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29425 DCHECK(CalledOnValidThread());
[email protected]9a8c4022011-01-25 14:25:33426 Preference p(this, pref_name, Value::TYPE_NULL);
initial.commit09911bf2008-07-26 23:55:29427 PreferenceSet::const_iterator it = prefs_.find(&p);
[email protected]9a8c4022011-01-25 14:25:33428 if (it != prefs_.end())
429 return *it;
430 const Value::ValueType type = default_store_->GetType(pref_name);
431 if (type == Value::TYPE_NULL)
432 return NULL;
433 Preference* new_pref = new Preference(this, pref_name, type);
434 prefs_.insert(new_pref);
435 return new_pref;
initial.commit09911bf2008-07-26 23:55:29436}
437
[email protected]acd78969c2010-12-08 09:49:11438bool PrefService::ReadOnly() const {
[email protected]f2d1f612010-12-09 15:10:17439 return user_pref_store_->ReadOnly();
[email protected]acd78969c2010-12-08 09:49:11440}
441
[email protected]57ecc4b2010-08-11 03:02:51442bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48443 const Preference* pref = FindPreference(pref_name);
[email protected]9a8c4022011-01-25 14:25:33444 return pref && pref->IsManaged();
[email protected]d90de1c02010-07-19 19:50:48445}
446
[email protected]57ecc4b2010-08-11 03:02:51447const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29448 DCHECK(CalledOnValidThread());
449
initial.commit09911bf2008-07-26 23:55:29450 const Preference* pref = FindPreference(path);
451 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40452 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29453 return NULL;
454 }
455 const Value* value = pref->GetValue();
[email protected]11b040b2011-02-02 12:42:25456 if (value->GetType() != Value::TYPE_DICTIONARY) {
457 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29458 return NULL;
[email protected]11b040b2011-02-02 12:42:25459 }
initial.commit09911bf2008-07-26 23:55:29460 return static_cast<const DictionaryValue*>(value);
461}
462
[email protected]57ecc4b2010-08-11 03:02:51463const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29464 DCHECK(CalledOnValidThread());
465
initial.commit09911bf2008-07-26 23:55:29466 const Preference* pref = FindPreference(path);
467 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40468 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29469 return NULL;
470 }
471 const Value* value = pref->GetValue();
[email protected]11b040b2011-02-02 12:42:25472 if (value->GetType() != Value::TYPE_LIST) {
473 NOTREACHED();
initial.commit09911bf2008-07-26 23:55:29474 return NULL;
[email protected]11b040b2011-02-02 12:42:25475 }
initial.commit09911bf2008-07-26 23:55:29476 return static_cast<const ListValue*>(value);
477}
478
[email protected]57ecc4b2010-08-11 03:02:51479void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29480 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50481 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29482}
483
[email protected]57ecc4b2010-08-11 03:02:51484void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29485 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50486 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29487}
488
[email protected]c3b54f372010-09-14 08:25:07489void PrefService::RegisterPreference(const char* path, Value* default_value) {
initial.commit09911bf2008-07-26 23:55:29490 DCHECK(CalledOnValidThread());
491
[email protected]c3b54f372010-09-14 08:25:07492 // The main code path takes ownership, but most don't. We'll be safe.
493 scoped_ptr<Value> scoped_value(default_value);
494
495 if (FindPreference(path)) {
496 NOTREACHED() << "Tried to register duplicate pref " << path;
initial.commit09911bf2008-07-26 23:55:29497 return;
498 }
[email protected]c3b54f372010-09-14 08:25:07499
[email protected]99cc9a02010-09-17 07:53:28500 Value::ValueType orig_type = default_value->GetType();
501 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) <<
502 "invalid preference type: " << orig_type;
503
[email protected]9a8c4022011-01-25 14:25:33504 // Hand off ownership.
505 default_store_->SetDefaultValue(path, scoped_value.release());
initial.commit09911bf2008-07-26 23:55:29506}
507
[email protected]57ecc4b2010-08-11 03:02:51508void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29509 DCHECK(CalledOnValidThread());
510
511 const Preference* pref = FindPreference(path);
512 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40513 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29514 return;
515 }
[email protected]f2d1f612010-12-09 15:10:17516 user_pref_store_->RemoveValue(path);
initial.commit09911bf2008-07-26 23:55:29517}
518
[email protected]57ecc4b2010-08-11 03:02:51519void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39520 DCHECK(CalledOnValidThread());
521
522 const Preference* pref = FindPreference(path);
523 if (!pref) {
524 NOTREACHED() << "Trying to write an unregistered pref: " << path;
525 return;
526 }
[email protected]ecde2742010-04-02 17:36:18527
[email protected]9a8c4022011-01-25 14:25:33528 if (pref->GetType() != value.GetType()) {
[email protected]99cc9a02010-09-17 07:53:28529 NOTREACHED() << "Trying to set pref " << path
530 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07531 << " to value of type " << value.GetType();
532 } else {
[email protected]f2d1f612010-12-09 15:10:17533 user_pref_store_->SetValue(path, value.DeepCopy());
[email protected]ecde2742010-04-02 17:36:18534 }
[email protected]a048d7e42009-12-01 01:02:39535}
536
[email protected]57ecc4b2010-08-11 03:02:51537void PrefService::SetBoolean(const char* path, bool value) {
[email protected]c3b54f372010-09-14 08:25:07538 SetUserPrefValue(path, Value::CreateBooleanValue(value));
initial.commit09911bf2008-07-26 23:55:29539}
540
[email protected]57ecc4b2010-08-11 03:02:51541void PrefService::SetInteger(const char* path, int value) {
[email protected]c3b54f372010-09-14 08:25:07542 SetUserPrefValue(path, Value::CreateIntegerValue(value));
initial.commit09911bf2008-07-26 23:55:29543}
544
[email protected]fb534c92011-02-01 01:02:07545void PrefService::SetDouble(const char* path, double value) {
546 SetUserPrefValue(path, Value::CreateDoubleValue(value));
initial.commit09911bf2008-07-26 23:55:29547}
548
[email protected]57ecc4b2010-08-11 03:02:51549void PrefService::SetString(const char* path, const std::string& value) {
[email protected]c3b54f372010-09-14 08:25:07550 SetUserPrefValue(path, Value::CreateStringValue(value));
initial.commit09911bf2008-07-26 23:55:29551}
552
[email protected]57ecc4b2010-08-11 03:02:51553void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]8703b2b2011-03-15 09:51:50554 SetUserPrefValue(path, base::CreateFilePathValue(value));
[email protected]b9636002009-03-04 00:05:25555}
556
[email protected]419a0572011-04-18 22:21:46557void PrefService::SetList(const char* path, ListValue* value) {
558 SetUserPrefValue(path, value);
559}
560
[email protected]57ecc4b2010-08-11 03:02:51561void PrefService::SetInt64(const char* path, int64 value) {
[email protected]c3b54f372010-09-14 08:25:07562 SetUserPrefValue(path, Value::CreateStringValue(base::Int64ToString(value)));
[email protected]0bb1a622009-03-04 03:22:32563}
564
[email protected]57ecc4b2010-08-11 03:02:51565int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32566 DCHECK(CalledOnValidThread());
567
[email protected]0bb1a622009-03-04 03:22:32568 const Preference* pref = FindPreference(path);
569 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40570 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08571 return 0;
[email protected]0bb1a622009-03-04 03:22:32572 }
[email protected]dc9a6762010-08-16 07:13:53573 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32574 bool rv = pref->GetValue()->GetAsString(&result);
575 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25576
577 int64 val;
[email protected]dc9a6762010-08-16 07:13:53578 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25579 return val;
[email protected]0bb1a622009-03-04 03:22:32580}
581
[email protected]57ecc4b2010-08-11 03:02:51582void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]c3b54f372010-09-14 08:25:07583 RegisterPreference(
584 path, Value::CreateStringValue(base::Int64ToString(default_value)));
[email protected]0bb1a622009-03-04 03:22:32585}
586
[email protected]26418b72011-03-30 14:07:39587Value* PrefService::GetMutableUserPref(const char* path,
588 Value::ValueType type) {
589 CHECK(type == Value::TYPE_DICTIONARY || type == Value::TYPE_LIST);
initial.commit09911bf2008-07-26 23:55:29590 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11591 DLOG_IF(WARNING, IsManagedPreference(path)) <<
592 "Attempt to change managed preference " << path;
initial.commit09911bf2008-07-26 23:55:29593
594 const Preference* pref = FindPreference(path);
595 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40596 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29597 return NULL;
598 }
[email protected]26418b72011-03-30 14:07:39599 if (pref->GetType() != type) {
600 NOTREACHED() << "Wrong type for GetMutableValue: " << path;
initial.commit09911bf2008-07-26 23:55:29601 return NULL;
602 }
603
[email protected]e0250892010-10-01 18:57:53604 // Look for an existing preference in the user store. If it doesn't
605 // exist or isn't the correct type, create a new user preference.
[email protected]26418b72011-03-30 14:07:39606 Value* value = NULL;
607 if (user_pref_store_->GetMutableValue(path, &value)
[email protected]f2d1f612010-12-09 15:10:17608 != PersistentPrefStore::READ_OK ||
[email protected]26418b72011-03-30 14:07:39609 !value->IsType(type)) {
610 if (type == Value::TYPE_DICTIONARY) {
611 value = new DictionaryValue;
612 } else if (type == Value::TYPE_LIST) {
613 value = new ListValue;
614 } else {
615 NOTREACHED();
616 }
617 user_pref_store_->SetValueSilently(path, value);
initial.commit09911bf2008-07-26 23:55:29618 }
[email protected]26418b72011-03-30 14:07:39619 return value;
620}
621
[email protected]68bf41a2011-03-25 16:38:31622void PrefService::ReportUserPrefChanged(const std::string& key) {
[email protected]f89ee342011-03-07 09:28:27623 user_pref_store_->ReportValueChanged(key);
624}
625
[email protected]c3b54f372010-09-14 08:25:07626void PrefService::SetUserPrefValue(const char* path, Value* new_value) {
627 DCHECK(CalledOnValidThread());
[email protected]d166fcb2011-02-09 18:04:11628 DLOG_IF(WARNING, IsManagedPreference(path)) <<
629 "Attempt to change managed preference " << path;
[email protected]c3b54f372010-09-14 08:25:07630
631 const Preference* pref = FindPreference(path);
632 if (!pref) {
633 NOTREACHED() << "Trying to write an unregistered pref: " << path;
634 return;
635 }
[email protected]99cc9a02010-09-17 07:53:28636 if (pref->GetType() != new_value->GetType()) {
637 NOTREACHED() << "Trying to set pref " << path
638 << " of type " << pref->GetType()
[email protected]c3b54f372010-09-14 08:25:07639 << " to value of type " << new_value->GetType();
640 return;
641 }
642
[email protected]f2d1f612010-12-09 15:10:17643 user_pref_store_->SetValue(path, new_value);
[email protected]73c47932010-12-06 18:13:43644}
645
initial.commit09911bf2008-07-26 23:55:29646///////////////////////////////////////////////////////////////////////////////
647// PrefService::Preference
648
[email protected]c3b54f372010-09-14 08:25:07649PrefService::Preference::Preference(const PrefService* service,
[email protected]9a8c4022011-01-25 14:25:33650 const char* name,
651 Value::ValueType type)
[email protected]99cc9a02010-09-17 07:53:28652 : name_(name),
[email protected]9a8c4022011-01-25 14:25:33653 type_(type),
[email protected]c3b54f372010-09-14 08:25:07654 pref_service_(service) {
initial.commit09911bf2008-07-26 23:55:29655 DCHECK(name);
[email protected]c3b54f372010-09-14 08:25:07656 DCHECK(service);
[email protected]99cc9a02010-09-17 07:53:28657}
658
659Value::ValueType PrefService::Preference::GetType() const {
[email protected]9a8c4022011-01-25 14:25:33660 return type_;
initial.commit09911bf2008-07-26 23:55:29661}
662
663const Value* PrefService::Preference::GetValue() const {
[email protected]c3b54f372010-09-14 08:25:07664 DCHECK(pref_service_->FindPreference(name_.c_str())) <<
initial.commit09911bf2008-07-26 23:55:29665 "Must register pref before getting its value";
666
[email protected]68bf41a2011-03-25 16:38:31667 const Value* found_value = NULL;
[email protected]887288f02011-02-04 22:52:46668 if (pref_value_store()->GetValue(name_, type_, &found_value)) {
[email protected]9a8c4022011-01-25 14:25:33669 DCHECK(found_value->IsType(type_));
[email protected]99cc9a02010-09-17 07:53:28670 return found_value;
[email protected]9a8c4022011-01-25 14:25:33671 }
initial.commit09911bf2008-07-26 23:55:29672
[email protected]c3b54f372010-09-14 08:25:07673 // Every registered preference has at least a default value.
[email protected]99cc9a02010-09-17 07:53:28674 NOTREACHED() << "no valid value found for registered pref " << name_;
[email protected]c3b54f372010-09-14 08:25:07675 return NULL;
[email protected]40a47c162010-09-09 11:14:01676}
677
678bool PrefService::Preference::IsManaged() const {
[email protected]887288f02011-02-04 22:52:46679 return pref_value_store()->PrefValueInManagedStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01680}
681
682bool PrefService::Preference::HasExtensionSetting() const {
[email protected]887288f02011-02-04 22:52:46683 return pref_value_store()->PrefValueInExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01684}
685
686bool PrefService::Preference::HasUserSetting() const {
[email protected]887288f02011-02-04 22:52:46687 return pref_value_store()->PrefValueInUserStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01688}
689
690bool PrefService::Preference::IsExtensionControlled() const {
[email protected]887288f02011-02-04 22:52:46691 return pref_value_store()->PrefValueFromExtensionStore(name_.c_str());
[email protected]40a47c162010-09-09 11:14:01692}
693
694bool PrefService::Preference::IsUserControlled() const {
[email protected]887288f02011-02-04 22:52:46695 return pref_value_store()->PrefValueFromUserStore(name_.c_str());
[email protected]c3b54f372010-09-14 08:25:07696}
697
698bool PrefService::Preference::IsDefaultValue() const {
[email protected]887288f02011-02-04 22:52:46699 return pref_value_store()->PrefValueFromDefaultStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35700}
[email protected]74379bc52010-07-21 13:54:08701
702bool PrefService::Preference::IsUserModifiable() const {
[email protected]887288f02011-02-04 22:52:46703 return pref_value_store()->PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08704}
[email protected]9a28f132011-02-24 21:15:16705
706bool PrefService::Preference::IsExtensionModifiable() const {
707 return pref_value_store()->PrefValueExtensionModifiable(name_.c_str());
708}