pref_member.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. #include "components/prefs/pref_member.h"
  5. #include <utility>
  6. #include "base/callback.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/json/values_util.h"
  9. #include "base/location.h"
  10. #include "base/threading/sequenced_task_runner_handle.h"
  11. #include "base/values.h"
  12. #include "components/prefs/pref_service.h"
  13. using base::SequencedTaskRunner;
  14. namespace subtle {
  15. PrefMemberBase::PrefMemberBase() : prefs_(nullptr), setting_value_(false) {}
  16. PrefMemberBase::~PrefMemberBase() {
  17. Destroy();
  18. }
  19. void PrefMemberBase::Init(const std::string& pref_name,
  20. PrefService* prefs,
  21. const NamedChangeCallback& observer) {
  22. observer_ = observer;
  23. Init(pref_name, prefs);
  24. }
  25. void PrefMemberBase::Init(const std::string& pref_name, PrefService* prefs) {
  26. DCHECK(prefs);
  27. DCHECK(pref_name_.empty()); // Check that Init is only called once.
  28. prefs_ = prefs;
  29. pref_name_ = pref_name;
  30. // Check that the preference is registered.
  31. DCHECK(prefs_->FindPreference(pref_name_)) << pref_name << " not registered.";
  32. // Add ourselves as a pref observer so we can keep our local value in sync.
  33. prefs_->AddPrefObserver(pref_name, this);
  34. }
  35. void PrefMemberBase::Destroy() {
  36. if (prefs_ && !pref_name_.empty()) {
  37. prefs_->RemovePrefObserver(pref_name_, this);
  38. prefs_ = nullptr;
  39. }
  40. }
  41. void PrefMemberBase::MoveToSequence(
  42. scoped_refptr<SequencedTaskRunner> task_runner) {
  43. VerifyValuePrefName();
  44. // Load the value from preferences if it hasn't been loaded so far.
  45. if (!internal())
  46. UpdateValueFromPref(base::OnceClosure());
  47. internal()->MoveToSequence(std::move(task_runner));
  48. }
  49. void PrefMemberBase::OnPreferenceChanged(PrefService* service,
  50. const std::string& pref_name) {
  51. VerifyValuePrefName();
  52. UpdateValueFromPref((!setting_value_ && !observer_.is_null())
  53. ? base::BindOnce(observer_, pref_name)
  54. : base::OnceClosure());
  55. }
  56. void PrefMemberBase::UpdateValueFromPref(base::OnceClosure callback) const {
  57. VerifyValuePrefName();
  58. const PrefService::Preference* pref = prefs_->FindPreference(pref_name_);
  59. DCHECK(pref);
  60. if (!internal())
  61. CreateInternal();
  62. internal()->UpdateValue(
  63. base::Value::ToUniquePtrValue(pref->GetValue()->Clone()).release(),
  64. pref->IsManaged(), pref->IsUserModifiable(), pref->IsDefaultValue(),
  65. std::move(callback));
  66. }
  67. void PrefMemberBase::VerifyPref() const {
  68. VerifyValuePrefName();
  69. if (!internal())
  70. UpdateValueFromPref(base::OnceClosure());
  71. }
  72. void PrefMemberBase::InvokeUnnamedCallback(
  73. const base::RepeatingClosure& callback,
  74. const std::string& pref_name) {
  75. callback.Run();
  76. }
  77. PrefMemberBase::Internal::Internal()
  78. : owning_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
  79. PrefMemberBase::Internal::~Internal() = default;
  80. bool PrefMemberBase::Internal::IsOnCorrectSequence() const {
  81. return owning_task_runner_->RunsTasksInCurrentSequence();
  82. }
  83. void PrefMemberBase::Internal::UpdateValue(base::Value* v,
  84. bool is_managed,
  85. bool is_user_modifiable,
  86. bool is_default_value,
  87. base::OnceClosure callback) const {
  88. std::unique_ptr<base::Value> value(v);
  89. base::ScopedClosureRunner closure_runner(std::move(callback));
  90. if (IsOnCorrectSequence()) {
  91. bool rv = UpdateValueInternal(*value);
  92. DCHECK(rv);
  93. is_managed_ = is_managed;
  94. is_user_modifiable_ = is_user_modifiable;
  95. is_default_value_ = is_default_value;
  96. } else {
  97. bool may_run = owning_task_runner_->PostTask(
  98. FROM_HERE,
  99. base::BindOnce(&PrefMemberBase::Internal::UpdateValue, this,
  100. value.release(), is_managed, is_user_modifiable,
  101. is_default_value, closure_runner.Release()));
  102. DCHECK(may_run);
  103. }
  104. }
  105. void PrefMemberBase::Internal::MoveToSequence(
  106. scoped_refptr<SequencedTaskRunner> task_runner) {
  107. CheckOnCorrectSequence();
  108. owning_task_runner_ = std::move(task_runner);
  109. }
  110. bool PrefMemberVectorStringUpdate(const base::Value& value,
  111. std::vector<std::string>* string_vector) {
  112. if (!value.is_list())
  113. return false;
  114. std::vector<std::string> local_vector;
  115. for (const auto& item : value.GetListDeprecated()) {
  116. if (!item.is_string())
  117. return false;
  118. local_vector.push_back(item.GetString());
  119. }
  120. string_vector->swap(local_vector);
  121. return true;
  122. }
  123. } // namespace subtle
  124. template <>
  125. void PrefMember<bool>::UpdatePref(const bool& value) {
  126. prefs()->SetBoolean(pref_name(), value);
  127. }
  128. template <>
  129. bool PrefMember<bool>::Internal::UpdateValueInternal(
  130. const base::Value& value) const {
  131. if (value.is_bool())
  132. value_ = value.GetBool();
  133. return value.is_bool();
  134. }
  135. template <>
  136. void PrefMember<int>::UpdatePref(const int& value) {
  137. prefs()->SetInteger(pref_name(), value);
  138. }
  139. template <>
  140. bool PrefMember<int>::Internal::UpdateValueInternal(
  141. const base::Value& value) const {
  142. if (value.is_int())
  143. value_ = value.GetInt();
  144. return value.is_int();
  145. }
  146. template <>
  147. void PrefMember<double>::UpdatePref(const double& value) {
  148. prefs()->SetDouble(pref_name(), value);
  149. }
  150. template <>
  151. bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value)
  152. const {
  153. if (value.is_double() || value.is_int())
  154. value_ = value.GetDouble();
  155. return value.is_double() || value.is_int();
  156. }
  157. template <>
  158. void PrefMember<std::string>::UpdatePref(const std::string& value) {
  159. prefs()->SetString(pref_name(), value);
  160. }
  161. template <>
  162. bool PrefMember<std::string>::Internal::UpdateValueInternal(
  163. const base::Value& value)
  164. const {
  165. if (value.is_string())
  166. value_ = value.GetString();
  167. return value.is_string();
  168. }
  169. template <>
  170. void PrefMember<base::FilePath>::UpdatePref(const base::FilePath& value) {
  171. prefs()->SetFilePath(pref_name(), value);
  172. }
  173. template <>
  174. bool PrefMember<base::FilePath>::Internal::UpdateValueInternal(
  175. const base::Value& value)
  176. const {
  177. absl::optional<base::FilePath> path = base::ValueToFilePath(value);
  178. if (!path)
  179. return false;
  180. value_ = *path;
  181. return true;
  182. }
  183. template <>
  184. void PrefMember<std::vector<std::string> >::UpdatePref(
  185. const std::vector<std::string>& value) {
  186. base::ListValue list_value;
  187. for (const std::string& val : value)
  188. list_value.Append(val);
  189. prefs()->Set(pref_name(), list_value);
  190. }
  191. template <>
  192. bool PrefMember<std::vector<std::string> >::Internal::UpdateValueInternal(
  193. const base::Value& value) const {
  194. return subtle::PrefMemberVectorStringUpdate(value, &value_);
  195. }