1 // Copyright 2024 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/wrap_with_prefix_pref_store.h"
6
7 #include <string>
8 #include <string_view>
9
10 #include "base/strings/strcat.h"
11 #include "base/strings/string_util.h"
12
WrapWithPrefixPrefStore(scoped_refptr<PersistentPrefStore> target_pref_store,std::string_view path_prefix)13 WrapWithPrefixPrefStore::WrapWithPrefixPrefStore(
14 scoped_refptr<PersistentPrefStore> target_pref_store,
15 std::string_view path_prefix)
16 : target_pref_store_(std::move(target_pref_store)),
17 dotted_prefix_(base::StrCat({path_prefix, "."})) {
18 target_pref_store_->AddObserver(this);
19 }
20
~WrapWithPrefixPrefStore()21 WrapWithPrefixPrefStore::~WrapWithPrefixPrefStore() {
22 target_pref_store_->RemoveObserver(this);
23 }
24
GetValue(std::string_view key,const base::Value ** value) const25 bool WrapWithPrefixPrefStore::GetValue(std::string_view key,
26 const base::Value** value) const {
27 return target_pref_store_->GetValue(AddDottedPrefix(key), value);
28 }
29
GetValues() const30 base::Value::Dict WrapWithPrefixPrefStore::GetValues() const {
31 base::Value::Dict values = target_pref_store_->GetValues();
32 std::string_view prefix(dotted_prefix_.c_str(), dotted_prefix_.size() - 1);
33 if (base::Value::Dict* values_with_prefix =
34 values.FindDictByDottedPath(prefix)) {
35 return std::move(*values_with_prefix);
36 }
37 return {};
38 }
39
GetMutableValue(std::string_view key,base::Value ** value)40 bool WrapWithPrefixPrefStore::GetMutableValue(std::string_view key,
41 base::Value** value) {
42 return target_pref_store_->GetMutableValue(AddDottedPrefix(key), value);
43 }
44
AddObserver(PrefStore::Observer * observer)45 void WrapWithPrefixPrefStore::AddObserver(PrefStore::Observer* observer) {
46 observers_.AddObserver(observer);
47 }
48
RemoveObserver(PrefStore::Observer * observer)49 void WrapWithPrefixPrefStore::RemoveObserver(PrefStore::Observer* observer) {
50 observers_.RemoveObserver(observer);
51 }
52
HasObservers() const53 bool WrapWithPrefixPrefStore::HasObservers() const {
54 return !observers_.empty();
55 }
56
IsInitializationComplete() const57 bool WrapWithPrefixPrefStore::IsInitializationComplete() const {
58 return target_pref_store_->IsInitializationComplete();
59 }
60
SetValue(std::string_view key,base::Value value,uint32_t flags)61 void WrapWithPrefixPrefStore::SetValue(std::string_view key,
62 base::Value value,
63 uint32_t flags) {
64 target_pref_store_->SetValue(AddDottedPrefix(key), std::move(value), flags);
65 }
66
SetValueSilently(std::string_view key,base::Value value,uint32_t flags)67 void WrapWithPrefixPrefStore::SetValueSilently(std::string_view key,
68 base::Value value,
69 uint32_t flags) {
70 target_pref_store_->SetValueSilently(AddDottedPrefix(key), std::move(value),
71 flags);
72 }
73
RemoveValue(std::string_view key,uint32_t flags)74 void WrapWithPrefixPrefStore::RemoveValue(std::string_view key,
75 uint32_t flags) {
76 target_pref_store_->RemoveValue(AddDottedPrefix(key), flags);
77 }
78
RemoveValuesByPrefixSilently(std::string_view prefix)79 void WrapWithPrefixPrefStore::RemoveValuesByPrefixSilently(
80 std::string_view prefix) {
81 target_pref_store_->RemoveValuesByPrefixSilently(AddDottedPrefix(prefix));
82 }
83
ReadOnly() const84 bool WrapWithPrefixPrefStore::ReadOnly() const {
85 return target_pref_store_->ReadOnly();
86 }
87
GetReadError() const88 PersistentPrefStore::PrefReadError WrapWithPrefixPrefStore::GetReadError()
89 const {
90 return target_pref_store_->GetReadError();
91 }
92
ReadPrefs()93 PersistentPrefStore::PrefReadError WrapWithPrefixPrefStore::ReadPrefs() {
94 // The target pref store should have been initialized prior to calling
95 // ReadPrefs() on this store.
96 CHECK(target_pref_store_->IsInitializationComplete() ||
97 // To catch case where target pref store initialization failed.
98 target_pref_store_->GetReadError() !=
99 PersistentPrefStore::PREF_READ_ERROR_NONE);
100 return target_pref_store_->GetReadError();
101 }
102
ReadPrefsAsync(ReadErrorDelegate * error_delegate)103 void WrapWithPrefixPrefStore::ReadPrefsAsync(
104 ReadErrorDelegate* error_delegate) {
105 // The target pref store should either have been initialized or should have an
106 // ongoing read.
107 CHECK(IsInitializationComplete() ||
108 // To catch case where target pref store initialization failed.
109 GetReadError() != PersistentPrefStore::PREF_READ_ERROR_NONE ||
110 // ReadPrefsAsync() was called but it's still ongoing.
111 target_pref_store_->HasReadErrorDelegate());
112 read_error_delegate_.emplace(error_delegate);
113 if (PersistentPrefStore::PrefReadError read_error = GetReadError();
114 read_error != PersistentPrefStore::PREF_READ_ERROR_NONE &&
115 error_delegate) {
116 error_delegate->OnError(read_error);
117 }
118 }
119
SchedulePendingLossyWrites()120 void WrapWithPrefixPrefStore::SchedulePendingLossyWrites() {
121 // This store is only a wrapper and relies on the target pref store being
122 // independently notified of this.
123 }
124
OnStoreDeletionFromDisk()125 void WrapWithPrefixPrefStore::OnStoreDeletionFromDisk() {
126 // This store is only a wrapper and relies on the target pref store being
127 // independently notified of this.
128 }
129
ReportValueChanged(std::string_view key,uint32_t flags)130 void WrapWithPrefixPrefStore::ReportValueChanged(std::string_view key,
131 uint32_t flags) {
132 return target_pref_store_->ReportValueChanged(AddDottedPrefix(key), flags);
133 }
134
OnPrefValueChanged(std::string_view key)135 void WrapWithPrefixPrefStore::OnPrefValueChanged(std::string_view key) {
136 if (!HasDottedPrefix(key)) {
137 return;
138 }
139 std::string_view original_key(RemoveDottedPrefix(key));
140 for (PrefStore::Observer& observer : observers_) {
141 observer.OnPrefValueChanged(original_key);
142 }
143 }
144
OnInitializationCompleted(bool succeeded)145 void WrapWithPrefixPrefStore::OnInitializationCompleted(bool succeeded) {
146 if (PersistentPrefStore::PrefReadError read_error = GetReadError();
147 read_error != PersistentPrefStore::PREF_READ_ERROR_NONE &&
148 read_error_delegate_.has_value() && read_error_delegate_.value()) {
149 read_error_delegate_.value()->OnError(read_error);
150 }
151 for (PrefStore::Observer& observer : observers_) {
152 observer.OnInitializationCompleted(succeeded);
153 }
154 }
155
AddDottedPrefix(std::string_view path) const156 std::string WrapWithPrefixPrefStore::AddDottedPrefix(
157 std::string_view path) const {
158 return base::StrCat({dotted_prefix_, path});
159 }
160
RemoveDottedPrefix(std::string_view path) const161 std::string_view WrapWithPrefixPrefStore::RemoveDottedPrefix(
162 std::string_view path) const {
163 CHECK(HasDottedPrefix(path));
164 path.remove_prefix(dotted_prefix_.size());
165 return path;
166 }
167
HasDottedPrefix(std::string_view path) const168 bool WrapWithPrefixPrefStore::HasDottedPrefix(std::string_view path) const {
169 return base::StartsWith(path, dotted_prefix_);
170 }
171
HasReadErrorDelegate() const172 bool WrapWithPrefixPrefStore::HasReadErrorDelegate() const {
173 return read_error_delegate_.has_value();
174 }
175