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