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/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()),
98 is_user_modifiable_(false) {
100 PrefMemberBase::Internal::~Internal() { }
102 bool PrefMemberBase::Internal::IsOnCorrectThread() const {
103 // In unit tests, there may not be a message loop.
104 return thread_loop_
.get() == NULL
|| thread_loop_
->BelongsToCurrentThread();
107 void PrefMemberBase::Internal::UpdateValue(
110 bool is_user_modifiable
,
111 const base::Closure
& callback
) const {
112 scoped_ptr
<base::Value
> value(v
);
113 base::ScopedClosureRunner
closure_runner(callback
);
114 if (IsOnCorrectThread()) {
115 bool rv
= UpdateValueInternal(*value
);
117 is_managed_
= is_managed
;
118 is_user_modifiable_
= is_user_modifiable
;
120 bool may_run
= thread_loop_
->PostTask(
122 base::Bind(&PrefMemberBase::Internal::UpdateValue
, this,
123 value
.release(), is_managed
, is_user_modifiable
,
124 closure_runner
.Release()));
129 void PrefMemberBase::Internal::MoveToThread(
130 const scoped_refptr
<MessageLoopProxy
>& message_loop
) {
131 CheckOnCorrectThread();
132 thread_loop_
= message_loop
;
135 bool PrefMemberVectorStringUpdate(const base::Value
& value
,
136 std::vector
<std::string
>* string_vector
) {
137 if (!value
.IsType(base::Value::TYPE_LIST
))
139 const base::ListValue
* list
= static_cast<const base::ListValue
*>(&value
);
141 std::vector
<std::string
> local_vector
;
142 for (base::ListValue::const_iterator it
= list
->begin();
143 it
!= list
->end(); ++it
) {
144 std::string string_value
;
145 if (!(*it
)->GetAsString(&string_value
))
148 local_vector
.push_back(string_value
);
151 string_vector
->swap(local_vector
);
155 } // namespace subtle
158 void PrefMember
<bool>::UpdatePref(const bool& value
) {
159 prefs()->SetBoolean(pref_name().c_str(), value
);
163 bool PrefMember
<bool>::Internal::UpdateValueInternal(
164 const base::Value
& value
) const {
165 return value
.GetAsBoolean(&value_
);
169 void PrefMember
<int>::UpdatePref(const int& value
) {
170 prefs()->SetInteger(pref_name().c_str(), value
);
174 bool PrefMember
<int>::Internal::UpdateValueInternal(
175 const base::Value
& value
) const {
176 return value
.GetAsInteger(&value_
);
180 void PrefMember
<double>::UpdatePref(const double& value
) {
181 prefs()->SetDouble(pref_name().c_str(), value
);
185 bool PrefMember
<double>::Internal::UpdateValueInternal(const base::Value
& value
)
187 return value
.GetAsDouble(&value_
);
191 void PrefMember
<std::string
>::UpdatePref(const std::string
& value
) {
192 prefs()->SetString(pref_name().c_str(), value
);
196 bool PrefMember
<std::string
>::Internal::UpdateValueInternal(
197 const base::Value
& value
)
199 return value
.GetAsString(&value_
);
203 void PrefMember
<base::FilePath
>::UpdatePref(const base::FilePath
& value
) {
204 prefs()->SetFilePath(pref_name().c_str(), value
);
208 bool PrefMember
<base::FilePath
>::Internal::UpdateValueInternal(
209 const base::Value
& value
)
211 return base::GetValueAsFilePath(value
, &value_
);
215 void PrefMember
<std::vector
<std::string
> >::UpdatePref(
216 const std::vector
<std::string
>& value
) {
217 base::ListValue list_value
;
218 list_value
.AppendStrings(value
);
219 prefs()->Set(pref_name().c_str(), list_value
);
223 bool PrefMember
<std::vector
<std::string
> >::Internal::UpdateValueInternal(
224 const base::Value
& value
) const {
225 return subtle::PrefMemberVectorStringUpdate(value
, &value_
);