| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prefs/pref_service.h" | 5 #include "chrome/browser/prefs/pref_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/prefs/default_pref_store.h" | 14 #include "base/prefs/default_pref_store.h" |
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
| 17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/value_conversions.h" | 18 #include "base/value_conversions.h" |
| 19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 20 #include "chrome/browser/prefs/pref_notifier_impl.h" | 20 #include "chrome/browser/prefs/pref_notifier_impl.h" |
| 21 #include "chrome/browser/prefs/pref_registry.h" |
| 21 #include "chrome/browser/prefs/pref_value_store.h" | 22 #include "chrome/browser/prefs/pref_value_store.h" |
| 22 | 23 |
| 23 using content::BrowserContext; | 24 using content::BrowserContext; |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate { | 28 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate { |
| 28 public: | 29 public: |
| 29 ReadErrorHandler(base::Callback<void(PersistentPrefStore::PrefReadError)> cb) | 30 ReadErrorHandler(base::Callback<void(PersistentPrefStore::PrefReadError)> cb) |
| 30 : callback_(cb) {} | 31 : callback_(cb) {} |
| 31 | 32 |
| 32 virtual void OnError(PersistentPrefStore::PrefReadError error) { | 33 virtual void OnError(PersistentPrefStore::PrefReadError error) { |
| 33 callback_.Run(error); | 34 callback_.Run(error); |
| 34 } | 35 } |
| 35 | 36 |
| 36 private: | 37 private: |
| 37 base::Callback<void(PersistentPrefStore::PrefReadError)> callback_; | 38 base::Callback<void(PersistentPrefStore::PrefReadError)> callback_; |
| 38 }; | 39 }; |
| 39 | 40 |
| 40 } // namespace | 41 } // namespace |
| 41 | 42 |
| 42 PrefService::PrefService( | 43 PrefService::PrefService( |
| 43 PrefNotifierImpl* pref_notifier, | 44 PrefNotifierImpl* pref_notifier, |
| 44 PrefValueStore* pref_value_store, | 45 PrefValueStore* pref_value_store, |
| 45 PersistentPrefStore* user_prefs, | 46 PersistentPrefStore* user_prefs, |
| 46 DefaultPrefStore* default_store, | 47 PrefRegistry* pref_registry, |
| 47 base::Callback<void(PersistentPrefStore::PrefReadError)> | 48 base::Callback<void(PersistentPrefStore::PrefReadError)> |
| 48 read_error_callback, | 49 read_error_callback, |
| 49 bool async) | 50 bool async) |
| 50 : pref_notifier_(pref_notifier), | 51 : pref_notifier_(pref_notifier), |
| 51 pref_value_store_(pref_value_store), | 52 pref_value_store_(pref_value_store), |
| 53 pref_registry_(pref_registry), |
| 52 user_pref_store_(user_prefs), | 54 user_pref_store_(user_prefs), |
| 53 default_store_(default_store), | |
| 54 read_error_callback_(read_error_callback) { | 55 read_error_callback_(read_error_callback) { |
| 55 pref_notifier_->SetPrefService(this); | 56 pref_notifier_->SetPrefService(this); |
| 57 |
| 58 pref_registry_->SetRegistrationCallback( |
| 59 base::Bind(&PrefService::AddRegisteredPreference, |
| 60 base::Unretained(this))); |
| 61 pref_registry_->SetUnregistrationCallback( |
| 62 base::Bind(&PrefService::RemoveRegisteredPreference, |
| 63 base::Unretained(this))); |
| 64 AddInitialPreferences(); |
| 65 |
| 56 InitFromStorage(async); | 66 InitFromStorage(async); |
| 57 } | 67 } |
| 58 | 68 |
| 59 PrefService::~PrefService() { | 69 PrefService::~PrefService() { |
| 60 DCHECK(CalledOnValidThread()); | 70 DCHECK(CalledOnValidThread()); |
| 61 | 71 |
| 72 // Remove our callbacks, setting NULL ones. |
| 73 pref_registry_->SetRegistrationCallback(PrefRegistry::RegistrationCallback()); |
| 74 pref_registry_->SetUnregistrationCallback( |
| 75 PrefRegistry::UnregistrationCallback()); |
| 76 |
| 62 // Reset pointers so accesses after destruction reliably crash. | 77 // Reset pointers so accesses after destruction reliably crash. |
| 63 pref_value_store_.reset(); | 78 pref_value_store_.reset(); |
| 79 pref_registry_ = NULL; |
| 64 user_pref_store_ = NULL; | 80 user_pref_store_ = NULL; |
| 65 default_store_ = NULL; | |
| 66 pref_notifier_.reset(); | 81 pref_notifier_.reset(); |
| 67 } | 82 } |
| 68 | 83 |
| 69 void PrefService::InitFromStorage(bool async) { | 84 void PrefService::InitFromStorage(bool async) { |
| 70 if (!async) { | 85 if (!async) { |
| 71 read_error_callback_.Run(user_pref_store_->ReadPrefs()); | 86 read_error_callback_.Run(user_pref_store_->ReadPrefs()); |
| 72 } else { | 87 } else { |
| 73 // Guarantee that initialization happens after this function returned. | 88 // Guarantee that initialization happens after this function returned. |
| 74 MessageLoop::current()->PostTask( | 89 MessageLoop::current()->PostTask( |
| 75 FROM_HERE, | 90 FROM_HERE, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 180 } |
| 166 | 181 |
| 167 bool PrefService::HasPrefPath(const char* path) const { | 182 bool PrefService::HasPrefPath(const char* path) const { |
| 168 const Preference* pref = FindPreference(path); | 183 const Preference* pref = FindPreference(path); |
| 169 return pref && !pref->IsDefaultValue(); | 184 return pref && !pref->IsDefaultValue(); |
| 170 } | 185 } |
| 171 | 186 |
| 172 DictionaryValue* PrefService::GetPreferenceValues() const { | 187 DictionaryValue* PrefService::GetPreferenceValues() const { |
| 173 DCHECK(CalledOnValidThread()); | 188 DCHECK(CalledOnValidThread()); |
| 174 DictionaryValue* out = new DictionaryValue; | 189 DictionaryValue* out = new DictionaryValue; |
| 175 DefaultPrefStore::const_iterator i = default_store_->begin(); | 190 PrefRegistry::const_iterator i = pref_registry_->begin(); |
| 176 for (; i != default_store_->end(); ++i) { | 191 for (; i != pref_registry_->end(); ++i) { |
| 177 const Value* value = GetPreferenceValue(i->first); | 192 const Value* value = GetPreferenceValue(i->first); |
| 178 DCHECK(value); | 193 DCHECK(value); |
| 179 out->Set(i->first, value->DeepCopy()); | 194 out->Set(i->first, value->DeepCopy()); |
| 180 } | 195 } |
| 181 return out; | 196 return out; |
| 182 } | 197 } |
| 183 | 198 |
| 184 const PrefService::Preference* PrefService::FindPreference( | 199 const PrefService::Preference* PrefService::FindPreference( |
| 185 const char* pref_name) const { | 200 const char* pref_name) const { |
| 186 DCHECK(CalledOnValidThread()); | 201 DCHECK(CalledOnValidThread()); |
| 187 PreferenceMap::iterator it = prefs_map_.find(pref_name); | 202 PreferenceMap::iterator it = prefs_map_.find(pref_name); |
| 188 if (it != prefs_map_.end()) | 203 if (it != prefs_map_.end()) |
| 189 return &(it->second); | 204 return &(it->second); |
| 190 const base::Value::Type type = default_store_->GetType(pref_name); | 205 const base::Value* default_value = NULL; |
| 191 if (type == Value::TYPE_NULL) | 206 if (!pref_registry_->defaults()->GetValue(pref_name, &default_value)) |
| 192 return NULL; | 207 return NULL; |
| 193 it = prefs_map_.insert( | 208 it = prefs_map_.insert( |
| 194 std::make_pair(pref_name, Preference(this, pref_name, type))).first; | 209 std::make_pair(pref_name, Preference( |
| 210 this, pref_name, default_value->GetType()))).first; |
| 195 return &(it->second); | 211 return &(it->second); |
| 196 } | 212 } |
| 197 | 213 |
| 198 bool PrefService::ReadOnly() const { | 214 bool PrefService::ReadOnly() const { |
| 199 return user_pref_store_->ReadOnly(); | 215 return user_pref_store_->ReadOnly(); |
| 200 } | 216 } |
| 201 | 217 |
| 202 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus() | 218 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus() |
| 203 const { | 219 const { |
| 204 if (!user_pref_store_->IsInitializationComplete()) | 220 if (!user_pref_store_->IsInitializationComplete()) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 return NULL; | 275 return NULL; |
| 260 } | 276 } |
| 261 | 277 |
| 262 return value; | 278 return value; |
| 263 } | 279 } |
| 264 | 280 |
| 265 const base::Value* PrefService::GetDefaultPrefValue(const char* path) const { | 281 const base::Value* PrefService::GetDefaultPrefValue(const char* path) const { |
| 266 DCHECK(CalledOnValidThread()); | 282 DCHECK(CalledOnValidThread()); |
| 267 // Lookup the preference in the default store. | 283 // Lookup the preference in the default store. |
| 268 const base::Value* value = NULL; | 284 const base::Value* value = NULL; |
| 269 if (!default_store_->GetValue(path, &value)) { | 285 if (!pref_registry_->defaults()->GetValue(path, &value)) { |
| 270 NOTREACHED() << "Default value missing for pref: " << path; | 286 NOTREACHED() << "Default value missing for pref: " << path; |
| 271 return NULL; | 287 return NULL; |
| 272 } | 288 } |
| 273 return value; | 289 return value; |
| 274 } | 290 } |
| 275 | 291 |
| 276 const ListValue* PrefService::GetList(const char* path) const { | 292 const ListValue* PrefService::GetList(const char* path) const { |
| 277 DCHECK(CalledOnValidThread()); | 293 DCHECK(CalledOnValidThread()); |
| 278 | 294 |
| 279 const Value* value = GetPreferenceValue(path); | 295 const Value* value = GetPreferenceValue(path); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 293 } | 309 } |
| 294 | 310 |
| 295 void PrefService::RemovePrefObserver(const char* path, PrefObserver* obs) { | 311 void PrefService::RemovePrefObserver(const char* path, PrefObserver* obs) { |
| 296 pref_notifier_->RemovePrefObserver(path, obs); | 312 pref_notifier_->RemovePrefObserver(path, obs); |
| 297 } | 313 } |
| 298 | 314 |
| 299 void PrefService::AddPrefInitObserver(base::Callback<void(bool)> obs) { | 315 void PrefService::AddPrefInitObserver(base::Callback<void(bool)> obs) { |
| 300 pref_notifier_->AddInitObserver(obs); | 316 pref_notifier_->AddInitObserver(obs); |
| 301 } | 317 } |
| 302 | 318 |
| 303 void PrefService::RegisterPreference(const char* path, | 319 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() { |
| 304 Value* default_value) { | 320 return pref_registry_.get(); |
| 321 } |
| 322 |
| 323 void PrefService::AddInitialPreferences() { |
| 324 for (PrefRegistry::const_iterator it = pref_registry_->begin(); |
| 325 it != pref_registry_->end(); |
| 326 ++it) { |
| 327 AddRegisteredPreference(it->first.c_str(), it->second); |
| 328 } |
| 329 } |
| 330 |
| 331 // TODO(joi): Once MarkNeedsEmptyValue is gone, we can probably |
| 332 // completely get rid of this method. There will be one difference in |
| 333 // semantics; currently all registered preferences are stored right |
| 334 // away in the prefs_map_, if we remove this they would be stored only |
| 335 // opportunistically. |
| 336 void PrefService::AddRegisteredPreference(const char* path, |
| 337 Value* default_value) { |
| 305 DCHECK(CalledOnValidThread()); | 338 DCHECK(CalledOnValidThread()); |
| 306 | 339 |
| 307 // The main code path takes ownership, but most don't. We'll be safe. | |
| 308 scoped_ptr<Value> scoped_value(default_value); | |
| 309 | |
| 310 CHECK(!FindPreference(path)) << "Tried to register duplicate pref " << path; | |
| 311 | |
| 312 base::Value::Type orig_type = default_value->GetType(); | |
| 313 DCHECK(orig_type != Value::TYPE_NULL && orig_type != Value::TYPE_BINARY) << | |
| 314 "invalid preference type: " << orig_type; | |
| 315 | |
| 316 // For ListValue and DictionaryValue with non empty default, empty value | 340 // For ListValue and DictionaryValue with non empty default, empty value |
| 317 // for |path| needs to be persisted in |user_pref_store_|. So that | 341 // for |path| needs to be persisted in |user_pref_store_|. So that |
| 318 // non empty default is not used when user sets an empty ListValue or | 342 // non empty default is not used when user sets an empty ListValue or |
| 319 // DictionaryValue. | 343 // DictionaryValue. |
| 320 bool needs_empty_value = false; | 344 bool needs_empty_value = false; |
| 345 base::Value::Type orig_type = default_value->GetType(); |
| 321 if (orig_type == base::Value::TYPE_LIST) { | 346 if (orig_type == base::Value::TYPE_LIST) { |
| 322 const base::ListValue* list = NULL; | 347 const base::ListValue* list = NULL; |
| 323 if (default_value->GetAsList(&list) && !list->empty()) | 348 if (default_value->GetAsList(&list) && !list->empty()) |
| 324 needs_empty_value = true; | 349 needs_empty_value = true; |
| 325 } else if (orig_type == base::Value::TYPE_DICTIONARY) { | 350 } else if (orig_type == base::Value::TYPE_DICTIONARY) { |
| 326 const base::DictionaryValue* dict = NULL; | 351 const base::DictionaryValue* dict = NULL; |
| 327 if (default_value->GetAsDictionary(&dict) && !dict->empty()) | 352 if (default_value->GetAsDictionary(&dict) && !dict->empty()) |
| 328 needs_empty_value = true; | 353 needs_empty_value = true; |
| 329 } | 354 } |
| 330 if (needs_empty_value) | 355 if (needs_empty_value) |
| 331 user_pref_store_->MarkNeedsEmptyValue(path); | 356 user_pref_store_->MarkNeedsEmptyValue(path); |
| 332 | |
| 333 // Hand off ownership. | |
| 334 default_store_->SetDefaultValue(path, scoped_value.release()); | |
| 335 } | 357 } |
| 336 | 358 |
| 337 void PrefService::UnregisterPreference(const char* path) { | 359 // TODO(joi): We can get rid of this once the ability to unregister |
| 360 // prefs has been removed. |
| 361 void PrefService::RemoveRegisteredPreference(const char* path) { |
| 338 DCHECK(CalledOnValidThread()); | 362 DCHECK(CalledOnValidThread()); |
| 339 | 363 |
| 340 PreferenceMap::iterator it = prefs_map_.find(path); | 364 prefs_map_.erase(path); |
| 341 CHECK(it != prefs_map_.end()) << "Trying to unregister an unregistered pref: " | |
| 342 << path; | |
| 343 | |
| 344 prefs_map_.erase(it); | |
| 345 default_store_->RemoveDefaultValue(path); | |
| 346 } | 365 } |
| 347 | 366 |
| 348 void PrefService::ClearPref(const char* path) { | 367 void PrefService::ClearPref(const char* path) { |
| 349 DCHECK(CalledOnValidThread()); | 368 DCHECK(CalledOnValidThread()); |
| 350 | 369 |
| 351 const Preference* pref = FindPreference(path); | 370 const Preference* pref = FindPreference(path); |
| 352 if (!pref) { | 371 if (!pref) { |
| 353 NOTREACHED() << "Trying to clear an unregistered pref: " << path; | 372 NOTREACHED() << "Trying to clear an unregistered pref: " << path; |
| 354 return; | 373 return; |
| 355 } | 374 } |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 return pref_value_store()->PrefValueUserModifiable(name_.c_str()); | 573 return pref_value_store()->PrefValueUserModifiable(name_.c_str()); |
| 555 } | 574 } |
| 556 | 575 |
| 557 bool PrefService::Preference::IsExtensionModifiable() const { | 576 bool PrefService::Preference::IsExtensionModifiable() const { |
| 558 return pref_value_store()->PrefValueExtensionModifiable(name_.c_str()); | 577 return pref_value_store()->PrefValueExtensionModifiable(name_.c_str()); |
| 559 } | 578 } |
| 560 | 579 |
| 561 const base::Value* PrefService::GetPreferenceValue( | 580 const base::Value* PrefService::GetPreferenceValue( |
| 562 const std::string& path) const { | 581 const std::string& path) const { |
| 563 DCHECK(CalledOnValidThread()); | 582 DCHECK(CalledOnValidThread()); |
| 564 const base::Value::Type type = default_store_->GetType(path); | 583 const Value* default_value = NULL; |
| 565 if (type == Value::TYPE_NULL) | 584 if (pref_registry_->defaults()->GetValue(path, &default_value)) { |
| 566 return NULL; | 585 const Value* found_value = NULL; |
| 567 const Value* found_value = NULL; | 586 base::Value::Type default_type = default_value->GetType(); |
| 568 if (pref_value_store_->GetValue(path, type, &found_value)) { | 587 if (pref_value_store_->GetValue(path, default_type, &found_value)) { |
| 569 DCHECK(found_value->IsType(type)); | 588 DCHECK(found_value->IsType(default_type)); |
| 570 return found_value; | 589 return found_value; |
| 590 } else { |
| 591 // Every registered preference has at least a default value. |
| 592 NOTREACHED() << "no valid value found for registered pref " << path; |
| 593 } |
| 571 } | 594 } |
| 572 | 595 |
| 573 // Every registered preference has at least a default value. | |
| 574 NOTREACHED() << "no valid value found for registered pref " << path; | |
| 575 return NULL; | 596 return NULL; |
| 576 } | 597 } |
| OLD | NEW |