blob: 1ab671a3d386b636274e8978c61c6ee67b5299d9 [file] [log] [blame]
[email protected]c0858b02010-05-12 15:03:321// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]37858e52010-08-26 00:22:025#include "chrome/browser/prefs/pref_service.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]1cb92b82010-03-08 23:12:157#include <algorithm>
8#include <string>
9
[email protected]a92b8642009-05-05 23:38:5610#include "app/l10n_util.h"
[email protected]aa4dc5e22010-06-16 11:32:5411#include "base/command_line.h"
[email protected]c02c853d72010-08-07 06:23:2412#include "base/file_path.h"
[email protected]1d01d412010-08-20 00:36:0113#include "base/file_util.h"
[email protected]ba399672010-04-06 15:42:3914#include "base/histogram.h"
initial.commit09911bf2008-07-26 23:55:2915#include "base/logging.h"
16#include "base/message_loop.h"
[email protected]807204142009-05-05 03:31:4417#include "base/stl_util-inl.h"
[email protected]e83326f2010-07-31 17:29:2518#include "base/string_number_conversions.h"
initial.commit09911bf2008-07-26 23:55:2919#include "base/string_util.h"
[email protected]66de4f092009-09-04 23:59:4020#include "base/sys_string_conversions.h"
[email protected]1cb92b82010-03-08 23:12:1521#include "base/utf_string_conversions.h"
[email protected]66de4f092009-09-04 23:59:4022#include "build/build_config.h"
[email protected]ba399672010-04-06 15:42:3923#include "chrome/browser/chrome_thread.h"
[email protected]fa26b3d52010-08-06 08:51:5024#include "chrome/browser/profile.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/notification_service.h"
[email protected]ba399672010-04-06 15:42:3926#include "grit/chromium_strings.h"
[email protected]34ac8f32009-02-22 23:03:2727#include "grit/generated_resources.h"
initial.commit09911bf2008-07-26 23:55:2928
29namespace {
30
initial.commit09911bf2008-07-26 23:55:2931// A helper function for RegisterLocalized*Pref that creates a Value* based on
32// the string value in the locale dll. Because we control the values in a
33// locale dll, this should always return a Value of the appropriate type.
34Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) {
[email protected]16b527162010-08-15 18:37:1035 std::string resource_string = l10n_util::GetStringUTF8(message_id);
initial.commit09911bf2008-07-26 23:55:2936 DCHECK(!resource_string.empty());
37 switch (type) {
38 case Value::TYPE_BOOLEAN: {
[email protected]16b527162010-08-15 18:37:1039 if ("true" == resource_string)
initial.commit09911bf2008-07-26 23:55:2940 return Value::CreateBooleanValue(true);
[email protected]16b527162010-08-15 18:37:1041 if ("false" == resource_string)
initial.commit09911bf2008-07-26 23:55:2942 return Value::CreateBooleanValue(false);
43 break;
44 }
45
46 case Value::TYPE_INTEGER: {
[email protected]e83326f2010-07-31 17:29:2547 int val;
[email protected]16b527162010-08-15 18:37:1048 base::StringToInt(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2549 return Value::CreateIntegerValue(val);
initial.commit09911bf2008-07-26 23:55:2950 }
51
52 case Value::TYPE_REAL: {
[email protected]e83326f2010-07-31 17:29:2553 double val;
[email protected]16b527162010-08-15 18:37:1054 base::StringToDouble(resource_string, &val);
[email protected]e83326f2010-07-31 17:29:2555 return Value::CreateRealValue(val);
initial.commit09911bf2008-07-26 23:55:2956 }
57
58 case Value::TYPE_STRING: {
59 return Value::CreateStringValue(resource_string);
initial.commit09911bf2008-07-26 23:55:2960 }
61
62 default: {
[email protected]b154e6f2009-03-06 01:52:4063 NOTREACHED() <<
[email protected]40a47c162010-09-09 11:14:0164 "list and dictionary types can not have default locale values";
initial.commit09911bf2008-07-26 23:55:2965 }
66 }
67 NOTREACHED();
68 return Value::CreateNullValue();
69}
70
[email protected]ba399672010-04-06 15:42:3971// Forwards a notification after a PostMessage so that we can wait for the
72// MessageLoop to run.
73void NotifyReadError(PrefService* pref, int message_id) {
74 Source<PrefService> source(pref);
75 NotificationService::current()->Notify(NotificationType::PROFILE_ERROR,
76 source, Details<int>(&message_id));
77}
78
initial.commit09911bf2008-07-26 23:55:2979} // namespace
80
[email protected]db198b22010-07-12 16:48:4981// static
[email protected]a9c23a52010-08-04 09:13:4482PrefService* PrefService::CreatePrefService(const FilePath& pref_filename,
83 Profile* profile) {
[email protected]1d01d412010-08-20 00:36:0184#if defined(OS_LINUX)
85 // We'd like to see what fraction of our users have the preferences
86 // stored on a network file system, as we've had no end of troubles
87 // with NFS/AFS.
88 // TODO(evanm): remove this once we've collected state.
89 file_util::FileSystemType fstype;
90 if (file_util::GetFileSystemType(pref_filename.DirName(), &fstype)) {
91 UMA_HISTOGRAM_ENUMERATION("PrefService.FileSystemType",
92 static_cast<int>(fstype),
93 file_util::FILE_SYSTEM_TYPE_COUNT);
94 }
95#endif
96
[email protected]fa26b3d52010-08-06 08:51:5097 return new PrefService(
98 PrefValueStore::CreatePrefValueStore(pref_filename, profile, false));
[email protected]db198b22010-07-12 16:48:4999}
100
101// static
[email protected]fa26b3d52010-08-06 08:51:50102PrefService* PrefService::CreateUserPrefService(const FilePath& pref_filename) {
103 return new PrefService(
104 PrefValueStore::CreatePrefValueStore(pref_filename, NULL, true));
[email protected]d8b08c92010-06-07 13:13:28105}
106
107PrefService::PrefService(PrefValueStore* pref_value_store)
108 : pref_value_store_(pref_value_store) {
[email protected]d81288a02010-08-18 07:25:50109 pref_notifier_.reset(new PrefNotifier(this, pref_value_store));
[email protected]277404c22010-04-22 13:09:45110 InitFromStorage();
initial.commit09911bf2008-07-26 23:55:29111}
112
113PrefService::~PrefService() {
114 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29115 STLDeleteContainerPointers(prefs_.begin(), prefs_.end());
116 prefs_.clear();
initial.commit09911bf2008-07-26 23:55:29117}
118
[email protected]277404c22010-04-22 13:09:45119void PrefService::InitFromStorage() {
120 PrefStore::PrefReadError error = LoadPersistentPrefs();
121 if (error == PrefStore::PREF_READ_ERROR_NONE)
[email protected]ba399672010-04-06 15:42:39122 return;
initial.commit09911bf2008-07-26 23:55:29123
[email protected]ba399672010-04-06 15:42:39124 // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
125 // an example problem that this can cause.
126 // Do some diagnosis and try to avoid losing data.
127 int message_id = 0;
[email protected]277404c22010-04-22 13:09:45128 if (error <= PrefStore::PREF_READ_ERROR_JSON_TYPE) {
[email protected]ba399672010-04-06 15:42:39129 message_id = IDS_PREFERENCES_CORRUPT_ERROR;
[email protected]277404c22010-04-22 13:09:45130 } else if (error != PrefStore::PREF_READ_ERROR_NO_FILE) {
[email protected]ba399672010-04-06 15:42:39131 message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
132 }
133
134 if (message_id) {
135 ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
136 NewRunnableFunction(&NotifyReadError, this, message_id));
137 }
138 UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error, 20);
139}
140
141bool PrefService::ReloadPersistentPrefs() {
[email protected]277404c22010-04-22 13:09:45142 return (LoadPersistentPrefs() == PrefStore::PREF_READ_ERROR_NONE);
[email protected]ba399672010-04-06 15:42:39143}
144
[email protected]277404c22010-04-22 13:09:45145PrefStore::PrefReadError PrefService::LoadPersistentPrefs() {
[email protected]ba399672010-04-06 15:42:39146 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39147
[email protected]d8b08c92010-06-07 13:13:28148 PrefStore::PrefReadError pref_error = pref_value_store_->ReadPrefs();
[email protected]7aa0a962010-04-21 17:24:42149
[email protected]7aa0a962010-04-21 17:24:42150 for (PreferenceSet::iterator it = prefs_.begin();
151 it != prefs_.end(); ++it) {
[email protected]40a47c162010-09-09 11:14:01152 (*it)->pref_value_store_ = pref_value_store_.get();
[email protected]7aa0a962010-04-21 17:24:42153 }
154
[email protected]277404c22010-04-22 13:09:45155 return pref_error;
initial.commit09911bf2008-07-26 23:55:29156}
157
[email protected]6faa0e0d2009-04-28 06:50:36158bool PrefService::SavePersistentPrefs() {
159 DCHECK(CalledOnValidThread());
initial.commit09911bf2008-07-26 23:55:29160
[email protected]d8b08c92010-06-07 13:13:28161 return pref_value_store_->WritePrefs();
[email protected]6faa0e0d2009-04-28 06:50:36162}
163
[email protected]6c1164042009-05-08 14:41:08164void PrefService::ScheduleSavePersistentPrefs() {
[email protected]6faa0e0d2009-04-28 06:50:36165 DCHECK(CalledOnValidThread());
[email protected]ba399672010-04-06 15:42:39166
[email protected]d8b08c92010-06-07 13:13:28167 pref_value_store_->ScheduleWritePrefs();
initial.commit09911bf2008-07-26 23:55:29168}
169
[email protected]57ecc4b2010-08-11 03:02:51170void PrefService::RegisterBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29171 bool default_value) {
[email protected]40a47c162010-09-09 11:14:01172 Preference* pref = new Preference(pref_value_store_.get(), path,
173 Value::CreateBooleanValue(default_value));
174 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29175}
176
[email protected]57ecc4b2010-08-11 03:02:51177void PrefService::RegisterIntegerPref(const char* path, int default_value) {
[email protected]40a47c162010-09-09 11:14:01178 Preference* pref = new Preference(pref_value_store_.get(), path,
179 Value::CreateIntegerValue(default_value));
180 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29181}
182
[email protected]57ecc4b2010-08-11 03:02:51183void PrefService::RegisterRealPref(const char* path, double default_value) {
[email protected]40a47c162010-09-09 11:14:01184 Preference* pref = new Preference(pref_value_store_.get(), path,
185 Value::CreateRealValue(default_value));
186 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29187}
188
[email protected]57ecc4b2010-08-11 03:02:51189void PrefService::RegisterStringPref(const char* path,
[email protected]20ce516d2010-06-18 02:20:04190 const std::string& default_value) {
[email protected]40a47c162010-09-09 11:14:01191 Preference* pref = new Preference(pref_value_store_.get(), path,
192 Value::CreateStringValue(default_value));
193 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29194}
195
[email protected]57ecc4b2010-08-11 03:02:51196void PrefService::RegisterFilePathPref(const char* path,
[email protected]b9636002009-03-04 00:05:25197 const FilePath& default_value) {
[email protected]40a47c162010-09-09 11:14:01198 Preference* pref = new Preference(pref_value_store_.get(), path,
199 Value::CreateStringValue(default_value.value()));
200 RegisterPreference(pref);
[email protected]b9636002009-03-04 00:05:25201}
202
[email protected]57ecc4b2010-08-11 03:02:51203void PrefService::RegisterListPref(const char* path) {
[email protected]40a47c162010-09-09 11:14:01204 Preference* pref = new Preference(pref_value_store_.get(), path,
205 new ListValue);
206 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29207}
208
[email protected]57ecc4b2010-08-11 03:02:51209void PrefService::RegisterDictionaryPref(const char* path) {
[email protected]40a47c162010-09-09 11:14:01210 Preference* pref = new Preference(pref_value_store_.get(), path,
211 new DictionaryValue());
212 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29213}
214
[email protected]57ecc4b2010-08-11 03:02:51215void PrefService::RegisterLocalizedBooleanPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29216 int locale_default_message_id) {
[email protected]40a47c162010-09-09 11:14:01217 Preference* pref = new Preference(pref_value_store_.get(), path,
initial.commit09911bf2008-07-26 23:55:29218 CreateLocaleDefaultValue(Value::TYPE_BOOLEAN, locale_default_message_id));
[email protected]40a47c162010-09-09 11:14:01219 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29220}
221
[email protected]57ecc4b2010-08-11 03:02:51222void PrefService::RegisterLocalizedIntegerPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29223 int locale_default_message_id) {
[email protected]40a47c162010-09-09 11:14:01224 Preference* pref = new Preference(pref_value_store_.get(), path,
initial.commit09911bf2008-07-26 23:55:29225 CreateLocaleDefaultValue(Value::TYPE_INTEGER, locale_default_message_id));
[email protected]40a47c162010-09-09 11:14:01226 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29227}
228
[email protected]57ecc4b2010-08-11 03:02:51229void PrefService::RegisterLocalizedRealPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29230 int locale_default_message_id) {
[email protected]40a47c162010-09-09 11:14:01231 Preference* pref = new Preference(pref_value_store_.get(), path,
initial.commit09911bf2008-07-26 23:55:29232 CreateLocaleDefaultValue(Value::TYPE_REAL, locale_default_message_id));
[email protected]40a47c162010-09-09 11:14:01233 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29234}
235
[email protected]57ecc4b2010-08-11 03:02:51236void PrefService::RegisterLocalizedStringPref(const char* path,
initial.commit09911bf2008-07-26 23:55:29237 int locale_default_message_id) {
[email protected]40a47c162010-09-09 11:14:01238 Preference* pref = new Preference(pref_value_store_.get(), path,
initial.commit09911bf2008-07-26 23:55:29239 CreateLocaleDefaultValue(Value::TYPE_STRING, locale_default_message_id));
[email protected]40a47c162010-09-09 11:14:01240 RegisterPreference(pref);
initial.commit09911bf2008-07-26 23:55:29241}
242
[email protected]57ecc4b2010-08-11 03:02:51243bool PrefService::GetBoolean(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29244 DCHECK(CalledOnValidThread());
245
246 bool result = false;
initial.commit09911bf2008-07-26 23:55:29247
248 const Preference* pref = FindPreference(path);
249 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40250 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29251 return result;
252 }
253 bool rv = pref->GetValue()->GetAsBoolean(&result);
254 DCHECK(rv);
255 return result;
256}
257
[email protected]57ecc4b2010-08-11 03:02:51258int PrefService::GetInteger(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29259 DCHECK(CalledOnValidThread());
260
261 int result = 0;
initial.commit09911bf2008-07-26 23:55:29262
263 const Preference* pref = FindPreference(path);
264 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40265 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29266 return result;
267 }
268 bool rv = pref->GetValue()->GetAsInteger(&result);
269 DCHECK(rv);
270 return result;
271}
272
[email protected]57ecc4b2010-08-11 03:02:51273double PrefService::GetReal(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29274 DCHECK(CalledOnValidThread());
275
276 double result = 0.0;
initial.commit09911bf2008-07-26 23:55:29277
278 const Preference* pref = FindPreference(path);
279 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40280 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29281 return result;
282 }
283 bool rv = pref->GetValue()->GetAsReal(&result);
284 DCHECK(rv);
285 return result;
286}
287
[email protected]57ecc4b2010-08-11 03:02:51288std::string PrefService::GetString(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29289 DCHECK(CalledOnValidThread());
290
[email protected]ddd231e2010-06-29 20:35:19291 std::string result;
[email protected]8e50b602009-03-03 22:59:43292
initial.commit09911bf2008-07-26 23:55:29293 const Preference* pref = FindPreference(path);
294 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40295 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29296 return result;
297 }
298 bool rv = pref->GetValue()->GetAsString(&result);
299 DCHECK(rv);
300 return result;
301}
302
[email protected]57ecc4b2010-08-11 03:02:51303FilePath PrefService::GetFilePath(const char* path) const {
[email protected]b9636002009-03-04 00:05:25304 DCHECK(CalledOnValidThread());
305
306 FilePath::StringType result;
[email protected]b9636002009-03-04 00:05:25307
308 const Preference* pref = FindPreference(path);
309 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40310 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25311 return FilePath(result);
312 }
313 bool rv = pref->GetValue()->GetAsString(&result);
314 DCHECK(rv);
[email protected]66de4f092009-09-04 23:59:40315#if defined(OS_POSIX)
316 // We store filepaths as UTF8, so convert it back to the system type.
317 result = base::SysWideToNativeMB(UTF8ToWide(result));
318#endif
[email protected]b9636002009-03-04 00:05:25319 return FilePath(result);
320}
321
[email protected]57ecc4b2010-08-11 03:02:51322bool PrefService::HasPrefPath(const char* path) const {
[email protected]d8b08c92010-06-07 13:13:28323 return pref_value_store_->HasPrefPath(path);
initial.commit09911bf2008-07-26 23:55:29324}
325
326const PrefService::Preference* PrefService::FindPreference(
[email protected]57ecc4b2010-08-11 03:02:51327 const char* pref_name) const {
initial.commit09911bf2008-07-26 23:55:29328 DCHECK(CalledOnValidThread());
[email protected]40a47c162010-09-09 11:14:01329 Preference p(NULL, pref_name, NULL);
initial.commit09911bf2008-07-26 23:55:29330 PreferenceSet::const_iterator it = prefs_.find(&p);
331 return it == prefs_.end() ? NULL : *it;
332}
333
[email protected]57ecc4b2010-08-11 03:02:51334bool PrefService::IsManagedPreference(const char* pref_name) const {
[email protected]d90de1c02010-07-19 19:50:48335 const Preference* pref = FindPreference(pref_name);
336 if (pref && pref->IsManaged()) {
337 return true;
338 }
339 return false;
340}
341
[email protected]57ecc4b2010-08-11 03:02:51342const DictionaryValue* PrefService::GetDictionary(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29343 DCHECK(CalledOnValidThread());
344
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 NULL;
349 }
350 const Value* value = pref->GetValue();
351 if (value->GetType() == Value::TYPE_NULL)
352 return NULL;
353 return static_cast<const DictionaryValue*>(value);
354}
355
[email protected]57ecc4b2010-08-11 03:02:51356const ListValue* PrefService::GetList(const char* path) const {
initial.commit09911bf2008-07-26 23:55:29357 DCHECK(CalledOnValidThread());
358
initial.commit09911bf2008-07-26 23:55:29359 const Preference* pref = FindPreference(path);
360 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40361 NOTREACHED() << "Trying to read an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29362 return NULL;
363 }
364 const Value* value = pref->GetValue();
365 if (value->GetType() == Value::TYPE_NULL)
366 return NULL;
367 return static_cast<const ListValue*>(value);
368}
369
[email protected]57ecc4b2010-08-11 03:02:51370void PrefService::AddPrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29371 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50372 pref_notifier_->AddPrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29373}
374
[email protected]57ecc4b2010-08-11 03:02:51375void PrefService::RemovePrefObserver(const char* path,
initial.commit09911bf2008-07-26 23:55:29376 NotificationObserver* obs) {
[email protected]d81288a02010-08-18 07:25:50377 pref_notifier_->RemovePrefObserver(path, obs);
initial.commit09911bf2008-07-26 23:55:29378}
379
[email protected]40a47c162010-09-09 11:14:01380void PrefService::RegisterPreference(Preference* pref) {
initial.commit09911bf2008-07-26 23:55:29381 DCHECK(CalledOnValidThread());
382
[email protected]40a47c162010-09-09 11:14:01383 if (FindPreference(pref->name().c_str())) {
384 NOTREACHED() << "Tried to register duplicate pref " << pref->name();
385 delete pref;
initial.commit09911bf2008-07-26 23:55:29386 return;
387 }
[email protected]40a47c162010-09-09 11:14:01388 prefs_.insert(pref);
initial.commit09911bf2008-07-26 23:55:29389}
390
[email protected]57ecc4b2010-08-11 03:02:51391void PrefService::ClearPref(const char* path) {
initial.commit09911bf2008-07-26 23:55:29392 DCHECK(CalledOnValidThread());
393
394 const Preference* pref = FindPreference(path);
395 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40396 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29397 return;
398 }
initial.commit09911bf2008-07-26 23:55:29399 Value* value;
[email protected]d8b08c92010-06-07 13:13:28400 bool has_old_value = pref_value_store_->GetValue(path, &value);
401 pref_value_store_->RemoveUserPrefValue(path);
initial.commit09911bf2008-07-26 23:55:29402
[email protected]d81288a02010-08-18 07:25:50403 // TODO(pamg): Removing the user value when there's a higher-priority setting
404 // doesn't change the value and shouldn't fire observers.
initial.commit09911bf2008-07-26 23:55:29405 if (has_old_value)
[email protected]d81288a02010-08-18 07:25:50406 pref_notifier_->FireObservers(path);
initial.commit09911bf2008-07-26 23:55:29407}
408
[email protected]57ecc4b2010-08-11 03:02:51409void PrefService::Set(const char* path, const Value& value) {
[email protected]a048d7e42009-12-01 01:02:39410 DCHECK(CalledOnValidThread());
411
412 const Preference* pref = FindPreference(path);
413 if (!pref) {
414 NOTREACHED() << "Trying to write an unregistered pref: " << path;
415 return;
416 }
[email protected]ecde2742010-04-02 17:36:18417
418 // Allow dictionary and list types to be set to null.
419 if (value.GetType() == Value::TYPE_NULL &&
420 (pref->type() == Value::TYPE_DICTIONARY ||
421 pref->type() == Value::TYPE_LIST)) {
422 scoped_ptr<Value> old_value(GetPrefCopy(path));
423 if (!old_value->Equals(&value)) {
[email protected]d8b08c92010-06-07 13:13:28424 pref_value_store_->RemoveUserPrefValue(path);
[email protected]d81288a02010-08-18 07:25:50425 pref_notifier_->FireObservers(path);
[email protected]ecde2742010-04-02 17:36:18426 }
427 return;
428 }
429
[email protected]a048d7e42009-12-01 01:02:39430 if (pref->type() != value.GetType()) {
431 NOTREACHED() << "Wrong type for Set: " << path;
432 }
433
434 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]d8b08c92010-06-07 13:13:28435 pref_value_store_->SetUserPrefValue(path, value.DeepCopy());
[email protected]a048d7e42009-12-01 01:02:39436
[email protected]d81288a02010-08-18 07:25:50437 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
[email protected]a048d7e42009-12-01 01:02:39438}
439
[email protected]57ecc4b2010-08-11 03:02:51440void PrefService::SetBoolean(const char* path, bool value) {
initial.commit09911bf2008-07-26 23:55:29441 DCHECK(CalledOnValidThread());
442
443 const Preference* pref = FindPreference(path);
444 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40445 NOTREACHED() << "Trying to write an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29446 return;
447 }
[email protected]91ae7e32010-04-23 12:58:50448 if (pref->IsManaged()) {
449 NOTREACHED() << "Preference is managed: " << path;
450 return;
451 }
initial.commit09911bf2008-07-26 23:55:29452 if (pref->type() != Value::TYPE_BOOLEAN) {
[email protected]b154e6f2009-03-06 01:52:40453 NOTREACHED() << "Wrong type for SetBoolean: " << path;
initial.commit09911bf2008-07-26 23:55:29454 return;
455 }
456
457 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]d8b08c92010-06-07 13:13:28458 Value* new_value = Value::CreateBooleanValue(value);
459 pref_value_store_->SetUserPrefValue(path, new_value);
initial.commit09911bf2008-07-26 23:55:29460
[email protected]d81288a02010-08-18 07:25:50461 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
initial.commit09911bf2008-07-26 23:55:29462}
463
[email protected]57ecc4b2010-08-11 03:02:51464void PrefService::SetInteger(const char* path, int value) {
initial.commit09911bf2008-07-26 23:55:29465 DCHECK(CalledOnValidThread());
466
467 const Preference* pref = FindPreference(path);
468 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40469 NOTREACHED() << "Trying to write an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29470 return;
471 }
[email protected]91ae7e32010-04-23 12:58:50472 if (pref->IsManaged()) {
473 NOTREACHED() << "Preference is managed: " << path;
474 return;
475 }
initial.commit09911bf2008-07-26 23:55:29476 if (pref->type() != Value::TYPE_INTEGER) {
[email protected]b154e6f2009-03-06 01:52:40477 NOTREACHED() << "Wrong type for SetInteger: " << path;
initial.commit09911bf2008-07-26 23:55:29478 return;
479 }
480
481 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]d8b08c92010-06-07 13:13:28482 Value* new_value = Value::CreateIntegerValue(value);
483 pref_value_store_->SetUserPrefValue(path, new_value);
initial.commit09911bf2008-07-26 23:55:29484
[email protected]d81288a02010-08-18 07:25:50485 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
initial.commit09911bf2008-07-26 23:55:29486}
487
[email protected]57ecc4b2010-08-11 03:02:51488void PrefService::SetReal(const char* path, double value) {
initial.commit09911bf2008-07-26 23:55:29489 DCHECK(CalledOnValidThread());
490
491 const Preference* pref = FindPreference(path);
492 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40493 NOTREACHED() << "Trying to write an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29494 return;
495 }
[email protected]91ae7e32010-04-23 12:58:50496 if (pref->IsManaged()) {
497 NOTREACHED() << "Preference is managed: " << path;
498 return;
499 }
initial.commit09911bf2008-07-26 23:55:29500 if (pref->type() != Value::TYPE_REAL) {
[email protected]b154e6f2009-03-06 01:52:40501 NOTREACHED() << "Wrong type for SetReal: " << path;
initial.commit09911bf2008-07-26 23:55:29502 return;
503 }
504
505 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]d8b08c92010-06-07 13:13:28506 Value* new_value = Value::CreateRealValue(value);
507 pref_value_store_->SetUserPrefValue(path, new_value);
initial.commit09911bf2008-07-26 23:55:29508
[email protected]d81288a02010-08-18 07:25:50509 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
initial.commit09911bf2008-07-26 23:55:29510}
511
[email protected]57ecc4b2010-08-11 03:02:51512void PrefService::SetString(const char* path, const std::string& value) {
initial.commit09911bf2008-07-26 23:55:29513 DCHECK(CalledOnValidThread());
514
515 const Preference* pref = FindPreference(path);
516 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40517 NOTREACHED() << "Trying to write an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29518 return;
519 }
[email protected]91ae7e32010-04-23 12:58:50520 if (pref->IsManaged()) {
521 NOTREACHED() << "Preference is managed: " << path;
522 return;
523 }
initial.commit09911bf2008-07-26 23:55:29524 if (pref->type() != Value::TYPE_STRING) {
[email protected]b154e6f2009-03-06 01:52:40525 NOTREACHED() << "Wrong type for SetString: " << path;
initial.commit09911bf2008-07-26 23:55:29526 return;
527 }
528
529 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]d8b08c92010-06-07 13:13:28530 Value* new_value = Value::CreateStringValue(value);
531 pref_value_store_->SetUserPrefValue(path, new_value);
initial.commit09911bf2008-07-26 23:55:29532
[email protected]d81288a02010-08-18 07:25:50533 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
initial.commit09911bf2008-07-26 23:55:29534}
535
[email protected]57ecc4b2010-08-11 03:02:51536void PrefService::SetFilePath(const char* path, const FilePath& value) {
[email protected]b9636002009-03-04 00:05:25537 DCHECK(CalledOnValidThread());
538
539 const Preference* pref = FindPreference(path);
540 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40541 NOTREACHED() << "Trying to write an unregistered pref: " << path;
[email protected]b9636002009-03-04 00:05:25542 return;
543 }
[email protected]91ae7e32010-04-23 12:58:50544 if (pref->IsManaged()) {
545 NOTREACHED() << "Preference is managed: " << path;
546 return;
547 }
[email protected]b9636002009-03-04 00:05:25548 if (pref->type() != Value::TYPE_STRING) {
[email protected]b154e6f2009-03-06 01:52:40549 NOTREACHED() << "Wrong type for SetFilePath: " << path;
[email protected]b9636002009-03-04 00:05:25550 return;
551 }
552
553 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]66de4f092009-09-04 23:59:40554#if defined(OS_POSIX)
555 // Value::SetString only knows about UTF8 strings, so convert the path from
556 // the system native value to UTF8.
557 std::string path_utf8 = WideToUTF8(base::SysNativeMBToWide(value.value()));
[email protected]d8b08c92010-06-07 13:13:28558 Value* new_value = Value::CreateStringValue(path_utf8);
559 pref_value_store_->SetUserPrefValue(path, new_value);
[email protected]66de4f092009-09-04 23:59:40560#else
[email protected]d8b08c92010-06-07 13:13:28561 Value* new_value = Value::CreateStringValue(value.value());
562 pref_value_store_->SetUserPrefValue(path, new_value);
[email protected]66de4f092009-09-04 23:59:40563#endif
[email protected]b9636002009-03-04 00:05:25564
[email protected]d81288a02010-08-18 07:25:50565 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
[email protected]b9636002009-03-04 00:05:25566}
567
[email protected]57ecc4b2010-08-11 03:02:51568void PrefService::SetInt64(const char* path, int64 value) {
[email protected]0bb1a622009-03-04 03:22:32569 DCHECK(CalledOnValidThread());
570
571 const Preference* pref = FindPreference(path);
572 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40573 NOTREACHED() << "Trying to write an unregistered pref: " << path;
[email protected]0bb1a622009-03-04 03:22:32574 return;
575 }
[email protected]91ae7e32010-04-23 12:58:50576 if (pref->IsManaged()) {
577 NOTREACHED() << "Preference is managed: " << path;
578 return;
579 }
[email protected]0bb1a622009-03-04 03:22:32580 if (pref->type() != Value::TYPE_STRING) {
[email protected]b154e6f2009-03-06 01:52:40581 NOTREACHED() << "Wrong type for SetInt64: " << path;
[email protected]0bb1a622009-03-04 03:22:32582 return;
583 }
584
585 scoped_ptr<Value> old_value(GetPrefCopy(path));
[email protected]e83326f2010-07-31 17:29:25586 Value* new_value = Value::CreateStringValue(base::Int64ToString(value));
[email protected]d8b08c92010-06-07 13:13:28587 pref_value_store_->SetUserPrefValue(path, new_value);
[email protected]0bb1a622009-03-04 03:22:32588
[email protected]d81288a02010-08-18 07:25:50589 pref_notifier_->OnUserPreferenceSet(path, old_value.get());
[email protected]0bb1a622009-03-04 03:22:32590}
591
[email protected]57ecc4b2010-08-11 03:02:51592int64 PrefService::GetInt64(const char* path) const {
[email protected]0bb1a622009-03-04 03:22:32593 DCHECK(CalledOnValidThread());
594
[email protected]0bb1a622009-03-04 03:22:32595 const Preference* pref = FindPreference(path);
596 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40597 NOTREACHED() << "Trying to read an unregistered pref: " << path;
[email protected]c3453302009-12-01 01:33:08598 return 0;
[email protected]0bb1a622009-03-04 03:22:32599 }
[email protected]dc9a6762010-08-16 07:13:53600 std::string result("0");
[email protected]0bb1a622009-03-04 03:22:32601 bool rv = pref->GetValue()->GetAsString(&result);
602 DCHECK(rv);
[email protected]e83326f2010-07-31 17:29:25603
604 int64 val;
[email protected]dc9a6762010-08-16 07:13:53605 base::StringToInt64(result, &val);
[email protected]e83326f2010-07-31 17:29:25606 return val;
[email protected]0bb1a622009-03-04 03:22:32607}
608
[email protected]57ecc4b2010-08-11 03:02:51609void PrefService::RegisterInt64Pref(const char* path, int64 default_value) {
[email protected]40a47c162010-09-09 11:14:01610 Preference* pref = new Preference(pref_value_store_.get(), path,
611 Value::CreateStringValue(base::Int64ToString(default_value)));
612 RegisterPreference(pref);
[email protected]0bb1a622009-03-04 03:22:32613}
614
[email protected]57ecc4b2010-08-11 03:02:51615DictionaryValue* PrefService::GetMutableDictionary(const char* path) {
initial.commit09911bf2008-07-26 23:55:29616 DCHECK(CalledOnValidThread());
617
618 const Preference* pref = FindPreference(path);
619 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40620 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29621 return NULL;
622 }
623 if (pref->type() != Value::TYPE_DICTIONARY) {
[email protected]b154e6f2009-03-06 01:52:40624 NOTREACHED() << "Wrong type for GetMutableDictionary: " << path;
initial.commit09911bf2008-07-26 23:55:29625 return NULL;
626 }
627
628 DictionaryValue* dict = NULL;
[email protected]d8b08c92010-06-07 13:13:28629 Value* tmp_value = NULL;
[email protected]91761242010-06-10 15:35:37630 if (!pref_value_store_->GetValue(path, &tmp_value) ||
631 !tmp_value->IsType(Value::TYPE_DICTIONARY)) {
initial.commit09911bf2008-07-26 23:55:29632 dict = new DictionaryValue;
[email protected]d8b08c92010-06-07 13:13:28633 pref_value_store_->SetUserPrefValue(path, dict);
634 } else {
635 dict = static_cast<DictionaryValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29636 }
637 return dict;
638}
639
[email protected]57ecc4b2010-08-11 03:02:51640ListValue* PrefService::GetMutableList(const char* path) {
initial.commit09911bf2008-07-26 23:55:29641 DCHECK(CalledOnValidThread());
642
643 const Preference* pref = FindPreference(path);
644 if (!pref) {
[email protected]b154e6f2009-03-06 01:52:40645 NOTREACHED() << "Trying to get an unregistered pref: " << path;
initial.commit09911bf2008-07-26 23:55:29646 return NULL;
647 }
648 if (pref->type() != Value::TYPE_LIST) {
[email protected]b154e6f2009-03-06 01:52:40649 NOTREACHED() << "Wrong type for GetMutableList: " << path;
initial.commit09911bf2008-07-26 23:55:29650 return NULL;
651 }
652
653 ListValue* list = NULL;
[email protected]d8b08c92010-06-07 13:13:28654 Value* tmp_value = NULL;
[email protected]40a47c162010-09-09 11:14:01655 if (!pref_value_store_->GetValue(path, &tmp_value)) {
initial.commit09911bf2008-07-26 23:55:29656 list = new ListValue;
[email protected]d8b08c92010-06-07 13:13:28657 pref_value_store_->SetUserPrefValue(path, list);
658 } else {
659 list = static_cast<ListValue*>(tmp_value);
initial.commit09911bf2008-07-26 23:55:29660 }
661 return list;
662}
663
[email protected]57ecc4b2010-08-11 03:02:51664Value* PrefService::GetPrefCopy(const char* path) {
initial.commit09911bf2008-07-26 23:55:29665 DCHECK(CalledOnValidThread());
666
667 const Preference* pref = FindPreference(path);
668 DCHECK(pref);
669 return pref->GetValue()->DeepCopy();
670}
671
initial.commit09911bf2008-07-26 23:55:29672///////////////////////////////////////////////////////////////////////////////
673// PrefService::Preference
674
[email protected]40a47c162010-09-09 11:14:01675PrefService::Preference::Preference(PrefValueStore* pref_value_store,
[email protected]57ecc4b2010-08-11 03:02:51676 const char* name,
[email protected]40a47c162010-09-09 11:14:01677 Value* default_value)
678 : type_(Value::TYPE_NULL),
initial.commit09911bf2008-07-26 23:55:29679 name_(name),
[email protected]40a47c162010-09-09 11:14:01680 default_value_(default_value),
681 pref_value_store_(pref_value_store) {
initial.commit09911bf2008-07-26 23:55:29682 DCHECK(name);
[email protected]40a47c162010-09-09 11:14:01683
684 if (default_value) {
685 type_ = default_value->GetType();
686 DCHECK(type_ != Value::TYPE_NULL && type_ != Value::TYPE_BINARY) <<
687 "invalid preference type: " << type_;
688 }
689
690 // We set the default value of lists and dictionaries to be null so it's
691 // easier for callers to check for empty list/dict prefs.
692 if (Value::TYPE_LIST == type_ || Value::TYPE_DICTIONARY == type_)
693 default_value_.reset(Value::CreateNullValue());
initial.commit09911bf2008-07-26 23:55:29694}
695
696const Value* PrefService::Preference::GetValue() const {
[email protected]40a47c162010-09-09 11:14:01697 DCHECK(NULL != pref_value_store_) <<
initial.commit09911bf2008-07-26 23:55:29698 "Must register pref before getting its value";
699
[email protected]40a47c162010-09-09 11:14:01700 Value* temp_value = NULL;
701 if (pref_value_store_->GetValue(name_, &temp_value) &&
702 temp_value->GetType() == type_) {
703 return temp_value;
initial.commit09911bf2008-07-26 23:55:29704 }
705
[email protected]40a47c162010-09-09 11:14:01706 // Pref not found, just return the app default.
707 return default_value_.get();
[email protected]37939232010-09-09 07:42:35708}
709
710bool PrefService::Preference::IsDefaultValue() const {
[email protected]40a47c162010-09-09 11:14:01711 DCHECK(default_value_.get());
712 return default_value_->Equals(GetValue());
713}
714
715bool PrefService::Preference::IsManaged() const {
716 return pref_value_store_->PrefValueInManagedStore(name_.c_str());
717}
718
719bool PrefService::Preference::HasExtensionSetting() const {
720 return pref_value_store_->PrefValueInExtensionStore(name_.c_str());
721}
722
723bool PrefService::Preference::HasUserSetting() const {
724 return pref_value_store_->PrefValueInUserStore(name_.c_str());
725}
726
727bool PrefService::Preference::IsExtensionControlled() const {
728 return pref_value_store_->PrefValueFromExtensionStore(name_.c_str());
729}
730
731bool PrefService::Preference::IsUserControlled() const {
732 return pref_value_store_->PrefValueFromUserStore(name_.c_str());
[email protected]d7449e82010-07-14 11:42:35733}
[email protected]74379bc52010-07-21 13:54:08734
735bool PrefService::Preference::IsUserModifiable() const {
[email protected]40a47c162010-09-09 11:14:01736 return pref_value_store_->PrefValueUserModifiable(name_.c_str());
[email protected]74379bc52010-07-21 13:54:08737}