overlay_user_pref_store.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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/overlay_user_pref_store.h"
  5. #include <memory>
  6. #include <ostream>
  7. #include <utility>
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/observer_list.h"
  11. #include "base/values.h"
  12. #include "components/prefs/in_memory_pref_store.h"
  13. // Allows us to monitor two pref stores and tell updates from them apart. It
  14. // essentially mimics a Callback for the Observer interface (e.g. it allows
  15. // binding additional arguments).
  16. class OverlayUserPrefStore::ObserverAdapter : public PrefStore::Observer {
  17. public:
  18. ObserverAdapter(bool ephemeral, OverlayUserPrefStore* parent)
  19. : ephemeral_user_pref_store_(ephemeral), parent_(parent) {}
  20. // Methods of PrefStore::Observer.
  21. void OnPrefValueChanged(const std::string& key) override {
  22. parent_->OnPrefValueChanged(ephemeral_user_pref_store_, key);
  23. }
  24. void OnInitializationCompleted(bool succeeded) override {
  25. parent_->OnInitializationCompleted(ephemeral_user_pref_store_, succeeded);
  26. }
  27. private:
  28. // Is the update for the ephemeral?
  29. const bool ephemeral_user_pref_store_;
  30. const raw_ptr<OverlayUserPrefStore> parent_;
  31. };
  32. OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* persistent)
  33. : OverlayUserPrefStore(new InMemoryPrefStore(), persistent) {}
  34. OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* ephemeral,
  35. PersistentPrefStore* persistent)
  36. : ephemeral_pref_store_observer_(
  37. std::make_unique<OverlayUserPrefStore::ObserverAdapter>(true, this)),
  38. persistent_pref_store_observer_(
  39. std::make_unique<OverlayUserPrefStore::ObserverAdapter>(false, this)),
  40. ephemeral_user_pref_store_(ephemeral),
  41. persistent_user_pref_store_(persistent) {
  42. DCHECK(ephemeral->IsInitializationComplete());
  43. ephemeral_user_pref_store_->AddObserver(ephemeral_pref_store_observer_.get());
  44. persistent_user_pref_store_->AddObserver(
  45. persistent_pref_store_observer_.get());
  46. }
  47. bool OverlayUserPrefStore::IsSetInOverlay(const std::string& key) const {
  48. return ephemeral_user_pref_store_->GetValue(key, nullptr);
  49. }
  50. void OverlayUserPrefStore::AddObserver(PrefStore::Observer* observer) {
  51. observers_.AddObserver(observer);
  52. }
  53. void OverlayUserPrefStore::RemoveObserver(PrefStore::Observer* observer) {
  54. observers_.RemoveObserver(observer);
  55. }
  56. bool OverlayUserPrefStore::HasObservers() const {
  57. return !observers_.empty();
  58. }
  59. bool OverlayUserPrefStore::IsInitializationComplete() const {
  60. return persistent_user_pref_store_->IsInitializationComplete() &&
  61. ephemeral_user_pref_store_->IsInitializationComplete();
  62. }
  63. bool OverlayUserPrefStore::GetValue(const std::string& key,
  64. const base::Value** result) const {
  65. // If the |key| shall NOT be stored in the ephemeral store, there must not
  66. // be an entry.
  67. DCHECK(!ShallBeStoredInPersistent(key) ||
  68. !ephemeral_user_pref_store_->GetValue(key, nullptr));
  69. if (ephemeral_user_pref_store_->GetValue(key, result))
  70. return true;
  71. return persistent_user_pref_store_->GetValue(key, result);
  72. }
  73. base::Value::Dict OverlayUserPrefStore::GetValues() const {
  74. auto values = ephemeral_user_pref_store_->GetValues();
  75. auto persistent_values = persistent_user_pref_store_->GetValues();
  76. // Output |values| are read from |ephemeral_user_pref_store_| (in-memory
  77. // store). Then the values of preferences in |persistent_names_set_| are
  78. // overwritten by the content of |persistent_user_pref_store_| (the persistent
  79. // store).
  80. for (const auto& key : persistent_names_set_) {
  81. absl::optional<base::Value> out_value =
  82. persistent_values.ExtractByDottedPath(key);
  83. if (out_value.has_value()) {
  84. values.SetByDottedPath(key, std::move(*out_value));
  85. }
  86. }
  87. return values;
  88. }
  89. bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
  90. base::Value** result) {
  91. if (ShallBeStoredInPersistent(key))
  92. return persistent_user_pref_store_->GetMutableValue(key, result);
  93. written_ephemeral_names_.insert(key);
  94. if (ephemeral_user_pref_store_->GetMutableValue(key, result))
  95. return true;
  96. // Try to create copy of persistent if the ephemeral does not contain a value.
  97. base::Value* persistent_value = nullptr;
  98. if (!persistent_user_pref_store_->GetMutableValue(key, &persistent_value))
  99. return false;
  100. ephemeral_user_pref_store_->SetValue(
  101. key, base::Value::ToUniquePtrValue(persistent_value->Clone()),
  102. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  103. ephemeral_user_pref_store_->GetMutableValue(key, result);
  104. return true;
  105. }
  106. void OverlayUserPrefStore::SetValue(const std::string& key,
  107. std::unique_ptr<base::Value> value,
  108. uint32_t flags) {
  109. if (ShallBeStoredInPersistent(key)) {
  110. persistent_user_pref_store_->SetValue(key, std::move(value), flags);
  111. return;
  112. }
  113. // TODO(https://crbug.com/861722): If we always store in in-memory storage
  114. // and conditionally also stored in persistent one, we wouldn't have to do a
  115. // complex merge in GetValues().
  116. written_ephemeral_names_.insert(key);
  117. ephemeral_user_pref_store_->SetValue(key, std::move(value), flags);
  118. }
  119. void OverlayUserPrefStore::SetValueSilently(const std::string& key,
  120. std::unique_ptr<base::Value> value,
  121. uint32_t flags) {
  122. if (ShallBeStoredInPersistent(key)) {
  123. persistent_user_pref_store_->SetValueSilently(key, std::move(value), flags);
  124. return;
  125. }
  126. written_ephemeral_names_.insert(key);
  127. ephemeral_user_pref_store_->SetValueSilently(key, std::move(value), flags);
  128. }
  129. void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
  130. if (ShallBeStoredInPersistent(key)) {
  131. persistent_user_pref_store_->RemoveValue(key, flags);
  132. return;
  133. }
  134. written_ephemeral_names_.insert(key);
  135. ephemeral_user_pref_store_->RemoveValue(key, flags);
  136. }
  137. void OverlayUserPrefStore::RemoveValuesByPrefixSilently(
  138. const std::string& prefix) {
  139. NOTIMPLEMENTED();
  140. }
  141. bool OverlayUserPrefStore::ReadOnly() const {
  142. return false;
  143. }
  144. PersistentPrefStore::PrefReadError OverlayUserPrefStore::GetReadError() const {
  145. return PersistentPrefStore::PREF_READ_ERROR_NONE;
  146. }
  147. PersistentPrefStore::PrefReadError OverlayUserPrefStore::ReadPrefs() {
  148. // We do not read intentionally.
  149. OnInitializationCompleted(/* ephemeral */ false, true);
  150. return PersistentPrefStore::PREF_READ_ERROR_NONE;
  151. }
  152. void OverlayUserPrefStore::ReadPrefsAsync(
  153. ReadErrorDelegate* error_delegate_raw) {
  154. std::unique_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
  155. // We do not read intentionally.
  156. OnInitializationCompleted(/* ephemeral */ false, true);
  157. }
  158. void OverlayUserPrefStore::CommitPendingWrite(
  159. base::OnceClosure reply_callback,
  160. base::OnceClosure synchronous_done_callback) {
  161. persistent_user_pref_store_->CommitPendingWrite(
  162. std::move(reply_callback), std::move(synchronous_done_callback));
  163. // We do not write our content intentionally.
  164. }
  165. void OverlayUserPrefStore::SchedulePendingLossyWrites() {
  166. persistent_user_pref_store_->SchedulePendingLossyWrites();
  167. }
  168. void OverlayUserPrefStore::ReportValueChanged(const std::string& key,
  169. uint32_t flags) {
  170. for (PrefStore::Observer& observer : observers_)
  171. observer.OnPrefValueChanged(key);
  172. }
  173. void OverlayUserPrefStore::RegisterPersistentPref(const std::string& key) {
  174. DCHECK(!key.empty()) << "Key is empty";
  175. DCHECK(persistent_names_set_.find(key) == persistent_names_set_.end())
  176. << "Key already registered: " << key;
  177. persistent_names_set_.insert(key);
  178. }
  179. void OverlayUserPrefStore::ClearMutableValues() {
  180. for (const auto& key : written_ephemeral_names_) {
  181. ephemeral_user_pref_store_->RemoveValue(
  182. key, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  183. }
  184. }
  185. void OverlayUserPrefStore::OnStoreDeletionFromDisk() {
  186. persistent_user_pref_store_->OnStoreDeletionFromDisk();
  187. }
  188. OverlayUserPrefStore::~OverlayUserPrefStore() {
  189. ephemeral_user_pref_store_->RemoveObserver(
  190. ephemeral_pref_store_observer_.get());
  191. persistent_user_pref_store_->RemoveObserver(
  192. persistent_pref_store_observer_.get());
  193. }
  194. void OverlayUserPrefStore::OnPrefValueChanged(bool ephemeral,
  195. const std::string& key) {
  196. if (ephemeral) {
  197. ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
  198. } else {
  199. if (!ephemeral_user_pref_store_->GetValue(key, nullptr))
  200. ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
  201. }
  202. }
  203. void OverlayUserPrefStore::OnInitializationCompleted(bool ephemeral,
  204. bool succeeded) {
  205. if (!IsInitializationComplete())
  206. return;
  207. for (PrefStore::Observer& observer : observers_)
  208. observer.OnInitializationCompleted(succeeded);
  209. }
  210. bool OverlayUserPrefStore::ShallBeStoredInPersistent(
  211. const std::string& key) const {
  212. return persistent_names_set_.find(key) != persistent_names_set_.end();
  213. }