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/bind_helpers.h"
8 #include "base/callback.h"
9 #include "base/location.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/value_conversions.h"
13 using base::MessageLoopProxy
;
17 PrefMemberBase::PrefMemberBase()
19 setting_value_(false) {
22 PrefMemberBase::~PrefMemberBase() {
26 void PrefMemberBase::Init(const char* pref_name
,
28 const NamedChangeCallback
& observer
) {
30 Init(pref_name
, prefs
);
33 void PrefMemberBase::Init(const char* pref_name
,
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_
.c_str()))
42 << pref_name
<< " not registered.";
44 // Add ourselves as a pref observer so we can keep our local value in sync.
45 prefs_
->AddPrefObserver(pref_name
, this);
48 void PrefMemberBase::Destroy() {
49 if (prefs_
&& !pref_name_
.empty()) {
50 prefs_
->RemovePrefObserver(pref_name_
.c_str(), this);
55 void PrefMemberBase::MoveToThread(
56 const scoped_refptr
<MessageLoopProxy
>& message_loop
) {
57 VerifyValuePrefName();
58 // Load the value from preferences if it hasn't been loaded so far.
60 UpdateValueFromPref(base::Closure());
61 internal()->MoveToThread(message_loop
);
64 void PrefMemberBase::OnPreferenceChanged(PrefService
* service
,
65 const std::string
& pref_name
) {
66 VerifyValuePrefName();
67 UpdateValueFromPref((!setting_value_
&& !observer_
.is_null()) ?
68 base::Bind(observer_
, pref_name
) : base::Closure());
71 void PrefMemberBase::UpdateValueFromPref(const base::Closure
& callback
) const {
72 VerifyValuePrefName();
73 const PrefService::Preference
* pref
=
74 prefs_
->FindPreference(pref_name_
.c_str());
78 internal()->UpdateValue(pref
->GetValue()->DeepCopy(),
80 pref
->IsUserModifiable(),
84 void PrefMemberBase::VerifyPref() const {
85 VerifyValuePrefName();
87 UpdateValueFromPref(base::Closure());
90 void PrefMemberBase::InvokeUnnamedCallback(const base::Closure
& callback
,
91 const std::string
& pref_name
) {
95 PrefMemberBase::Internal::Internal()
96 : thread_loop_(MessageLoopProxy::current()),
99 PrefMemberBase::Internal::~Internal() { }
101 bool PrefMemberBase::Internal::IsOnCorrectThread() const {
102 // In unit tests, there may not be a message loop.
103 return thread_loop_
== NULL
|| thread_loop_
->BelongsToCurrentThread();
106 void PrefMemberBase::Internal::UpdateValue(
109 bool is_user_modifiable
,
110 const base::Closure
& callback
) const {
111 scoped_ptr
<base::Value
> value(v
);
112 base::ScopedClosureRunner
closure_runner(callback
);
113 if (IsOnCorrectThread()) {
114 bool rv
= UpdateValueInternal(*value
);
116 is_managed_
= is_managed
;
117 is_user_modifiable_
= is_user_modifiable
;
119 bool may_run
= thread_loop_
->PostTask(
121 base::Bind(&PrefMemberBase::Internal::UpdateValue
, this,
122 value
.release(), is_managed
, is_user_modifiable
,
123 closure_runner
.Release()));
128 void PrefMemberBase::Internal::MoveToThread(
129 const scoped_refptr
<MessageLoopProxy
>& message_loop
) {
130 CheckOnCorrectThread();
131 thread_loop_
= message_loop
;
134 bool PrefMemberVectorStringUpdate(const base::Value
& value
,
135 std::vector
<std::string
>* string_vector
) {
136 if (!value
.IsType(base::Value::TYPE_LIST
))
138 const ListValue
* list
= static_cast<const ListValue
*>(&value
);
140 std::vector
<std::string
> local_vector
;
141 for (ListValue::const_iterator it
= list
->begin(); 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().c_str(), 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().c_str(), 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().c_str(), 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().c_str(), 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().c_str(), 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 ListValue list_value
;
216 list_value
.AppendStrings(value
);
217 prefs()->Set(pref_name().c_str(), list_value
);
221 bool PrefMember
<std::vector
<std::string
> >::Internal::UpdateValueInternal(
222 const base::Value
& value
) const {
223 return subtle::PrefMemberVectorStringUpdate(value
, &value_
);