Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: services/preferences/public/cpp/persistent_pref_store_client.cc

Issue 2812863002: Pref service: Add a ScopedDictionaryPrefUpdate to track value changes. (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/preferences/public/cpp/persistent_pref_store_client.h" 5 #include "services/preferences/public/cpp/persistent_pref_store_client.h"
6 6
7 #include <utility>
8
9 #include "base/values.h" 7 #include "base/values.h"
10 #include "components/prefs/pref_registry.h" 8 #include "components/prefs/pref_registry.h"
9 #include "mojo/common/values.mojom.h"
10 #include "mojo/common/values_struct_traits.h"
11 #include "mojo/public/cpp/bindings/sync_call_restrictions.h" 11 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
12 #include "services/preferences/public/cpp/pref_registry_serializer.h" 12 #include "services/preferences/public/cpp/pref_registry_serializer.h"
13 13
14 namespace prefs { 14 namespace prefs {
15 namespace {
16
17 const base::Value* LookupPath(const base::Value* root,
18 const std::vector<std::string>& path_components) {
19 const base::DictionaryValue* dictionary_value = nullptr;
20 if (!root->GetAsDictionary(&dictionary_value))
21 NOTREACHED();
22
23 for (size_t i = 0; i < path_components.size() - 1; ++i) {
24 if (!dictionary_value->GetDictionaryWithoutPathExpansion(
25 path_components[i], &dictionary_value)) {
26 return nullptr;
27 }
28 }
29 const base::Value* result = nullptr;
30 dictionary_value->GetWithoutPathExpansion(path_components.back(), &result);
31 return result;
32 }
33
34 template <typename StringType>
35 bool IsPrefix(const std::vector<StringType>& prefix,
36 const std::vector<StringType>& full_path) {
37 if (prefix.size() >= full_path.size())
38 return false;
39
40 for (size_t i = 0; i < prefix.size(); i++) {
41 if (prefix[i] != full_path[i])
42 return false;
43 }
44 return true;
45 }
46
47 void RemoveRedundantPaths(std::set<std::vector<std::string>>* updated_paths) {
48 for (auto it = updated_paths->begin(), previous_it = updated_paths->end();
49 it != updated_paths->end();) {
50 if (previous_it != updated_paths->end() && IsPrefix(*previous_it, *it)) {
51 it = updated_paths->erase(it);
52 } else {
53 previous_it = it;
54 ++it;
55 }
56 }
57 }
58
59 } // namespace
15 60
16 PersistentPrefStoreClient::PersistentPrefStoreClient( 61 PersistentPrefStoreClient::PersistentPrefStoreClient(
17 mojom::PrefStoreConnectorPtr connector, 62 mojom::PrefStoreConnectorPtr connector,
18 scoped_refptr<PrefRegistry> pref_registry, 63 scoped_refptr<PrefRegistry> pref_registry,
19 std::vector<PrefValueStore::PrefStoreType> already_connected_types) 64 std::vector<PrefValueStore::PrefStoreType> already_connected_types)
20 : connector_(std::move(connector)), 65 : connector_(std::move(connector)),
21 pref_registry_(std::move(pref_registry)), 66 pref_registry_(std::move(pref_registry)),
22 already_connected_types_(std::move(already_connected_types)), 67 already_connected_types_(std::move(already_connected_types)),
23 weak_factory_(this) { 68 weak_factory_(this) {
24 DCHECK(connector_); 69 DCHECK(connector_);
(...skipping 25 matching lines...) Expand all
50 } 95 }
51 96
52 bool PersistentPrefStoreClient::GetMutableValue(const std::string& key, 97 bool PersistentPrefStoreClient::GetMutableValue(const std::string& key,
53 base::Value** result) { 98 base::Value** result) {
54 return GetMutableValues().Get(key, result); 99 return GetMutableValues().Get(key, result);
55 } 100 }
56 101
57 void PersistentPrefStoreClient::ReportValueChanged(const std::string& key, 102 void PersistentPrefStoreClient::ReportValueChanged(const std::string& key,
58 uint32_t flags) { 103 uint32_t flags) {
59 DCHECK(pref_store_); 104 DCHECK(pref_store_);
60 const base::Value* local_value = nullptr;
61 GetMutableValues().Get(key, &local_value);
62 105
63 QueueWrite(key, flags); 106 ReportSubValuesChanged(
107 key, std::set<std::vector<std::string>>{std::vector<std::string>{}},
108 flags);
109 }
110
111 void PersistentPrefStoreClient::ReportSubValuesChanged(
112 const std::string& key,
113 std::set<std::vector<std::string>> path_components,
114 uint32_t flags) {
115 QueueWrite(key, std::move(path_components), flags);
64 ReportPrefValueChanged(key); 116 ReportPrefValueChanged(key);
65 } 117 }
66 118
67 void PersistentPrefStoreClient::SetValueSilently( 119 void PersistentPrefStoreClient::SetValueSilently(
68 const std::string& key, 120 const std::string& key,
69 std::unique_ptr<base::Value> value, 121 std::unique_ptr<base::Value> value,
70 uint32_t flags) { 122 uint32_t flags) {
71 DCHECK(pref_store_); 123 DCHECK(pref_store_);
72 QueueWrite(key, flags);
73 GetMutableValues().Set(key, std::move(value)); 124 GetMutableValues().Set(key, std::move(value));
125 QueueWrite(key,
126 std::set<std::vector<std::string>>{std::vector<std::string>{}},
127 flags);
74 } 128 }
75 129
76 bool PersistentPrefStoreClient::ReadOnly() const { 130 bool PersistentPrefStoreClient::ReadOnly() const {
77 return read_only_; 131 return read_only_;
78 } 132 }
79 133
80 PersistentPrefStore::PrefReadError PersistentPrefStoreClient::GetReadError() 134 PersistentPrefStore::PrefReadError PersistentPrefStoreClient::GetReadError()
81 const { 135 const {
82 return read_error_; 136 return read_error_;
83 } 137 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 error_delegate_.reset(); 200 error_delegate_.reset();
147 201
148 if (connection->pref_store_connection) { 202 if (connection->pref_store_connection) {
149 Init(std::move(connection->pref_store_connection->initial_prefs), true, 203 Init(std::move(connection->pref_store_connection->initial_prefs), true,
150 std::move(connection->pref_store_connection->observer)); 204 std::move(connection->pref_store_connection->observer));
151 } else { 205 } else {
152 Init(nullptr, false, nullptr); 206 Init(nullptr, false, nullptr);
153 } 207 }
154 } 208 }
155 209
156 void PersistentPrefStoreClient::QueueWrite(const std::string& key, 210 void PersistentPrefStoreClient::QueueWrite(
157 uint32_t flags) { 211 const std::string& key,
212 std::set<std::vector<std::string>> path_components,
213 uint32_t flags) {
214 DCHECK(!path_components.empty());
158 if (pending_writes_.empty()) { 215 if (pending_writes_.empty()) {
159 // Use a weak pointer since a pending write should not prolong the life of 216 // Use a weak pointer since a pending write should not prolong the life of
160 // |this|. Instead, the destruction of |this| will flush any pending writes. 217 // |this|. Instead, the destruction of |this| will flush any pending
218 // writes.
161 base::ThreadTaskRunnerHandle::Get()->PostTask( 219 base::ThreadTaskRunnerHandle::Get()->PostTask(
162 FROM_HERE, base::Bind(&PersistentPrefStoreClient::FlushPendingWrites, 220 FROM_HERE, base::Bind(&PersistentPrefStoreClient::FlushPendingWrites,
163 weak_factory_.GetWeakPtr())); 221 weak_factory_.GetWeakPtr()));
164 } 222 }
165 pending_writes_.insert(std::make_pair(key, flags)); 223 RemoveRedundantPaths(&path_components);
224 auto& entry = pending_writes_[key];
225 entry.second = flags;
226 for (auto& path : path_components) {
227 entry.first.insert(std::move(path));
228 }
166 } 229 }
167 230
168 void PersistentPrefStoreClient::FlushPendingWrites() { 231 void PersistentPrefStoreClient::FlushPendingWrites() {
169 std::vector<mojom::PrefUpdatePtr> updates; 232 std::vector<mojom::PrefUpdatePtr> updates;
170 for (const auto& pref : pending_writes_) { 233 for (auto& pref : pending_writes_) {
234 auto update_value = mojom::PrefUpdateValue::New();
171 const base::Value* value = nullptr; 235 const base::Value* value = nullptr;
172 if (GetValue(pref.first, &value)) { 236 if (GetValue(pref.first, &value)) {
173 updates.push_back(mojom::PrefUpdate::New( 237 std::vector<mojom::SubPrefUpdatePtr> pref_updates;
174 pref.first, value->CreateDeepCopy(), pref.second)); 238 RemoveRedundantPaths(&pref.second.first);
239 for (const auto& path : pref.second.first) {
240 if (path.empty()) {
241 pref_updates.clear();
242 break;
243 }
244 const base::Value* nested_value = LookupPath(value, path);
245 if (nested_value) {
246 pref_updates.emplace_back(base::in_place, path,
247 nested_value->CreateDeepCopy());
248 } else {
249 pref_updates.emplace_back(base::in_place, path, nullptr);
250 }
251 }
252 if (pref_updates.empty()) {
253 update_value->set_atomic_update(value->CreateDeepCopy());
254 } else {
255 update_value->set_split_updates(std::move(pref_updates));
256 }
175 } else { 257 } else {
176 updates.push_back( 258 update_value->set_atomic_update(nullptr);
177 mojom::PrefUpdate::New(pref.first, nullptr, pref.second));
178 } 259 }
260 updates.emplace_back(base::in_place, pref.first, std::move(update_value),
261 pref.second.second);
179 } 262 }
180 pref_store_->SetValues(std::move(updates)); 263 pref_store_->SetValues(std::move(updates));
181 pending_writes_.clear(); 264 pending_writes_.clear();
182 } 265 }
183 266
184 } // namespace prefs 267 } // namespace prefs
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698