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