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
3 // found in the LICENSE file.
5 #include "base/prefs/pref_member.h"
7 #include "base/callback.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/value_conversions.h"
14 using base::SingleThreadTaskRunner
;
18 PrefMemberBase::PrefMemberBase()
20 setting_value_(false) {
23 PrefMemberBase::~PrefMemberBase() {
27 void PrefMemberBase::Init(const std::string
& pref_name
,
29 const NamedChangeCallback
& observer
) {
31 Init(pref_name
, prefs
);
34 void PrefMemberBase::Init(const std::string
& pref_name
, PrefService
* prefs
) {
36 DCHECK(pref_name_
.empty()); // Check that Init is only called once.
38 pref_name_
= pref_name
;
39 // Check that the preference is registered.
40 DCHECK(prefs_
->FindPreference(pref_name_
)) << pref_name
<< " not registered.";
42 // Add ourselves as a pref observer so we can keep our local value in sync.
43 prefs_
->AddPrefObserver(pref_name
, this);
46 void PrefMemberBase::Destroy() {
47 if (prefs_
&& !pref_name_
.empty()) {
48 prefs_
->RemovePrefObserver(pref_name_
, this);
53 void PrefMemberBase::MoveToThread(
54 scoped_refptr
<SingleThreadTaskRunner
> task_runner
) {
55 VerifyValuePrefName();
56 // Load the value from preferences if it hasn't been loaded so far.
58 UpdateValueFromPref(base::Closure());
59 internal()->MoveToThread(task_runner
.Pass());
62 void PrefMemberBase::OnPreferenceChanged(PrefService
* service
,
63 const std::string
& pref_name
) {
64 VerifyValuePrefName();
65 UpdateValueFromPref((!setting_value_
&& !observer_
.is_null()) ?
66 base::Bind(observer_
, pref_name
) : base::Closure());
69 void PrefMemberBase::UpdateValueFromPref(const base::Closure
& callback
) const {
70 VerifyValuePrefName();
71 const PrefService::Preference
* pref
= prefs_
->FindPreference(pref_name_
);
75 internal()->UpdateValue(pref
->GetValue()->DeepCopy(),
77 pref
->IsUserModifiable(),
81 void PrefMemberBase::VerifyPref() const {
82 VerifyValuePrefName();
84 UpdateValueFromPref(base::Closure());
87 void PrefMemberBase::InvokeUnnamedCallback(const base::Closure
& callback
,
88 const std::string
& pref_name
) {
92 PrefMemberBase::Internal::Internal()
93 : thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
95 is_user_modifiable_(false) {
97 PrefMemberBase::Internal::~Internal() { }
99 bool PrefMemberBase::Internal::IsOnCorrectThread() const {
100 return thread_task_runner_
->BelongsToCurrentThread();
103 void PrefMemberBase::Internal::UpdateValue(
106 bool is_user_modifiable
,
107 const base::Closure
& callback
) const {
108 scoped_ptr
<base::Value
> value(v
);
109 base::ScopedClosureRunner
closure_runner(callback
);
110 if (IsOnCorrectThread()) {
111 bool rv
= UpdateValueInternal(*value
);
113 is_managed_
= is_managed
;
114 is_user_modifiable_
= is_user_modifiable
;
116 bool may_run
= thread_task_runner_
->PostTask(
117 FROM_HERE
, base::Bind(&PrefMemberBase::Internal::UpdateValue
, this,
118 value
.release(), is_managed
, is_user_modifiable
,
119 closure_runner
.Release()));
124 void PrefMemberBase::Internal::MoveToThread(
125 scoped_refptr
<SingleThreadTaskRunner
> task_runner
) {
126 CheckOnCorrectThread();
127 thread_task_runner_
= task_runner
.Pass();
130 bool PrefMemberVectorStringUpdate(const base::Value
& value
,
131 std::vector
<std::string
>* string_vector
) {
132 if (!value
.IsType(base::Value::TYPE_LIST
))
134 const base::ListValue
* list
= static_cast<const base::ListValue
*>(&value
);
136 std::vector
<std::string
> local_vector
;
137 for (base::ListValue::const_iterator it
= list
->begin();
138 it
!= list
->end(); ++it
) {
139 std::string string_value
;
140 if (!(*it
)->GetAsString(&string_value
))
143 local_vector
.push_back(string_value
);
146 string_vector
->swap(local_vector
);
150 } // namespace subtle
153 void PrefMember
<bool>::UpdatePref(const bool& value
) {
154 prefs()->SetBoolean(pref_name(), value
);
158 bool PrefMember
<bool>::Internal::UpdateValueInternal(
159 const base::Value
& value
) const {
160 return value
.GetAsBoolean(&value_
);
164 void PrefMember
<int>::UpdatePref(const int& value
) {
165 prefs()->SetInteger(pref_name(), value
);
169 bool PrefMember
<int>::Internal::UpdateValueInternal(
170 const base::Value
& value
) const {
171 return value
.GetAsInteger(&value_
);
175 void PrefMember
<double>::UpdatePref(const double& value
) {
176 prefs()->SetDouble(pref_name(), value
);
180 bool PrefMember
<double>::Internal::UpdateValueInternal(const base::Value
& value
)
182 return value
.GetAsDouble(&value_
);
186 void PrefMember
<std::string
>::UpdatePref(const std::string
& value
) {
187 prefs()->SetString(pref_name(), value
);
191 bool PrefMember
<std::string
>::Internal::UpdateValueInternal(
192 const base::Value
& value
)
194 return value
.GetAsString(&value_
);
198 void PrefMember
<base::FilePath
>::UpdatePref(const base::FilePath
& value
) {
199 prefs()->SetFilePath(pref_name(), value
);
203 bool PrefMember
<base::FilePath
>::Internal::UpdateValueInternal(
204 const base::Value
& value
)
206 return base::GetValueAsFilePath(value
, &value_
);
210 void PrefMember
<std::vector
<std::string
> >::UpdatePref(
211 const std::vector
<std::string
>& value
) {
212 base::ListValue list_value
;
213 list_value
.AppendStrings(value
);
214 prefs()->Set(pref_name(), list_value
);
218 bool PrefMember
<std::vector
<std::string
> >::Internal::UpdateValueInternal(
219 const base::Value
& value
) const {
220 return subtle::PrefMemberVectorStringUpdate(value
, &value_
);