| Index: base/prefs/pref_value_store.cc
|
| diff --git a/base/prefs/pref_value_store.cc b/base/prefs/pref_value_store.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fe7cd67d08eb5970e36f50cf4c849ad1b842454e
|
| --- /dev/null
|
| +++ b/base/prefs/pref_value_store.cc
|
| @@ -0,0 +1,290 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/prefs/pref_value_store.h"
|
| +
|
| +#include <stddef.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/prefs/pref_notifier.h"
|
| +#include "base/prefs/pref_observer.h"
|
| +
|
| +PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
|
| + : pref_value_store_(NULL),
|
| + type_(PrefValueStore::INVALID_STORE) {
|
| +}
|
| +
|
| +PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
|
| + if (pref_store_.get()) {
|
| + pref_store_->RemoveObserver(this);
|
| + pref_store_ = NULL;
|
| + }
|
| + pref_value_store_ = NULL;
|
| +}
|
| +
|
| +void PrefValueStore::PrefStoreKeeper::Initialize(
|
| + PrefValueStore* store,
|
| + PrefStore* pref_store,
|
| + PrefValueStore::PrefStoreType type) {
|
| + if (pref_store_.get()) {
|
| + pref_store_->RemoveObserver(this);
|
| + DCHECK(!pref_store_->HasObservers());
|
| + }
|
| + type_ = type;
|
| + pref_value_store_ = store;
|
| + pref_store_ = pref_store;
|
| + if (pref_store_.get())
|
| + pref_store_->AddObserver(this);
|
| +}
|
| +
|
| +void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
|
| + const std::string& key) {
|
| + pref_value_store_->OnPrefValueChanged(type_, key);
|
| +}
|
| +
|
| +void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
|
| + bool succeeded) {
|
| + pref_value_store_->OnInitializationCompleted(type_, succeeded);
|
| +}
|
| +
|
| +PrefValueStore::PrefValueStore(PrefStore* managed_prefs,
|
| + PrefStore* supervised_user_prefs,
|
| + PrefStore* extension_prefs,
|
| + PrefStore* command_line_prefs,
|
| + PrefStore* user_prefs,
|
| + PrefStore* recommended_prefs,
|
| + PrefStore* default_prefs,
|
| + PrefNotifier* pref_notifier)
|
| + : pref_notifier_(pref_notifier),
|
| + initialization_failed_(false) {
|
| + InitPrefStore(MANAGED_STORE, managed_prefs);
|
| + InitPrefStore(SUPERVISED_USER_STORE, supervised_user_prefs);
|
| + InitPrefStore(EXTENSION_STORE, extension_prefs);
|
| + InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
|
| + InitPrefStore(USER_STORE, user_prefs);
|
| + InitPrefStore(RECOMMENDED_STORE, recommended_prefs);
|
| + InitPrefStore(DEFAULT_STORE, default_prefs);
|
| +
|
| + CheckInitializationCompleted();
|
| +}
|
| +
|
| +PrefValueStore::~PrefValueStore() {}
|
| +
|
| +PrefValueStore* PrefValueStore::CloneAndSpecialize(
|
| + PrefStore* managed_prefs,
|
| + PrefStore* supervised_user_prefs,
|
| + PrefStore* extension_prefs,
|
| + PrefStore* command_line_prefs,
|
| + PrefStore* user_prefs,
|
| + PrefStore* recommended_prefs,
|
| + PrefStore* default_prefs,
|
| + PrefNotifier* pref_notifier) {
|
| + DCHECK(pref_notifier);
|
| + if (!managed_prefs)
|
| + managed_prefs = GetPrefStore(MANAGED_STORE);
|
| + if (!supervised_user_prefs)
|
| + supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE);
|
| + if (!extension_prefs)
|
| + extension_prefs = GetPrefStore(EXTENSION_STORE);
|
| + if (!command_line_prefs)
|
| + command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
|
| + if (!user_prefs)
|
| + user_prefs = GetPrefStore(USER_STORE);
|
| + if (!recommended_prefs)
|
| + recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
|
| + if (!default_prefs)
|
| + default_prefs = GetPrefStore(DEFAULT_STORE);
|
| +
|
| + return new PrefValueStore(
|
| + managed_prefs, supervised_user_prefs, extension_prefs, command_line_prefs,
|
| + user_prefs, recommended_prefs, default_prefs, pref_notifier);
|
| +}
|
| +
|
| +void PrefValueStore::set_callback(const PrefChangedCallback& callback) {
|
| + pref_changed_callback_ = callback;
|
| +}
|
| +
|
| +bool PrefValueStore::GetValue(const std::string& name,
|
| + base::Value::Type type,
|
| + const base::Value** out_value) const {
|
| + // Check the |PrefStore|s in order of their priority from highest to lowest,
|
| + // looking for the first preference value with the given |name| and |type|.
|
| + for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
|
| + if (GetValueFromStoreWithType(name, type, static_cast<PrefStoreType>(i),
|
| + out_value))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool PrefValueStore::GetRecommendedValue(const std::string& name,
|
| + base::Value::Type type,
|
| + const base::Value** out_value) const {
|
| + return GetValueFromStoreWithType(name, type, RECOMMENDED_STORE, out_value);
|
| +}
|
| +
|
| +void PrefValueStore::NotifyPrefChanged(
|
| + const std::string& path,
|
| + PrefValueStore::PrefStoreType new_store) {
|
| + DCHECK(new_store != INVALID_STORE);
|
| + // A notification is sent when the pref value in any store changes. If this
|
| + // store is currently being overridden by a higher-priority store, the
|
| + // effective value of the pref will not have changed.
|
| + pref_notifier_->OnPreferenceChanged(path);
|
| + if (!pref_changed_callback_.is_null())
|
| + pref_changed_callback_.Run(path);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueInManagedStore(const std::string& name) const {
|
| + return PrefValueInStore(name, MANAGED_STORE);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueInSupervisedStore(const std::string& name) const {
|
| + return PrefValueInStore(name, SUPERVISED_USER_STORE);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueInExtensionStore(const std::string& name) const {
|
| + return PrefValueInStore(name, EXTENSION_STORE);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueInUserStore(const std::string& name) const {
|
| + return PrefValueInStore(name, USER_STORE);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueFromExtensionStore(
|
| + const std::string& name) const {
|
| + return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueFromUserStore(const std::string& name) const {
|
| + return ControllingPrefStoreForPref(name) == USER_STORE;
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueFromRecommendedStore(
|
| + const std::string& name) const {
|
| + return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE;
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueFromDefaultStore(const std::string& name) const {
|
| + return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueUserModifiable(const std::string& name) const {
|
| + PrefStoreType effective_store = ControllingPrefStoreForPref(name);
|
| + return effective_store >= USER_STORE ||
|
| + effective_store == INVALID_STORE;
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueExtensionModifiable(
|
| + const std::string& name) const {
|
| + PrefStoreType effective_store = ControllingPrefStoreForPref(name);
|
| + return effective_store >= EXTENSION_STORE ||
|
| + effective_store == INVALID_STORE;
|
| +}
|
| +
|
| +void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
|
| + InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueInStore(
|
| + const std::string& name,
|
| + PrefValueStore::PrefStoreType store) const {
|
| + // Declare a temp Value* and call GetValueFromStore,
|
| + // ignoring the output value.
|
| + const base::Value* tmp_value = NULL;
|
| + return GetValueFromStore(name, store, &tmp_value);
|
| +}
|
| +
|
| +bool PrefValueStore::PrefValueInStoreRange(
|
| + const std::string& name,
|
| + PrefValueStore::PrefStoreType first_checked_store,
|
| + PrefValueStore::PrefStoreType last_checked_store) const {
|
| + if (first_checked_store > last_checked_store) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + for (size_t i = first_checked_store;
|
| + i <= static_cast<size_t>(last_checked_store); ++i) {
|
| + if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
|
| + const std::string& name) const {
|
| + for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
|
| + if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
|
| + return static_cast<PrefStoreType>(i);
|
| + }
|
| + return INVALID_STORE;
|
| +}
|
| +
|
| +bool PrefValueStore::GetValueFromStore(const std::string& name,
|
| + PrefValueStore::PrefStoreType store_type,
|
| + const base::Value** out_value) const {
|
| + // Only return true if we find a value and it is the correct type, so stale
|
| + // values with the incorrect type will be ignored.
|
| + const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
|
| + if (store && store->GetValue(name, out_value))
|
| + return true;
|
| +
|
| + // No valid value found for the given preference name: set the return value
|
| + // to false.
|
| + *out_value = NULL;
|
| + return false;
|
| +}
|
| +
|
| +bool PrefValueStore::GetValueFromStoreWithType(
|
| + const std::string& name,
|
| + base::Value::Type type,
|
| + PrefStoreType store,
|
| + const base::Value** out_value) const {
|
| + if (GetValueFromStore(name, store, out_value)) {
|
| + if ((*out_value)->IsType(type))
|
| + return true;
|
| +
|
| + LOG(WARNING) << "Expected type for " << name << " is " << type
|
| + << " but got " << (*out_value)->GetType()
|
| + << " in store " << store;
|
| + }
|
| +
|
| + *out_value = NULL;
|
| + return false;
|
| +}
|
| +
|
| +void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
|
| + const std::string& key) {
|
| + NotifyPrefChanged(key, type);
|
| +}
|
| +
|
| +void PrefValueStore::OnInitializationCompleted(
|
| + PrefValueStore::PrefStoreType type, bool succeeded) {
|
| + if (initialization_failed_)
|
| + return;
|
| + if (!succeeded) {
|
| + initialization_failed_ = true;
|
| + pref_notifier_->OnInitializationCompleted(false);
|
| + return;
|
| + }
|
| + CheckInitializationCompleted();
|
| +}
|
| +
|
| +void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
|
| + PrefStore* pref_store) {
|
| + pref_stores_[type].Initialize(this, pref_store, type);
|
| +}
|
| +
|
| +void PrefValueStore::CheckInitializationCompleted() {
|
| + if (initialization_failed_)
|
| + return;
|
| + for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
|
| + scoped_refptr<PrefStore> store =
|
| + GetPrefStore(static_cast<PrefStoreType>(i));
|
| + if (store.get() && !store->IsInitializationComplete())
|
| + return;
|
| + }
|
| + pref_notifier_->OnInitializationCompleted(true);
|
| +}
|
|
|