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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: services/preferences/public/cpp/persistent_pref_store_client.cc
diff --git a/services/preferences/public/cpp/persistent_pref_store_client.cc b/services/preferences/public/cpp/persistent_pref_store_client.cc
index 9bcb92fb1b6e3859e745c8360fc93dea0bcf42c5..c152b8471ada48cfb1ed32aeafb1492a7bb109f5 100644
--- a/services/preferences/public/cpp/persistent_pref_store_client.cc
+++ b/services/preferences/public/cpp/persistent_pref_store_client.cc
@@ -4,14 +4,59 @@
#include "services/preferences/public/cpp/persistent_pref_store_client.h"
-#include <utility>
-
#include "base/values.h"
#include "components/prefs/pref_registry.h"
+#include "mojo/common/values.mojom.h"
+#include "mojo/common/values_struct_traits.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "services/preferences/public/cpp/pref_registry_serializer.h"
namespace prefs {
+namespace {
+
+const base::Value* LookupPath(const base::Value* root,
+ const std::vector<std::string>& path_components) {
+ const base::DictionaryValue* dictionary_value = nullptr;
+ if (!root->GetAsDictionary(&dictionary_value))
+ NOTREACHED();
+
+ for (size_t i = 0; i < path_components.size() - 1; ++i) {
+ if (!dictionary_value->GetDictionaryWithoutPathExpansion(
+ path_components[i], &dictionary_value)) {
+ return nullptr;
+ }
+ }
+ const base::Value* result = nullptr;
+ dictionary_value->GetWithoutPathExpansion(path_components.back(), &result);
+ return result;
+}
+
+template <typename StringType>
+bool IsPrefix(const std::vector<StringType>& prefix,
+ const std::vector<StringType>& full_path) {
+ if (prefix.size() >= full_path.size())
+ return false;
+
+ for (size_t i = 0; i < prefix.size(); i++) {
+ if (prefix[i] != full_path[i])
+ return false;
+ }
+ return true;
+}
+
+void RemoveRedundantPaths(std::set<std::vector<std::string>>* updated_paths) {
+ for (auto it = updated_paths->begin(), previous_it = updated_paths->end();
+ it != updated_paths->end();) {
+ if (previous_it != updated_paths->end() && IsPrefix(*previous_it, *it)) {
+ it = updated_paths->erase(it);
+ } else {
+ previous_it = it;
+ ++it;
+ }
+ }
+}
+
+} // namespace
PersistentPrefStoreClient::PersistentPrefStoreClient(
mojom::PrefStoreConnectorPtr connector,
@@ -57,10 +102,17 @@ bool PersistentPrefStoreClient::GetMutableValue(const std::string& key,
void PersistentPrefStoreClient::ReportValueChanged(const std::string& key,
uint32_t flags) {
DCHECK(pref_store_);
- const base::Value* local_value = nullptr;
- GetMutableValues().Get(key, &local_value);
- QueueWrite(key, flags);
+ ReportSubValuesChanged(
+ key, std::set<std::vector<std::string>>{std::vector<std::string>{}},
+ flags);
+}
+
+void PersistentPrefStoreClient::ReportSubValuesChanged(
+ const std::string& key,
+ std::set<std::vector<std::string>> path_components,
+ uint32_t flags) {
+ QueueWrite(key, std::move(path_components), flags);
ReportPrefValueChanged(key);
}
@@ -69,8 +121,10 @@ void PersistentPrefStoreClient::SetValueSilently(
std::unique_ptr<base::Value> value,
uint32_t flags) {
DCHECK(pref_store_);
- QueueWrite(key, flags);
GetMutableValues().Set(key, std::move(value));
+ QueueWrite(key,
+ std::set<std::vector<std::string>>{std::vector<std::string>{}},
+ flags);
}
bool PersistentPrefStoreClient::ReadOnly() const {
@@ -153,29 +207,58 @@ void PersistentPrefStoreClient::OnConnect(
}
}
-void PersistentPrefStoreClient::QueueWrite(const std::string& key,
- uint32_t flags) {
+void PersistentPrefStoreClient::QueueWrite(
+ const std::string& key,
+ std::set<std::vector<std::string>> path_components,
+ uint32_t flags) {
+ DCHECK(!path_components.empty());
if (pending_writes_.empty()) {
// Use a weak pointer since a pending write should not prolong the life of
- // |this|. Instead, the destruction of |this| will flush any pending writes.
+ // |this|. Instead, the destruction of |this| will flush any pending
+ // writes.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&PersistentPrefStoreClient::FlushPendingWrites,
weak_factory_.GetWeakPtr()));
}
- pending_writes_.insert(std::make_pair(key, flags));
+ RemoveRedundantPaths(&path_components);
+ auto& entry = pending_writes_[key];
+ entry.second = flags;
+ for (auto& path : path_components) {
+ entry.first.insert(std::move(path));
+ }
}
void PersistentPrefStoreClient::FlushPendingWrites() {
std::vector<mojom::PrefUpdatePtr> updates;
- for (const auto& pref : pending_writes_) {
+ for (auto& pref : pending_writes_) {
+ auto update_value = mojom::PrefUpdateValue::New();
const base::Value* value = nullptr;
if (GetValue(pref.first, &value)) {
- updates.push_back(mojom::PrefUpdate::New(
- pref.first, value->CreateDeepCopy(), pref.second));
+ std::vector<mojom::SubPrefUpdatePtr> pref_updates;
+ RemoveRedundantPaths(&pref.second.first);
+ for (const auto& path : pref.second.first) {
+ if (path.empty()) {
+ pref_updates.clear();
+ break;
+ }
+ const base::Value* nested_value = LookupPath(value, path);
+ if (nested_value) {
+ pref_updates.emplace_back(base::in_place, path,
+ nested_value->CreateDeepCopy());
+ } else {
+ pref_updates.emplace_back(base::in_place, path, nullptr);
+ }
+ }
+ if (pref_updates.empty()) {
+ update_value->set_atomic_update(value->CreateDeepCopy());
+ } else {
+ update_value->set_split_updates(std::move(pref_updates));
+ }
} else {
- updates.push_back(
- mojom::PrefUpdate::New(pref.first, nullptr, pref.second));
+ update_value->set_atomic_update(nullptr);
}
+ updates.emplace_back(base::in_place, pref.first, std::move(update_value),
+ pref.second.second);
}
pref_store_->SetValues(std::move(updates));
pending_writes_.clear();

Powered by Google App Engine
This is Rietveld 408576698