Index: services/preferences/public/cpp/scoped_pref_update.cc |
diff --git a/services/preferences/public/cpp/scoped_pref_update.cc b/services/preferences/public/cpp/scoped_pref_update.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..433ecd8724e0f9afca822c2e958c4c00b8592bbc |
--- /dev/null |
+++ b/services/preferences/public/cpp/scoped_pref_update.cc |
@@ -0,0 +1,385 @@ |
+// Copyright 2017 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 "services/preferences/public/cpp/scoped_pref_update.h" |
+ |
+#include <algorithm> |
+#include <utility> |
+ |
+#include "base/memory/ptr_util.h" |
+#include "base/strings/string_split.h" |
+#include "components/prefs/pref_service.h" |
+ |
+namespace prefs { |
+ |
+ScopedDictionaryPrefUpdate::ScopedDictionaryPrefUpdate(PrefService* service, |
+ base::StringPiece path) |
+ : service_(service), path_(path.as_string()) { |
+ base::DictionaryValue* value = static_cast<base::DictionaryValue*>( |
+ service_->GetMutableUserPref(path_, base::Value::Type::DICTIONARY)); |
+ value_ = Insert(base::WrapUnique( |
+ new DictionaryValueUpdate(this, value, std::vector<std::string>()))); |
+} |
+ |
+ScopedDictionaryPrefUpdate::~ScopedDictionaryPrefUpdate() { |
+ if (value_) |
+ Notify(); |
+} |
+ |
+DictionaryValueUpdate* ScopedDictionaryPrefUpdate::Get() { |
+ return value_; |
+} |
+ |
+DictionaryValueUpdate* ScopedDictionaryPrefUpdate::operator->() { |
+ return Get(); |
+} |
+ |
+void ScopedDictionaryPrefUpdate::Notify() { |
+ DCHECK(value_); |
+ if (!updated_paths_.empty()) |
+ service_->ReportUserPrefChanged(path_, std::move(updated_paths_)); |
+ value_ = nullptr; |
+ updates_.clear(); |
+} |
+ |
+void ScopedDictionaryPrefUpdate::RecordPath( |
+ const std::vector<std::string>& path) { |
+ updated_paths_.insert(std::move(path)); |
+} |
+ |
+DictionaryValueUpdate* ScopedDictionaryPrefUpdate::Insert( |
+ std::unique_ptr<DictionaryValueUpdate> dictionary_value_update) { |
+ updates_.push_back(std::move(dictionary_value_update)); |
+ return updates_.back().get(); |
+} |
+ |
+DictionaryValueUpdate::DictionaryValueUpdate(ScopedDictionaryPrefUpdate* update, |
+ base::DictionaryValue* value, |
+ std::vector<std::string> path) |
+ : update_(update), value_(value), path_(std::move(path)) {} |
+ |
+DictionaryValueUpdate::~DictionaryValueUpdate() = default; |
+ |
+bool DictionaryValueUpdate::HasKey(base::StringPiece key) const { |
+ return value_->HasKey(key); |
+} |
+ |
+size_t DictionaryValueUpdate::size() const { |
+ return value_->size(); |
+} |
+ |
+bool DictionaryValueUpdate::empty() const { |
+ return value_->empty(); |
+} |
+ |
+void DictionaryValueUpdate::Clear() { |
+ if (empty()) |
+ return; |
+ |
+ RecordSplitPath(std::vector<base::StringPiece>()); |
+ value_->Clear(); |
+} |
+ |
+void DictionaryValueUpdate::Set(base::StringPiece path, |
+ std::unique_ptr<base::Value> in_value) { |
+ const base::Value* old_value = nullptr; |
+ if (value_->Get(path, &old_value) && *old_value == *in_value) |
+ return; |
+ |
+ RecordPath(path); |
+ value_->Set(path, std::move(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetBoolean(base::StringPiece path, bool in_value) { |
+ Set(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetInteger(base::StringPiece path, int in_value) { |
+ Set(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetDouble(base::StringPiece path, double in_value) { |
+ Set(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetString(base::StringPiece path, |
+ base::StringPiece in_value) { |
+ Set(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetString(base::StringPiece path, |
+ const base::string16& in_value) { |
+ Set(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+DictionaryValueUpdate* DictionaryValueUpdate::SetDictionary( |
+ base::StringPiece path, |
+ std::unique_ptr<base::DictionaryValue> in_value) { |
+ RecordPath(path); |
+ base::DictionaryValue* dictionary_value = in_value.get(); |
+ value_->Set(path, std::move(in_value)); |
+ |
+ return update_->Insert(base::WrapUnique(new DictionaryValueUpdate( |
+ update_, dictionary_value, ConcatPath(path_, path)))); |
+} |
+ |
+void DictionaryValueUpdate::SetWithoutPathExpansion( |
+ base::StringPiece key, |
+ std::unique_ptr<base::Value> in_value) { |
+ const base::Value* old_value = nullptr; |
+ if (value_->GetWithoutPathExpansion(key, &old_value) && |
+ *old_value == *in_value) { |
+ return; |
+ } |
+ RecordKey(key); |
+ value_->SetWithoutPathExpansion(key, std::move(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetBooleanWithoutPathExpansion( |
+ base::StringPiece path, |
+ bool in_value) { |
+ SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetIntegerWithoutPathExpansion( |
+ base::StringPiece path, |
+ int in_value) { |
+ SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetDoubleWithoutPathExpansion( |
+ base::StringPiece path, |
+ double in_value) { |
+ SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetStringWithoutPathExpansion( |
+ base::StringPiece path, |
+ base::StringPiece in_value) { |
+ SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+void DictionaryValueUpdate::SetStringWithoutPathExpansion( |
+ base::StringPiece path, |
+ const base::string16& in_value) { |
+ SetWithoutPathExpansion(path, base::MakeUnique<base::Value>(in_value)); |
+} |
+ |
+DictionaryValueUpdate* DictionaryValueUpdate::SetDictionaryWithoutPathExpansion( |
+ base::StringPiece path, |
+ std::unique_ptr<base::DictionaryValue> in_value) { |
+ RecordKey(path); |
+ base::DictionaryValue* dictionary_value = in_value.get(); |
+ value_->SetWithoutPathExpansion(path, std::move(in_value)); |
+ |
+ std::vector<std::string> full_path = path_; |
+ full_path.push_back(path.as_string()); |
+ return update_->Insert(base::WrapUnique(new DictionaryValueUpdate( |
+ update_, dictionary_value, std::move(full_path)))); |
+} |
+ |
+bool DictionaryValueUpdate::GetBoolean(base::StringPiece path, |
+ bool* out_value) const { |
+ return value_->GetBoolean(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetInteger(base::StringPiece path, |
+ int* out_value) const { |
+ return value_->GetInteger(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetDouble(base::StringPiece path, |
+ double* out_value) const { |
+ return value_->GetDouble(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetString(base::StringPiece path, |
+ std::string* out_value) const { |
+ return value_->GetString(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetString(base::StringPiece path, |
+ base::string16* out_value) const { |
+ return value_->GetString(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetBinary(base::StringPiece path, |
+ const base::Value** out_value) const { |
+ return AsConstDictionary()->GetBinary(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetDictionary( |
+ base::StringPiece path, |
+ const base::DictionaryValue** out_value) const { |
+ return AsConstDictionary()->GetDictionary(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetDictionary(base::StringPiece path, |
+ DictionaryValueUpdate** out_value) { |
+ base::DictionaryValue* dictionary_value = nullptr; |
+ if (!value_->GetDictionary(path, &dictionary_value)) |
+ return false; |
+ |
+ *out_value = update_->Insert(base::WrapUnique(new DictionaryValueUpdate( |
+ update_, dictionary_value, ConcatPath(path_, path)))); |
+ return true; |
+} |
+ |
+bool DictionaryValueUpdate::GetList(base::StringPiece path, |
+ const base::ListValue** out_value) const { |
+ return AsConstDictionary()->GetList(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetList(base::StringPiece path, |
+ base::ListValue** out_value) { |
+ RecordPath(path); |
+ return value_->GetList(path, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetBooleanWithoutPathExpansion( |
+ base::StringPiece key, |
+ bool* out_value) const { |
+ return value_->GetBooleanWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetIntegerWithoutPathExpansion( |
+ base::StringPiece key, |
+ int* out_value) const { |
+ return value_->GetIntegerWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetDoubleWithoutPathExpansion( |
+ base::StringPiece key, |
+ double* out_value) const { |
+ return value_->GetDoubleWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetStringWithoutPathExpansion( |
+ base::StringPiece key, |
+ std::string* out_value) const { |
+ return value_->GetStringWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetStringWithoutPathExpansion( |
+ base::StringPiece key, |
+ base::string16* out_value) const { |
+ return value_->GetStringWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetDictionaryWithoutPathExpansion( |
+ base::StringPiece key, |
+ const base::DictionaryValue** out_value) const { |
+ return value_->GetDictionaryWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetDictionaryWithoutPathExpansion( |
+ base::StringPiece key, |
+ DictionaryValueUpdate** out_value) { |
+ base::DictionaryValue* dictionary_value = nullptr; |
+ if (!value_->GetDictionary(key, &dictionary_value)) |
+ return false; |
+ |
+ std::vector<std::string> full_path = path_; |
+ full_path.push_back(key.as_string()); |
+ *out_value = update_->Insert(base::WrapUnique(new DictionaryValueUpdate( |
+ update_, dictionary_value, std::move(full_path)))); |
+ return true; |
+} |
+ |
+bool DictionaryValueUpdate::GetListWithoutPathExpansion( |
+ base::StringPiece key, |
+ const base::ListValue** out_value) const { |
+ return value_->GetListWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::GetListWithoutPathExpansion( |
+ base::StringPiece key, |
+ base::ListValue** out_value) { |
+ RecordKey(key); |
+ return value_->GetListWithoutPathExpansion(key, out_value); |
+} |
+ |
+bool DictionaryValueUpdate::Remove(base::StringPiece path, |
+ std::unique_ptr<base::Value>* out_value) { |
+ if (!value_->Remove(path, out_value)) |
+ return false; |
+ |
+ RecordPath(path); |
+ return true; |
+} |
+ |
+bool DictionaryValueUpdate::RemoveWithoutPathExpansion( |
+ base::StringPiece key, |
+ std::unique_ptr<base::Value>* out_value) { |
+ if (!value_->RemoveWithoutPathExpansion(key, out_value)) |
+ return false; |
+ |
+ RecordKey(key); |
+ return true; |
+} |
+ |
+bool DictionaryValueUpdate::RemovePath( |
+ base::StringPiece path, |
+ std::unique_ptr<base::Value>* out_value) { |
+ if (!value_->RemovePath(path, out_value)) |
+ return false; |
+ |
+ std::vector<base::StringPiece> split_path = SplitPath(path); |
+ base::DictionaryValue* dict = value_; |
+ for (size_t i = 0; i < split_path.size() - 1; ++i) { |
+ if (!dict->GetDictionary(split_path[i], &dict)) { |
+ split_path.resize(i + 1); |
+ RecordSplitPath(split_path); |
+ return true; |
+ } |
+ } |
+ RecordPath(path); |
+ return true; |
+} |
+ |
+base::DictionaryValue* DictionaryValueUpdate::AsDictionary() { |
+ RecordSplitPath(std::vector<base::StringPiece>()); |
+ return value_; |
+} |
+ |
+const base::DictionaryValue* DictionaryValueUpdate::AsConstDictionary() const { |
+ return value_; |
+} |
+ |
+void DictionaryValueUpdate::RecordKey(base::StringPiece key) { |
+ RecordSplitPath({key}); |
+} |
+ |
+void DictionaryValueUpdate::RecordPath(base::StringPiece path) { |
+ RecordSplitPath(SplitPath(path)); |
+} |
+ |
+void DictionaryValueUpdate::RecordSplitPath( |
+ const std::vector<base::StringPiece>& path) { |
+ update_->RecordPath(ConcatPath(path_, path)); |
+} |
+ |
+std::vector<base::StringPiece> DictionaryValueUpdate::SplitPath( |
+ base::StringPiece path) { |
+ return base::SplitStringPiece(path, ".", base::TRIM_WHITESPACE, |
+ base::SPLIT_WANT_NONEMPTY); |
+} |
+ |
+std::vector<std::string> DictionaryValueUpdate::ConcatPath( |
+ const std::vector<std::string>& base_path, |
+ base::StringPiece path) { |
+ return ConcatPath(base_path, SplitPath(path)); |
+} |
+ |
+std::vector<std::string> DictionaryValueUpdate::ConcatPath( |
+ const std::vector<std::string>& base_path, |
+ const std::vector<base::StringPiece>& path) { |
+ std::vector<std::string> full_path = base_path; |
+ full_path.reserve(full_path.size() + path.size()); |
+ std::transform(path.begin(), path.end(), std::back_inserter(full_path), |
+ [](base::StringPiece s) { return s.as_string(); }); |
+ return full_path; |
+} |
+ |
+} // namespace prefs |