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 char* pref_name
,
30 const NamedChangeCallback
& observer
) {
32 Init(pref_name
, prefs
);
35 void PrefMemberBase::Init(const char* pref_name
,
39 DCHECK(pref_name_
.empty()); // Check that Init is only called once.
41 pref_name_
= pref_name
;
42 // Check that the preference is registered.
43 DCHECK(prefs_
->FindPreference(pref_name_
.c_str()))
44 << pref_name
<< " not registered.";
46 // Add ourselves as a pref observer so we can keep our local value in sync.
47 prefs_
->AddPrefObserver(pref_name
, this);
50 void PrefMemberBase::Destroy() {
51 if (prefs_
&& !pref_name_
.empty()) {
52 prefs_
->RemovePrefObserver(pref_name_
.c_str(), this);
57 void PrefMemberBase::MoveToThread(
58 const scoped_refptr
<SingleThreadTaskRunner
>& task_runner
) {
59 VerifyValuePrefName();
60 // Load the value from preferences if it hasn't been loaded so far.
62 UpdateValueFromPref(base::Closure());
63 internal()->MoveToThread(task_runner
);
66 void PrefMemberBase::OnPreferenceChanged(PrefService
* service
,
67 const std::string
& pref_name
) {
68 VerifyValuePrefName();
69 UpdateValueFromPref((!setting_value_
&& !observer_
.is_null()) ?
70 base::Bind(observer_
, pref_name
) : base::Closure());
73 void PrefMemberBase::UpdateValueFromPref(const base::Closure
& callback
) const {
74 VerifyValuePrefName();
75 const PrefService::Preference
* pref
=
76 prefs_
->FindPreference(pref_name_
.c_str());
80 internal()->UpdateValue(pref
->GetValue()->DeepCopy(),
82 pref
->IsUserModifiable(),
86 void PrefMemberBase::VerifyPref() const {
87 VerifyValuePrefName();
89 UpdateValueFromPref(base::Closure());
92 void PrefMemberBase::InvokeUnnamedCallback(const base::Closure
& callback
,
93 const std::string
& pref_name
) {
97 PrefMemberBase::Internal::Internal()
98 : thread_loop_(MessageLoopProxy::current()),
100 is_user_modifiable_(false) {
102 PrefMemberBase::Internal::~Internal() { }
104 bool PrefMemberBase::Internal::IsOnCorrectThread() const {
105 // In unit tests, there may not be a message loop.
106 return thread_loop_
.get() == NULL
|| thread_loop_
->BelongsToCurrentThread();
109 void PrefMemberBase::Internal::UpdateValue(
112 bool is_user_modifiable
,
113 const base::Closure
& callback
) const {
114 scoped_ptr
<base::Value
> value(v
);
115 base::ScopedClosureRunner
closure_runner(callback
);
116 if (IsOnCorrectThread()) {
117 bool rv
= UpdateValueInternal(*value
);
119 is_managed_
= is_managed
;
120 is_user_modifiable_
= is_user_modifiable
;
122 bool may_run
= thread_loop_
->PostTask(
124 base::Bind(&PrefMemberBase::Internal::UpdateValue
, this,
125 value
.release(), is_managed
, is_user_modifiable
,
126 closure_runner
.Release()));
131 void PrefMemberBase::Internal::MoveToThread(
132 const scoped_refptr
<SingleThreadTaskRunner
>& task_runner
) {
133 CheckOnCorrectThread();
134 thread_loop_
= task_runner
;
137 bool PrefMemberVectorStringUpdate(const base::Value
& value
,
138 std::vector
<std::string
>* string_vector
) {
139 if (!value
.IsType(base::Value::TYPE_LIST
))
141 const base::ListValue
* list
= static_cast<const base::ListValue
*>(&value
);
143 std::vector
<std::string
> local_vector
;
144 for (base::ListValue::const_iterator it
= list
->begin();
145 it
!= list
->end(); ++it
) {
146 std::string string_value
;
147 if (!(*it
)->GetAsString(&string_value
))
150 local_vector
.push_back(string_value
);
153 string_vector
->swap(local_vector
);
157 } // namespace subtle
160 void PrefMember
<bool>::UpdatePref(const bool& value
) {
161 prefs()->SetBoolean(pref_name().c_str(), value
);
165 bool PrefMember
<bool>::Internal::UpdateValueInternal(
166 const base::Value
& value
) const {
167 return value
.GetAsBoolean(&value_
);
171 void PrefMember
<int>::UpdatePref(const int& value
) {
172 prefs()->SetInteger(pref_name().c_str(), value
);
176 bool PrefMember
<int>::Internal::UpdateValueInternal(
177 const base::Value
& value
) const {
178 return value
.GetAsInteger(&value_
);
182 void PrefMember
<double>::UpdatePref(const double& value
) {
183 prefs()->SetDouble(pref_name().c_str(), value
);
187 bool PrefMember
<double>::Internal::UpdateValueInternal(const base::Value
& value
)
189 return value
.GetAsDouble(&value_
);
193 void PrefMember
<std::string
>::UpdatePref(const std::string
& value
) {
194 prefs()->SetString(pref_name().c_str(), value
);
198 bool PrefMember
<std::string
>::Internal::UpdateValueInternal(
199 const base::Value
& value
)
201 return value
.GetAsString(&value_
);
205 void PrefMember
<base::FilePath
>::UpdatePref(const base::FilePath
& value
) {
206 prefs()->SetFilePath(pref_name().c_str(), value
);
210 bool PrefMember
<base::FilePath
>::Internal::UpdateValueInternal(
211 const base::Value
& value
)
213 return base::GetValueAsFilePath(value
, &value_
);
217 void PrefMember
<std::vector
<std::string
> >::UpdatePref(
218 const std::vector
<std::string
>& value
) {
219 base::ListValue list_value
;
220 list_value
.AppendStrings(value
);
221 prefs()->Set(pref_name().c_str(), list_value
);
225 bool PrefMember
<std::vector
<std::string
> >::Internal::UpdateValueInternal(
226 const base::Value
& value
) const {
227 return subtle::PrefMemberVectorStringUpdate(value
, &value_
);