OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/prefs/pref_member.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/callback_helpers.h" | |
11 #include "base/location.h" | |
12 #include "base/prefs/pref_service.h" | |
13 #include "base/thread_task_runner_handle.h" | |
14 #include "base/value_conversions.h" | |
15 | |
16 using base::SingleThreadTaskRunner; | |
17 | |
18 namespace subtle { | |
19 | |
20 PrefMemberBase::PrefMemberBase() | |
21 : prefs_(NULL), | |
22 setting_value_(false) { | |
23 } | |
24 | |
25 PrefMemberBase::~PrefMemberBase() { | |
26 Destroy(); | |
27 } | |
28 | |
29 void PrefMemberBase::Init(const std::string& pref_name, | |
30 PrefService* prefs, | |
31 const NamedChangeCallback& observer) { | |
32 observer_ = observer; | |
33 Init(pref_name, prefs); | |
34 } | |
35 | |
36 void PrefMemberBase::Init(const std::string& pref_name, PrefService* prefs) { | |
37 DCHECK(prefs); | |
38 DCHECK(pref_name_.empty()); // Check that Init is only called once. | |
39 prefs_ = prefs; | |
40 pref_name_ = pref_name; | |
41 // Check that the preference is registered. | |
42 DCHECK(prefs_->FindPreference(pref_name_)) << pref_name << " not registered."; | |
43 | |
44 // Add ourselves as a pref observer so we can keep our local value in sync. | |
45 prefs_->AddPrefObserver(pref_name, this); | |
46 } | |
47 | |
48 void PrefMemberBase::Destroy() { | |
49 if (prefs_ && !pref_name_.empty()) { | |
50 prefs_->RemovePrefObserver(pref_name_, this); | |
51 prefs_ = NULL; | |
52 } | |
53 } | |
54 | |
55 void PrefMemberBase::MoveToThread( | |
56 scoped_refptr<SingleThreadTaskRunner> task_runner) { | |
57 VerifyValuePrefName(); | |
58 // Load the value from preferences if it hasn't been loaded so far. | |
59 if (!internal()) | |
60 UpdateValueFromPref(base::Closure()); | |
61 internal()->MoveToThread(std::move(task_runner)); | |
62 } | |
63 | |
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()); | |
69 } | |
70 | |
71 void PrefMemberBase::UpdateValueFromPref(const base::Closure& callback) const { | |
72 VerifyValuePrefName(); | |
73 const PrefService::Preference* pref = prefs_->FindPreference(pref_name_); | |
74 DCHECK(pref); | |
75 if (!internal()) | |
76 CreateInternal(); | |
77 internal()->UpdateValue(pref->GetValue()->DeepCopy(), | |
78 pref->IsManaged(), | |
79 pref->IsUserModifiable(), | |
80 callback); | |
81 } | |
82 | |
83 void PrefMemberBase::VerifyPref() const { | |
84 VerifyValuePrefName(); | |
85 if (!internal()) | |
86 UpdateValueFromPref(base::Closure()); | |
87 } | |
88 | |
89 void PrefMemberBase::InvokeUnnamedCallback(const base::Closure& callback, | |
90 const std::string& pref_name) { | |
91 callback.Run(); | |
92 } | |
93 | |
94 PrefMemberBase::Internal::Internal() | |
95 : thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
96 is_managed_(false), | |
97 is_user_modifiable_(false) { | |
98 } | |
99 PrefMemberBase::Internal::~Internal() { } | |
100 | |
101 bool PrefMemberBase::Internal::IsOnCorrectThread() const { | |
102 return thread_task_runner_->BelongsToCurrentThread(); | |
103 } | |
104 | |
105 void PrefMemberBase::Internal::UpdateValue( | |
106 base::Value* v, | |
107 bool is_managed, | |
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); | |
114 DCHECK(rv); | |
115 is_managed_ = is_managed; | |
116 is_user_modifiable_ = is_user_modifiable; | |
117 } else { | |
118 bool may_run = thread_task_runner_->PostTask( | |
119 FROM_HERE, base::Bind(&PrefMemberBase::Internal::UpdateValue, this, | |
120 value.release(), is_managed, is_user_modifiable, | |
121 closure_runner.Release())); | |
122 DCHECK(may_run); | |
123 } | |
124 } | |
125 | |
126 void PrefMemberBase::Internal::MoveToThread( | |
127 scoped_refptr<SingleThreadTaskRunner> task_runner) { | |
128 CheckOnCorrectThread(); | |
129 thread_task_runner_ = std::move(task_runner); | |
130 } | |
131 | |
132 bool PrefMemberVectorStringUpdate(const base::Value& value, | |
133 std::vector<std::string>* string_vector) { | |
134 if (!value.IsType(base::Value::TYPE_LIST)) | |
135 return false; | |
136 const base::ListValue* list = static_cast<const base::ListValue*>(&value); | |
137 | |
138 std::vector<std::string> local_vector; | |
139 for (base::ListValue::const_iterator it = list->begin(); | |
140 it != list->end(); ++it) { | |
141 std::string string_value; | |
142 if (!(*it)->GetAsString(&string_value)) | |
143 return false; | |
144 | |
145 local_vector.push_back(string_value); | |
146 } | |
147 | |
148 string_vector->swap(local_vector); | |
149 return true; | |
150 } | |
151 | |
152 } // namespace subtle | |
153 | |
154 template <> | |
155 void PrefMember<bool>::UpdatePref(const bool& value) { | |
156 prefs()->SetBoolean(pref_name(), value); | |
157 } | |
158 | |
159 template <> | |
160 bool PrefMember<bool>::Internal::UpdateValueInternal( | |
161 const base::Value& value) const { | |
162 return value.GetAsBoolean(&value_); | |
163 } | |
164 | |
165 template <> | |
166 void PrefMember<int>::UpdatePref(const int& value) { | |
167 prefs()->SetInteger(pref_name(), value); | |
168 } | |
169 | |
170 template <> | |
171 bool PrefMember<int>::Internal::UpdateValueInternal( | |
172 const base::Value& value) const { | |
173 return value.GetAsInteger(&value_); | |
174 } | |
175 | |
176 template <> | |
177 void PrefMember<double>::UpdatePref(const double& value) { | |
178 prefs()->SetDouble(pref_name(), value); | |
179 } | |
180 | |
181 template <> | |
182 bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value) | |
183 const { | |
184 return value.GetAsDouble(&value_); | |
185 } | |
186 | |
187 template <> | |
188 void PrefMember<std::string>::UpdatePref(const std::string& value) { | |
189 prefs()->SetString(pref_name(), value); | |
190 } | |
191 | |
192 template <> | |
193 bool PrefMember<std::string>::Internal::UpdateValueInternal( | |
194 const base::Value& value) | |
195 const { | |
196 return value.GetAsString(&value_); | |
197 } | |
198 | |
199 template <> | |
200 void PrefMember<base::FilePath>::UpdatePref(const base::FilePath& value) { | |
201 prefs()->SetFilePath(pref_name(), value); | |
202 } | |
203 | |
204 template <> | |
205 bool PrefMember<base::FilePath>::Internal::UpdateValueInternal( | |
206 const base::Value& value) | |
207 const { | |
208 return base::GetValueAsFilePath(value, &value_); | |
209 } | |
210 | |
211 template <> | |
212 void PrefMember<std::vector<std::string> >::UpdatePref( | |
213 const std::vector<std::string>& value) { | |
214 base::ListValue list_value; | |
215 list_value.AppendStrings(value); | |
216 prefs()->Set(pref_name(), list_value); | |
217 } | |
218 | |
219 template <> | |
220 bool PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal( | |
221 const base::Value& value) const { | |
222 return subtle::PrefMemberVectorStringUpdate(value, &value_); | |
223 } | |
OLD | NEW |