123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/prefs/overlay_user_pref_store.h"
- #include <memory>
- #include <ostream>
- #include <utility>
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "base/observer_list.h"
- #include "base/values.h"
- #include "components/prefs/in_memory_pref_store.h"
- // Allows us to monitor two pref stores and tell updates from them apart. It
- // essentially mimics a Callback for the Observer interface (e.g. it allows
- // binding additional arguments).
- class OverlayUserPrefStore::ObserverAdapter : public PrefStore::Observer {
- public:
- ObserverAdapter(bool ephemeral, OverlayUserPrefStore* parent)
- : ephemeral_user_pref_store_(ephemeral), parent_(parent) {}
- // Methods of PrefStore::Observer.
- void OnPrefValueChanged(const std::string& key) override {
- parent_->OnPrefValueChanged(ephemeral_user_pref_store_, key);
- }
- void OnInitializationCompleted(bool succeeded) override {
- parent_->OnInitializationCompleted(ephemeral_user_pref_store_, succeeded);
- }
- private:
- // Is the update for the ephemeral?
- const bool ephemeral_user_pref_store_;
- const raw_ptr<OverlayUserPrefStore> parent_;
- };
- OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* persistent)
- : OverlayUserPrefStore(new InMemoryPrefStore(), persistent) {}
- OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* ephemeral,
- PersistentPrefStore* persistent)
- : ephemeral_pref_store_observer_(
- std::make_unique<OverlayUserPrefStore::ObserverAdapter>(true, this)),
- persistent_pref_store_observer_(
- std::make_unique<OverlayUserPrefStore::ObserverAdapter>(false, this)),
- ephemeral_user_pref_store_(ephemeral),
- persistent_user_pref_store_(persistent) {
- DCHECK(ephemeral->IsInitializationComplete());
- ephemeral_user_pref_store_->AddObserver(ephemeral_pref_store_observer_.get());
- persistent_user_pref_store_->AddObserver(
- persistent_pref_store_observer_.get());
- }
- bool OverlayUserPrefStore::IsSetInOverlay(const std::string& key) const {
- return ephemeral_user_pref_store_->GetValue(key, nullptr);
- }
- void OverlayUserPrefStore::AddObserver(PrefStore::Observer* observer) {
- observers_.AddObserver(observer);
- }
- void OverlayUserPrefStore::RemoveObserver(PrefStore::Observer* observer) {
- observers_.RemoveObserver(observer);
- }
- bool OverlayUserPrefStore::HasObservers() const {
- return !observers_.empty();
- }
- bool OverlayUserPrefStore::IsInitializationComplete() const {
- return persistent_user_pref_store_->IsInitializationComplete() &&
- ephemeral_user_pref_store_->IsInitializationComplete();
- }
- bool OverlayUserPrefStore::GetValue(const std::string& key,
- const base::Value** result) const {
- // If the |key| shall NOT be stored in the ephemeral store, there must not
- // be an entry.
- DCHECK(!ShallBeStoredInPersistent(key) ||
- !ephemeral_user_pref_store_->GetValue(key, nullptr));
- if (ephemeral_user_pref_store_->GetValue(key, result))
- return true;
- return persistent_user_pref_store_->GetValue(key, result);
- }
- base::Value::Dict OverlayUserPrefStore::GetValues() const {
- auto values = ephemeral_user_pref_store_->GetValues();
- auto persistent_values = persistent_user_pref_store_->GetValues();
- // Output |values| are read from |ephemeral_user_pref_store_| (in-memory
- // store). Then the values of preferences in |persistent_names_set_| are
- // overwritten by the content of |persistent_user_pref_store_| (the persistent
- // store).
- for (const auto& key : persistent_names_set_) {
- absl::optional<base::Value> out_value =
- persistent_values.ExtractByDottedPath(key);
- if (out_value.has_value()) {
- values.SetByDottedPath(key, std::move(*out_value));
- }
- }
- return values;
- }
- bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
- base::Value** result) {
- if (ShallBeStoredInPersistent(key))
- return persistent_user_pref_store_->GetMutableValue(key, result);
- written_ephemeral_names_.insert(key);
- if (ephemeral_user_pref_store_->GetMutableValue(key, result))
- return true;
- // Try to create copy of persistent if the ephemeral does not contain a value.
- base::Value* persistent_value = nullptr;
- if (!persistent_user_pref_store_->GetMutableValue(key, &persistent_value))
- return false;
- ephemeral_user_pref_store_->SetValue(
- key, base::Value::ToUniquePtrValue(persistent_value->Clone()),
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- ephemeral_user_pref_store_->GetMutableValue(key, result);
- return true;
- }
- void OverlayUserPrefStore::SetValue(const std::string& key,
- std::unique_ptr<base::Value> value,
- uint32_t flags) {
- if (ShallBeStoredInPersistent(key)) {
- persistent_user_pref_store_->SetValue(key, std::move(value), flags);
- return;
- }
- // TODO(https://crbug.com/861722): If we always store in in-memory storage
- // and conditionally also stored in persistent one, we wouldn't have to do a
- // complex merge in GetValues().
- written_ephemeral_names_.insert(key);
- ephemeral_user_pref_store_->SetValue(key, std::move(value), flags);
- }
- void OverlayUserPrefStore::SetValueSilently(const std::string& key,
- std::unique_ptr<base::Value> value,
- uint32_t flags) {
- if (ShallBeStoredInPersistent(key)) {
- persistent_user_pref_store_->SetValueSilently(key, std::move(value), flags);
- return;
- }
- written_ephemeral_names_.insert(key);
- ephemeral_user_pref_store_->SetValueSilently(key, std::move(value), flags);
- }
- void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
- if (ShallBeStoredInPersistent(key)) {
- persistent_user_pref_store_->RemoveValue(key, flags);
- return;
- }
- written_ephemeral_names_.insert(key);
- ephemeral_user_pref_store_->RemoveValue(key, flags);
- }
- void OverlayUserPrefStore::RemoveValuesByPrefixSilently(
- const std::string& prefix) {
- NOTIMPLEMENTED();
- }
- bool OverlayUserPrefStore::ReadOnly() const {
- return false;
- }
- PersistentPrefStore::PrefReadError OverlayUserPrefStore::GetReadError() const {
- return PersistentPrefStore::PREF_READ_ERROR_NONE;
- }
- PersistentPrefStore::PrefReadError OverlayUserPrefStore::ReadPrefs() {
- // We do not read intentionally.
- OnInitializationCompleted(/* ephemeral */ false, true);
- return PersistentPrefStore::PREF_READ_ERROR_NONE;
- }
- void OverlayUserPrefStore::ReadPrefsAsync(
- ReadErrorDelegate* error_delegate_raw) {
- std::unique_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
- // We do not read intentionally.
- OnInitializationCompleted(/* ephemeral */ false, true);
- }
- void OverlayUserPrefStore::CommitPendingWrite(
- base::OnceClosure reply_callback,
- base::OnceClosure synchronous_done_callback) {
- persistent_user_pref_store_->CommitPendingWrite(
- std::move(reply_callback), std::move(synchronous_done_callback));
- // We do not write our content intentionally.
- }
- void OverlayUserPrefStore::SchedulePendingLossyWrites() {
- persistent_user_pref_store_->SchedulePendingLossyWrites();
- }
- void OverlayUserPrefStore::ReportValueChanged(const std::string& key,
- uint32_t flags) {
- for (PrefStore::Observer& observer : observers_)
- observer.OnPrefValueChanged(key);
- }
- void OverlayUserPrefStore::RegisterPersistentPref(const std::string& key) {
- DCHECK(!key.empty()) << "Key is empty";
- DCHECK(persistent_names_set_.find(key) == persistent_names_set_.end())
- << "Key already registered: " << key;
- persistent_names_set_.insert(key);
- }
- void OverlayUserPrefStore::ClearMutableValues() {
- for (const auto& key : written_ephemeral_names_) {
- ephemeral_user_pref_store_->RemoveValue(
- key, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- }
- }
- void OverlayUserPrefStore::OnStoreDeletionFromDisk() {
- persistent_user_pref_store_->OnStoreDeletionFromDisk();
- }
- OverlayUserPrefStore::~OverlayUserPrefStore() {
- ephemeral_user_pref_store_->RemoveObserver(
- ephemeral_pref_store_observer_.get());
- persistent_user_pref_store_->RemoveObserver(
- persistent_pref_store_observer_.get());
- }
- void OverlayUserPrefStore::OnPrefValueChanged(bool ephemeral,
- const std::string& key) {
- if (ephemeral) {
- ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
- } else {
- if (!ephemeral_user_pref_store_->GetValue(key, nullptr))
- ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
- }
- }
- void OverlayUserPrefStore::OnInitializationCompleted(bool ephemeral,
- bool succeeded) {
- if (!IsInitializationComplete())
- return;
- for (PrefStore::Observer& observer : observers_)
- observer.OnInitializationCompleted(succeeded);
- }
- bool OverlayUserPrefStore::ShallBeStoredInPersistent(
- const std::string& key) const {
- return persistent_names_set_.find(key) != persistent_names_set_.end();
- }
|