| Index: base/prefs/pref_member.cc
|
| diff --git a/base/prefs/pref_member.cc b/base/prefs/pref_member.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..934237d37ca9df1ba474799721e6dfe7a582f78b
|
| --- /dev/null
|
| +++ b/base/prefs/pref_member.cc
|
| @@ -0,0 +1,223 @@
|
| +// 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_member.h"
|
| +
|
| +#include <utility>
|
| +
|
| +#include "base/callback.h"
|
| +#include "base/callback_helpers.h"
|
| +#include "base/location.h"
|
| +#include "base/prefs/pref_service.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| +#include "base/value_conversions.h"
|
| +
|
| +using base::SingleThreadTaskRunner;
|
| +
|
| +namespace subtle {
|
| +
|
| +PrefMemberBase::PrefMemberBase()
|
| + : prefs_(NULL),
|
| + setting_value_(false) {
|
| +}
|
| +
|
| +PrefMemberBase::~PrefMemberBase() {
|
| + Destroy();
|
| +}
|
| +
|
| +void PrefMemberBase::Init(const std::string& pref_name,
|
| + PrefService* prefs,
|
| + const NamedChangeCallback& observer) {
|
| + observer_ = observer;
|
| + Init(pref_name, prefs);
|
| +}
|
| +
|
| +void PrefMemberBase::Init(const std::string& pref_name, PrefService* prefs) {
|
| + DCHECK(prefs);
|
| + DCHECK(pref_name_.empty()); // Check that Init is only called once.
|
| + prefs_ = prefs;
|
| + pref_name_ = pref_name;
|
| + // Check that the preference is registered.
|
| + DCHECK(prefs_->FindPreference(pref_name_)) << pref_name << " not registered.";
|
| +
|
| + // Add ourselves as a pref observer so we can keep our local value in sync.
|
| + prefs_->AddPrefObserver(pref_name, this);
|
| +}
|
| +
|
| +void PrefMemberBase::Destroy() {
|
| + if (prefs_ && !pref_name_.empty()) {
|
| + prefs_->RemovePrefObserver(pref_name_, this);
|
| + prefs_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void PrefMemberBase::MoveToThread(
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner) {
|
| + VerifyValuePrefName();
|
| + // Load the value from preferences if it hasn't been loaded so far.
|
| + if (!internal())
|
| + UpdateValueFromPref(base::Closure());
|
| + internal()->MoveToThread(std::move(task_runner));
|
| +}
|
| +
|
| +void PrefMemberBase::OnPreferenceChanged(PrefService* service,
|
| + const std::string& pref_name) {
|
| + VerifyValuePrefName();
|
| + UpdateValueFromPref((!setting_value_ && !observer_.is_null()) ?
|
| + base::Bind(observer_, pref_name) : base::Closure());
|
| +}
|
| +
|
| +void PrefMemberBase::UpdateValueFromPref(const base::Closure& callback) const {
|
| + VerifyValuePrefName();
|
| + const PrefService::Preference* pref = prefs_->FindPreference(pref_name_);
|
| + DCHECK(pref);
|
| + if (!internal())
|
| + CreateInternal();
|
| + internal()->UpdateValue(pref->GetValue()->DeepCopy(),
|
| + pref->IsManaged(),
|
| + pref->IsUserModifiable(),
|
| + callback);
|
| +}
|
| +
|
| +void PrefMemberBase::VerifyPref() const {
|
| + VerifyValuePrefName();
|
| + if (!internal())
|
| + UpdateValueFromPref(base::Closure());
|
| +}
|
| +
|
| +void PrefMemberBase::InvokeUnnamedCallback(const base::Closure& callback,
|
| + const std::string& pref_name) {
|
| + callback.Run();
|
| +}
|
| +
|
| +PrefMemberBase::Internal::Internal()
|
| + : thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + is_managed_(false),
|
| + is_user_modifiable_(false) {
|
| +}
|
| +PrefMemberBase::Internal::~Internal() { }
|
| +
|
| +bool PrefMemberBase::Internal::IsOnCorrectThread() const {
|
| + return thread_task_runner_->BelongsToCurrentThread();
|
| +}
|
| +
|
| +void PrefMemberBase::Internal::UpdateValue(
|
| + base::Value* v,
|
| + bool is_managed,
|
| + bool is_user_modifiable,
|
| + const base::Closure& callback) const {
|
| + scoped_ptr<base::Value> value(v);
|
| + base::ScopedClosureRunner closure_runner(callback);
|
| + if (IsOnCorrectThread()) {
|
| + bool rv = UpdateValueInternal(*value);
|
| + DCHECK(rv);
|
| + is_managed_ = is_managed;
|
| + is_user_modifiable_ = is_user_modifiable;
|
| + } else {
|
| + bool may_run = thread_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&PrefMemberBase::Internal::UpdateValue, this,
|
| + value.release(), is_managed, is_user_modifiable,
|
| + closure_runner.Release()));
|
| + DCHECK(may_run);
|
| + }
|
| +}
|
| +
|
| +void PrefMemberBase::Internal::MoveToThread(
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner) {
|
| + CheckOnCorrectThread();
|
| + thread_task_runner_ = std::move(task_runner);
|
| +}
|
| +
|
| +bool PrefMemberVectorStringUpdate(const base::Value& value,
|
| + std::vector<std::string>* string_vector) {
|
| + if (!value.IsType(base::Value::TYPE_LIST))
|
| + return false;
|
| + const base::ListValue* list = static_cast<const base::ListValue*>(&value);
|
| +
|
| + std::vector<std::string> local_vector;
|
| + for (base::ListValue::const_iterator it = list->begin();
|
| + it != list->end(); ++it) {
|
| + std::string string_value;
|
| + if (!(*it)->GetAsString(&string_value))
|
| + return false;
|
| +
|
| + local_vector.push_back(string_value);
|
| + }
|
| +
|
| + string_vector->swap(local_vector);
|
| + return true;
|
| +}
|
| +
|
| +} // namespace subtle
|
| +
|
| +template <>
|
| +void PrefMember<bool>::UpdatePref(const bool& value) {
|
| + prefs()->SetBoolean(pref_name(), value);
|
| +}
|
| +
|
| +template <>
|
| +bool PrefMember<bool>::Internal::UpdateValueInternal(
|
| + const base::Value& value) const {
|
| + return value.GetAsBoolean(&value_);
|
| +}
|
| +
|
| +template <>
|
| +void PrefMember<int>::UpdatePref(const int& value) {
|
| + prefs()->SetInteger(pref_name(), value);
|
| +}
|
| +
|
| +template <>
|
| +bool PrefMember<int>::Internal::UpdateValueInternal(
|
| + const base::Value& value) const {
|
| + return value.GetAsInteger(&value_);
|
| +}
|
| +
|
| +template <>
|
| +void PrefMember<double>::UpdatePref(const double& value) {
|
| + prefs()->SetDouble(pref_name(), value);
|
| +}
|
| +
|
| +template <>
|
| +bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value)
|
| + const {
|
| + return value.GetAsDouble(&value_);
|
| +}
|
| +
|
| +template <>
|
| +void PrefMember<std::string>::UpdatePref(const std::string& value) {
|
| + prefs()->SetString(pref_name(), value);
|
| +}
|
| +
|
| +template <>
|
| +bool PrefMember<std::string>::Internal::UpdateValueInternal(
|
| + const base::Value& value)
|
| + const {
|
| + return value.GetAsString(&value_);
|
| +}
|
| +
|
| +template <>
|
| +void PrefMember<base::FilePath>::UpdatePref(const base::FilePath& value) {
|
| + prefs()->SetFilePath(pref_name(), value);
|
| +}
|
| +
|
| +template <>
|
| +bool PrefMember<base::FilePath>::Internal::UpdateValueInternal(
|
| + const base::Value& value)
|
| + const {
|
| + return base::GetValueAsFilePath(value, &value_);
|
| +}
|
| +
|
| +template <>
|
| +void PrefMember<std::vector<std::string> >::UpdatePref(
|
| + const std::vector<std::string>& value) {
|
| + base::ListValue list_value;
|
| + list_value.AppendStrings(value);
|
| + prefs()->Set(pref_name(), list_value);
|
| +}
|
| +
|
| +template <>
|
| +bool PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal(
|
| + const base::Value& value) const {
|
| + return subtle::PrefMemberVectorStringUpdate(value, &value_);
|
| +}
|
|
|