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/message_loop/message_loop_proxy.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/value_conversions.h"
14 using base::MessageLoopProxy
;
15 using base::SingleThreadTaskRunner
;
19 PrefMemberBase::PrefMemberBase()
21 setting_value_(false) {
24 PrefMemberBase::~PrefMemberBase() {
28 void PrefMemberBase::Init(const std::string
& pref_name
,
30 const NamedChangeCallback
& observer
) {
32 Init(pref_name
, prefs
);
35 void PrefMemberBase::Init(const std::string
& pref_name
, PrefService
* prefs
) {
37 DCHECK(pref_name_
.empty()); // Check that Init is only called once.
39 pref_name_
= pref_name
;
40 // Check that the preference is registered.
41 DCHECK(prefs_
->FindPreference(pref_name_
)) << pref_name
<< " not registered.";
43 // Add ourselves as a pref observer so we can keep our local value in sync.
44 prefs_
->AddPrefObserver(pref_name
, this);
47 void PrefMemberBase::Destroy() {
48 if (prefs_
&& !pref_name_
.empty()) {
49 prefs_
->RemovePrefObserver(pref_name_
, this);
54 void PrefMemberBase::MoveToThread(
55 const scoped_refptr
<SingleThreadTaskRunner
>& task_runner
) {
56 VerifyValuePrefName();
57 // Load the value from preferences if it hasn't been loaded so far.
59 UpdateValueFromPref(base::Closure());
60 internal()->MoveToThread(task_runner
);
63 void PrefMemberBase::OnPreferenceChanged(PrefService
* service
,
64 const std::string
& pref_name
) {
65 VerifyValuePrefName();
66 UpdateValueFromPref((!setting_value_
&& !observer_
.is_null()) ?
67 base::Bind(observer_
, pref_name
) : base::Closure());
70 void PrefMemberBase::UpdateValueFromPref(const base::Closure
& callback
) const {
71 VerifyValuePrefName();
72 const PrefService::Preference
* pref
= prefs_
->FindPreference(pref_name_
);
76 internal()->UpdateValue(pref
->GetValue()->DeepCopy(),
78 pref
->IsUserModifiable(),
82 void PrefMemberBase::VerifyPref() const {
83 VerifyValuePrefName();
85 UpdateValueFromPref(base::Closure());
88 void PrefMemberBase::InvokeUnnamedCallback(const base::Closure
& callback
,
89 const std::string
& pref_name
) {
93 PrefMemberBase::Internal::Internal()
94 : thread_loop_(MessageLoopProxy::current()),
96 is_user_modifiable_(false) {
98 PrefMemberBase::Internal::~Internal() { }
100 bool PrefMemberBase::Internal::IsOnCorrectThread() const {
101 // In unit tests, there may not be a message loop.
102 return thread_loop_
.get() == NULL
|| thread_loop_
->BelongsToCurrentThread();
105 void PrefMemberBase::Internal::UpdateValue(
108 bool is_user_modifiable
,
109 const base::Closure
& callback
) const {
110 scoped_ptr
<base::Value
> value(v
);
111 base::ScopedClosureRunner
closure_runner(callback
);
112 if (IsOnCorrectThread()) {
113 bool rv
= UpdateValueInternal(*value
);
115 is_managed_
= is_managed
;
116 is_user_modifiable_
= is_user_modifiable
;
118 bool may_run
= thread_loop_
->PostTask(
120 base::Bind(&PrefMemberBase::Internal::UpdateValue
, this,
121 value
.release(), is_managed
, is_user_modifiable
,
122 closure_runner
.Release()));
127 void PrefMemberBase::Internal::MoveToThread(
128 const scoped_refptr
<SingleThreadTaskRunner
>& task_runner
) {
129 CheckOnCorrectThread();
130 thread_loop_
= task_runner
;
133 bool PrefMemberVectorStringUpdate(const base::Value
& value
,
134 std::vector
<std::string
>* string_vector
) {
135 if (!value
.IsType(base::Value::TYPE_LIST
))
137 const base::ListValue
* list
= static_cast<const base::ListValue
*>(&value
);
139 std::vector
<std::string
> local_vector
;
140 for (base::ListValue::const_iterator it
= list
->begin();
141 it
!= list
->end(); ++it
) {
142 std::string string_value
;
143 if (!(*it
)->GetAsString(&string_value
))
146 local_vector
.push_back(string_value
);
149 string_vector
->swap(local_vector
);
153 } // namespace subtle
156 void PrefMember
<bool>::UpdatePref(const bool& value
) {
157 prefs()->SetBoolean(pref_name(), value
);
161 bool PrefMember
<bool>::Internal::UpdateValueInternal(
162 const base::Value
& value
) const {
163 return value
.GetAsBoolean(&value_
);
167 void PrefMember
<int>::UpdatePref(const int& value
) {
168 prefs()->SetInteger(pref_name(), value
);
172 bool PrefMember
<int>::Internal::UpdateValueInternal(
173 const base::Value
& value
) const {
174 return value
.GetAsInteger(&value_
);
178 void PrefMember
<double>::UpdatePref(const double& value
) {
179 prefs()->SetDouble(pref_name(), value
);
183 bool PrefMember
<double>::Internal::UpdateValueInternal(const base::Value
& value
)
185 return value
.GetAsDouble(&value_
);
189 void PrefMember
<std::string
>::UpdatePref(const std::string
& value
) {
190 prefs()->SetString(pref_name(), value
);
194 bool PrefMember
<std::string
>::Internal::UpdateValueInternal(
195 const base::Value
& value
)
197 return value
.GetAsString(&value_
);
201 void PrefMember
<base::FilePath
>::UpdatePref(const base::FilePath
& value
) {
202 prefs()->SetFilePath(pref_name(), value
);
206 bool PrefMember
<base::FilePath
>::Internal::UpdateValueInternal(
207 const base::Value
& value
)
209 return base::GetValueAsFilePath(value
, &value_
);
213 void PrefMember
<std::vector
<std::string
> >::UpdatePref(
214 const std::vector
<std::string
>& value
) {
215 base::ListValue list_value
;
216 list_value
.AppendStrings(value
);
217 prefs()->Set(pref_name(), list_value
);
221 bool PrefMember
<std::vector
<std::string
> >::Internal::UpdateValueInternal(
222 const base::Value
& value
) const {
223 return subtle::PrefMemberVectorStringUpdate(value
, &value_
);