diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-09-03 13:32:17 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-01 14:31:55 +0200 |
commit | 21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch) | |
tree | 91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/components/prefs | |
parent | 03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff) | |
download | qtwebengine-chromium-21ba0c5d4bf8fba15dddd97cd693bad2358b77fd.tar.gz |
BASELINE: Update Chromium to 92.0.4515.166
Change-Id: I42a050486714e9e54fc271f2a8939223a02ae364
Diffstat (limited to 'chromium/components/prefs')
21 files changed, 832 insertions, 97 deletions
diff --git a/chromium/components/prefs/BUILD.gn b/chromium/components/prefs/BUILD.gn index 1017a2069cc..0df592dc08a 100644 --- a/chromium/components/prefs/BUILD.gn +++ b/chromium/components/prefs/BUILD.gn @@ -42,6 +42,8 @@ component("prefs") { "prefs_export.h", "scoped_user_pref_update.cc", "scoped_user_pref_update.h", + "segregated_pref_store.cc", + "segregated_pref_store.h", "value_map_pref_store.cc", "value_map_pref_store.h", "writeable_pref_store.cc", @@ -103,6 +105,7 @@ source_set("unit_tests") { "pref_value_map_unittest.cc", "pref_value_store_unittest.cc", "scoped_user_pref_update_unittest.cc", + "segregated_pref_store_unittest.cc", ] deps = [ diff --git a/chromium/components/prefs/DIR_METADATA b/chromium/components/prefs/DIR_METADATA index 1b859d641e2..e9153b069b8 100644 --- a/chromium/components/prefs/DIR_METADATA +++ b/chromium/components/prefs/DIR_METADATA @@ -1,5 +1,5 @@ monorail { - component: "UI>Browser>Preferences" + component: "Internals>Preferences" } team_email: "chromium-dev@chromium.org" diff --git a/chromium/components/prefs/android/DIR_METADATA b/chromium/components/prefs/android/DIR_METADATA index 830f167d664..1744a1fc936 100644 --- a/chromium/components/prefs/android/DIR_METADATA +++ b/chromium/components/prefs/android/DIR_METADATA @@ -1,5 +1,2 @@ -monorail { - component: "Internals>Preferences" -} os: ANDROID diff --git a/chromium/components/prefs/command_line_pref_store.cc b/chromium/components/prefs/command_line_pref_store.cc index 4a475f57695..35c74a4b62e 100644 --- a/chromium/components/prefs/command_line_pref_store.cc +++ b/chromium/components/prefs/command_line_pref_store.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/values.h" CommandLinePrefStore::CommandLinePrefStore( const base::CommandLine* command_line) diff --git a/chromium/components/prefs/command_line_pref_store.h b/chromium/components/prefs/command_line_pref_store.h index 03d5da96958..bbc7b2bff1a 100644 --- a/chromium/components/prefs/command_line_pref_store.h +++ b/chromium/components/prefs/command_line_pref_store.h @@ -7,7 +7,6 @@ #include "base/command_line.h" #include "base/macros.h" -#include "base/values.h" #include "components/prefs/value_map_pref_store.h" // Base class for a PrefStore that maps command line switches to preferences. diff --git a/chromium/components/prefs/json_pref_store.cc b/chromium/components/prefs/json_pref_store.cc index c7017f0b61e..2f1f2c72fa9 100644 --- a/chromium/components/prefs/json_pref_store.cc +++ b/chromium/components/prefs/json_pref_store.cc @@ -220,7 +220,7 @@ void JsonPrefStore::SetValue(const std::string& key, DCHECK(value); base::Value* old_value = nullptr; prefs_->Get(key, &old_value); - if (!old_value || !value->Equals(old_value)) { + if (!old_value || *value != *old_value) { prefs_->Set(key, std::move(value)); ReportValueChanged(key, flags); } @@ -234,7 +234,7 @@ void JsonPrefStore::SetValueSilently(const std::string& key, DCHECK(value); base::Value* old_value = nullptr; prefs_->Get(key, &old_value); - if (!old_value || !value->Equals(old_value)) { + if (!old_value || *value != *old_value) { prefs_->Set(key, std::move(value)); ScheduleWrite(flags); } diff --git a/chromium/components/prefs/json_pref_store_unittest.cc b/chromium/components/prefs/json_pref_store_unittest.cc index 024f36a0091..5eeeeeed12e 100644 --- a/chromium/components/prefs/json_pref_store_unittest.cc +++ b/chromium/components/prefs/json_pref_store_unittest.cc @@ -240,55 +240,51 @@ void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store, const Value* actual; EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual)); - std::string string_value; - EXPECT_TRUE(actual->GetAsString(&string_value)); - EXPECT_EQ(cnn, string_value); + EXPECT_TRUE(actual->is_string()); + EXPECT_EQ(cnn, actual->GetString()); const char kSomeDirectory[] = "some_directory"; EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual)); - std::string path; - EXPECT_TRUE(actual->GetAsString(&path)); - EXPECT_EQ("/usr/local/", path); + EXPECT_TRUE(actual->is_string()); + EXPECT_EQ("/usr/local/", actual->GetString()); base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/")); pref_store->SetValue(kSomeDirectory, std::make_unique<Value>(some_path.AsUTF8Unsafe()), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual)); - EXPECT_TRUE(actual->GetAsString(&path)); - EXPECT_EQ(some_path.AsUTF8Unsafe(), path); + EXPECT_TRUE(actual->is_string()); + EXPECT_EQ(some_path.AsUTF8Unsafe(), actual->GetString()); // Test reading some other data types from sub-dictionaries. EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual)); - bool boolean = false; - EXPECT_TRUE(actual->GetAsBoolean(&boolean)); - EXPECT_TRUE(boolean); + EXPECT_TRUE(actual->is_bool()); + EXPECT_TRUE(actual->GetBool()); pref_store->SetValue(kNewWindowsInTabs, std::make_unique<Value>(false), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual)); - EXPECT_TRUE(actual->GetAsBoolean(&boolean)); - EXPECT_FALSE(boolean); + EXPECT_TRUE(actual->is_bool()); + EXPECT_FALSE(actual->GetBool()); EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual)); - int integer = 0; - EXPECT_TRUE(actual->GetAsInteger(&integer)); - EXPECT_EQ(20, integer); + ASSERT_TRUE(actual->is_int()); + EXPECT_EQ(20, actual->GetInt()); pref_store->SetValue(kMaxTabs, std::make_unique<Value>(10), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual)); - EXPECT_TRUE(actual->GetAsInteger(&integer)); - EXPECT_EQ(10, integer); + ASSERT_TRUE(actual->is_int()); + EXPECT_EQ(10, actual->GetInt()); pref_store->SetValue( kLongIntPref, std::make_unique<Value>(base::NumberToString(214748364842LL)), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual)); - EXPECT_TRUE(actual->GetAsString(&string_value)); + EXPECT_TRUE(actual->is_string()); int64_t value; - base::StringToInt64(string_value, &value); + base::StringToInt64(actual->GetString(), &value); EXPECT_EQ(214748364842LL, value); // Serialize and compare to expected output. diff --git a/chromium/components/prefs/mock_pref_change_callback.h b/chromium/components/prefs/mock_pref_change_callback.h index 9c0aeecd9c3..6ba895c3d52 100644 --- a/chromium/components/prefs/mock_pref_change_callback.h +++ b/chromium/components/prefs/mock_pref_change_callback.h @@ -28,7 +28,7 @@ MATCHER_P3(PrefValueMatches, prefs, pref_name, value, "") { return value == NULL; if (!value) return actual_value == NULL; - return value->Equals(actual_value); + return *value == *actual_value; } // A mock for testing preference notifications and easy setup of expectations. diff --git a/chromium/components/prefs/overlay_user_pref_store.cc b/chromium/components/prefs/overlay_user_pref_store.cc index 5bb26b43e48..b3374930553 100644 --- a/chromium/components/prefs/overlay_user_pref_store.cc +++ b/chromium/components/prefs/overlay_user_pref_store.cc @@ -116,7 +116,7 @@ bool OverlayUserPrefStore::GetMutableValue(const std::string& key, return false; ephemeral_user_pref_store_->SetValue( - key, persistent_value->CreateDeepCopy(), + key, base::Value::ToUniquePtrValue(persistent_value->Clone()), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); ephemeral_user_pref_store_->GetMutableValue(key, result); return true; diff --git a/chromium/components/prefs/overlay_user_pref_store_unittest.cc b/chromium/components/prefs/overlay_user_pref_store_unittest.cc index 1c0c855b93c..d8be47e61b0 100644 --- a/chromium/components/prefs/overlay_user_pref_store_unittest.cc +++ b/chromium/components/prefs/overlay_user_pref_store_unittest.cc @@ -145,7 +145,7 @@ TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) { EXPECT_TRUE(underlay_->GetMutableValue(regular_key, &original_in_underlay)); ASSERT_TRUE(original_in_underlay); ASSERT_TRUE(original_in_underlay->is_dict()); - EXPECT_TRUE(static_cast<DictionaryValue*>(original_in_underlay)->empty()); + EXPECT_TRUE(original_in_underlay->DictEmpty()); Value* modified = nullptr; EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modified)); diff --git a/chromium/components/prefs/persistent_pref_store.h b/chromium/components/prefs/persistent_pref_store.h index 967ccdaaec8..0da1423d159 100644 --- a/chromium/components/prefs/persistent_pref_store.h +++ b/chromium/components/prefs/persistent_pref_store.h @@ -5,8 +5,6 @@ #ifndef COMPONENTS_PREFS_PERSISTENT_PREF_STORE_H_ #define COMPONENTS_PREFS_PERSISTENT_PREF_STORE_H_ -#include <string> - #include "base/callback.h" #include "components/prefs/prefs_export.h" #include "components/prefs/writeable_pref_store.h" diff --git a/chromium/components/prefs/pref_member.cc b/chromium/components/prefs/pref_member.cc index a53394f6ff8..e2087ab1bc7 100644 --- a/chromium/components/prefs/pref_member.cc +++ b/chromium/components/prefs/pref_member.cc @@ -11,6 +11,7 @@ #include "base/location.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/util/values/values_util.h" +#include "base/values.h" #include "components/prefs/pref_service.h" using base::SequencedTaskRunner; @@ -72,8 +73,9 @@ void PrefMemberBase::UpdateValueFromPref(base::OnceClosure callback) const { DCHECK(pref); if (!internal()) CreateInternal(); - internal()->UpdateValue(pref->GetValue()->DeepCopy(), pref->IsManaged(), - pref->IsUserModifiable(), std::move(callback)); + internal()->UpdateValue( + base::Value::ToUniquePtrValue(pref->GetValue()->Clone()).release(), + pref->IsManaged(), pref->IsUserModifiable(), std::move(callback)); } void PrefMemberBase::VerifyPref() const { @@ -129,15 +131,12 @@ bool PrefMemberVectorStringUpdate(const base::Value& value, std::vector<std::string>* string_vector) { if (!value.is_list()) return false; - const base::ListValue* list = static_cast<const base::ListValue*>(&value); std::vector<std::string> local_vector; - for (auto it = list->begin(); it != list->end(); ++it) { - std::string string_value; - if (!it->GetAsString(&string_value)) + for (const auto& item : value.GetList()) { + if (!item.is_string()) return false; - - local_vector.push_back(string_value); + local_vector.push_back(item.GetString()); } string_vector->swap(local_vector); @@ -154,7 +153,9 @@ void PrefMember<bool>::UpdatePref(const bool& value) { template <> bool PrefMember<bool>::Internal::UpdateValueInternal( const base::Value& value) const { - return value.GetAsBoolean(&value_); + if (value.is_bool()) + value_ = value.GetBool(); + return value.is_bool(); } template <> @@ -165,7 +166,9 @@ void PrefMember<int>::UpdatePref(const int& value) { template <> bool PrefMember<int>::Internal::UpdateValueInternal( const base::Value& value) const { - return value.GetAsInteger(&value_); + if (value.is_int()) + value_ = value.GetInt(); + return value.is_int(); } template <> @@ -176,7 +179,9 @@ void PrefMember<double>::UpdatePref(const double& value) { template <> bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value) const { - return value.GetAsDouble(&value_); + if (value.is_double() || value.is_int()) + value_ = value.GetDouble(); + return value.is_double() || value.is_int(); } template <> @@ -188,7 +193,9 @@ template <> bool PrefMember<std::string>::Internal::UpdateValueInternal( const base::Value& value) const { - return value.GetAsString(&value_); + if (value.is_string()) + value_ = value.GetString(); + return value.is_string(); } template <> @@ -200,7 +207,7 @@ template <> bool PrefMember<base::FilePath>::Internal::UpdateValueInternal( const base::Value& value) const { - base::Optional<base::FilePath> path = util::ValueToFilePath(value); + absl::optional<base::FilePath> path = util::ValueToFilePath(value); if (!path) return false; value_ = *path; @@ -211,7 +218,9 @@ template <> void PrefMember<std::vector<std::string> >::UpdatePref( const std::vector<std::string>& value) { base::ListValue list_value; - list_value.AppendStrings(value); + for (const std::string& val : value) + list_value.Append(val); + prefs()->Set(pref_name(), list_value); } diff --git a/chromium/components/prefs/pref_service.cc b/chromium/components/prefs/pref_service.cc index e15c2d5f723..3f1474a47e1 100644 --- a/chromium/components/prefs/pref_service.cc +++ b/chromium/components/prefs/pref_service.cc @@ -23,6 +23,7 @@ #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/util/values/values_util.h" +#include "base/values.h" #include "build/build_config.h" #include "components/prefs/default_pref_store.h" #include "components/prefs/pref_notifier_impl.h" @@ -196,7 +197,7 @@ base::FilePath PrefService::GetFilePath(const std::string& path) const { const base::Value* value = GetPreferenceValueChecked(path); if (!value) return base::FilePath(); - base::Optional<base::FilePath> result = util::ValueToFilePath(*value); + absl::optional<base::FilePath> result = util::ValueToFilePath(*value); DCHECK(result); return *result; } @@ -492,7 +493,7 @@ void PrefService::SetInt64(const std::string& path, int64_t value) { int64_t PrefService::GetInt64(const std::string& path) const { const base::Value* value = GetPreferenceValueChecked(path); - base::Optional<int64_t> integer = util::ValueToInt64(value); + absl::optional<int64_t> integer = util::ValueToInt64(value); DCHECK(integer); return integer.value_or(0); } @@ -519,7 +520,7 @@ void PrefService::SetTime(const std::string& path, base::Time value) { base::Time PrefService::GetTime(const std::string& path) const { const base::Value* value = GetPreferenceValueChecked(path); - base::Optional<base::Time> time = util::ValueToTime(value); + absl::optional<base::Time> time = util::ValueToTime(value); DCHECK(time); return time.value_or(base::Time()); } @@ -530,7 +531,7 @@ void PrefService::SetTimeDelta(const std::string& path, base::TimeDelta value) { base::TimeDelta PrefService::GetTimeDelta(const std::string& path) const { const base::Value* value = GetPreferenceValueChecked(path); - base::Optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value); + absl::optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value); DCHECK(time_delta); return time_delta.value_or(base::TimeDelta()); } @@ -559,22 +560,13 @@ base::Value* PrefService::GetMutableUserPref(const std::string& path, return value; } - // TODO(crbug.com/859477): Remove once root cause has been found. - if (value && value->type() != type) { - DEBUG_ALIAS_FOR_CSTR(path_copy, path.c_str(), 1024); - base::debug::DumpWithoutCrashing(); - } - // If no user preference of the correct type exists, clone default value. const base::Value* default_value = nullptr; pref_registry_->defaults()->GetValue(path, &default_value); - // TODO(crbug.com/859477): Revert to DCHECK once root cause has been found. - if (default_value->type() != type) { - DEBUG_ALIAS_FOR_CSTR(path_copy, path.c_str(), 1024); - base::debug::DumpWithoutCrashing(); - } - user_pref_store_->SetValueSilently(path, default_value->CreateDeepCopy(), - GetWriteFlags(pref)); + DCHECK_EQ(default_value->type(), type); + user_pref_store_->SetValueSilently( + path, base::Value::ToUniquePtrValue(default_value->Clone()), + GetWriteFlags(pref)); user_pref_store_->GetMutableValue(path, &value); return value; } diff --git a/chromium/components/prefs/pref_service_unittest.cc b/chromium/components/prefs/pref_service_unittest.cc index 392cd6816c8..fd83ccf6955 100644 --- a/chromium/components/prefs/pref_service_unittest.cc +++ b/chromium/components/prefs/pref_service_unittest.cc @@ -158,9 +158,8 @@ TEST(PrefServiceTest, GetValueChangedType) { const base::Value* value = pref->GetValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - int actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kTestValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kTestValue, value->GetInt()); } TEST(PrefServiceTest, GetValueAndGetRecommendedValue) { @@ -178,9 +177,8 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) { const base::Value* value = pref->GetValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - int actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kDefaultValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kDefaultValue, value->GetInt()); // Check that GetRecommendedValue() returns no value. value = pref->GetRecommendedValue(); @@ -193,9 +191,8 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) { value = pref->GetValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kUserValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kUserValue, value->GetInt()); // Check that GetRecommendedValue() returns no value. value = pref->GetRecommendedValue(); @@ -209,17 +206,15 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) { value = pref->GetValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kUserValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kUserValue, value->GetInt()); // Check that GetRecommendedValue() returns the recommended value. value = pref->GetRecommendedValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kRecommendedValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kRecommendedValue, value->GetInt()); // Remove the user-set value. prefs.RemoveUserPref(kPrefName); @@ -228,17 +223,15 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) { value = pref->GetValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kRecommendedValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kRecommendedValue, value->GetInt()); // Check that GetRecommendedValue() returns the recommended value. value = pref->GetRecommendedValue(); ASSERT_TRUE(value); EXPECT_EQ(base::Value::Type::INTEGER, value->type()); - actual_int_value = -1; - EXPECT_TRUE(value->GetAsInteger(&actual_int_value)); - EXPECT_EQ(kRecommendedValue, actual_int_value); + ASSERT_TRUE(value->is_int()); + EXPECT_EQ(kRecommendedValue, value->GetInt()); } TEST(PrefServiceTest, SetTimeValue_RegularTime) { diff --git a/chromium/components/prefs/pref_value_map.cc b/chromium/components/prefs/pref_value_map.cc index 559f827bcec..78adef8fc75 100644 --- a/chromium/components/prefs/pref_value_map.cc +++ b/chromium/components/prefs/pref_value_map.cc @@ -89,7 +89,11 @@ bool PrefValueMap::empty() const { bool PrefValueMap::GetBoolean(const std::string& key, bool* value) const { const base::Value* stored_value = nullptr; - return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value); + if (GetValue(key, &stored_value) && stored_value->is_bool()) { + *value = stored_value->GetBool(); + return true; + } + return false; } void PrefValueMap::SetBoolean(const std::string& key, bool value) { @@ -98,7 +102,11 @@ void PrefValueMap::SetBoolean(const std::string& key, bool value) { bool PrefValueMap::GetString(const std::string& key, std::string* value) const { const base::Value* stored_value = nullptr; - return GetValue(key, &stored_value) && stored_value->GetAsString(value); + if (GetValue(key, &stored_value) && stored_value->is_string()) { + *value = stored_value->GetString(); + return true; + } + return false; } void PrefValueMap::SetString(const std::string& key, const std::string& value) { @@ -107,7 +115,11 @@ void PrefValueMap::SetString(const std::string& key, const std::string& value) { bool PrefValueMap::GetInteger(const std::string& key, int* value) const { const base::Value* stored_value = nullptr; - return GetValue(key, &stored_value) && stored_value->GetAsInteger(value); + if (GetValue(key, &stored_value) && stored_value->is_int()) { + *value = stored_value->GetInt(); + return true; + } + return false; } void PrefValueMap::SetInteger(const std::string& key, const int value) { @@ -137,7 +149,7 @@ void PrefValueMap::GetDifferingKeys( while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) { const int diff = this_pref->first.compare(other_pref->first); if (diff == 0) { - if (!this_pref->second->Equals(other_pref->second)) + if (*this_pref->second != *other_pref->second) differing_keys->push_back(this_pref->first); ++this_pref; ++other_pref; @@ -160,7 +172,8 @@ void PrefValueMap::GetDifferingKeys( std::unique_ptr<base::DictionaryValue> PrefValueMap::AsDictionaryValue() const { auto dictionary = std::make_unique<base::DictionaryValue>(); for (const auto& value : prefs_) - dictionary->Set(value.first, value.second.CreateDeepCopy()); + dictionary->Set(value.first, + base::Value::ToUniquePtrValue(value.second.Clone())); return dictionary; } diff --git a/chromium/components/prefs/prefs_export.h b/chromium/components/prefs/prefs_export.h index e047ad99ab2..b5c8366b955 100644 --- a/chromium/components/prefs/prefs_export.h +++ b/chromium/components/prefs/prefs_export.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PREFS_COMPONENTS_PREFS_EXPORT_H_ -#define COMPONENTS_PREFS_COMPONENTS_PREFS_EXPORT_H_ +#ifndef COMPONENTS_PREFS_PREFS_EXPORT_H_ +#define COMPONENTS_PREFS_PREFS_EXPORT_H_ #if defined(COMPONENT_BUILD) #if defined(WIN32) @@ -26,4 +26,4 @@ #define COMPONENTS_PREFS_EXPORT #endif -#endif // COMPONENTS_PREFS_COMPONENTS_PREFS_EXPORT_H_ +#endif // COMPONENTS_PREFS_PREFS_EXPORT_H_ diff --git a/chromium/components/prefs/scoped_user_pref_update_unittest.cc b/chromium/components/prefs/scoped_user_pref_update_unittest.cc index fa1dc71ae45..431fad1b0f1 100644 --- a/chromium/components/prefs/scoped_user_pref_update_unittest.cc +++ b/chromium/components/prefs/scoped_user_pref_update_unittest.cc @@ -102,9 +102,9 @@ TEST_F(ScopedUserPrefUpdateTest, UpdatingDictionaryPrefWithDefaults) { std::string pref_name = "mypref"; prefs_.registry()->RegisterDictionaryPref(pref_name, std::move(defaults)); - EXPECT_EQ(2u, prefs_.GetDictionary(pref_name)->size()); + EXPECT_EQ(2u, prefs_.GetDictionary(pref_name)->DictSize()); DictionaryPrefUpdate update(&prefs_, pref_name); update->SetKey("thirdkey", base::Value("value")); - EXPECT_EQ(3u, prefs_.GetDictionary(pref_name)->size()); + EXPECT_EQ(3u, prefs_.GetDictionary(pref_name)->DictSize()); } diff --git a/chromium/components/prefs/segregated_pref_store.cc b/chromium/components/prefs/segregated_pref_store.cc new file mode 100644 index 00000000000..65f2c8052db --- /dev/null +++ b/chromium/components/prefs/segregated_pref_store.cc @@ -0,0 +1,224 @@ +// Copyright 2014 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/segregated_pref_store.h" + +#include <utility> + +#include "base/barrier_closure.h" +#include "base/check_op.h" +#include "base/containers/contains.h" +#include "base/notreached.h" +#include "base/values.h" + +SegregatedPrefStore::AggregatingObserver::AggregatingObserver( + SegregatedPrefStore* outer) + : outer_(outer), + failed_sub_initializations_(0), + successful_sub_initializations_(0) {} + +void SegregatedPrefStore::AggregatingObserver::OnPrefValueChanged( + const std::string& key) { + // There is no need to tell clients about changes if they have not yet been + // told about initialization. + if (failed_sub_initializations_ + successful_sub_initializations_ < 2) + return; + + for (auto& observer : outer_->observers_) + observer.OnPrefValueChanged(key); +} + +void SegregatedPrefStore::AggregatingObserver::OnInitializationCompleted( + bool succeeded) { + if (succeeded) + ++successful_sub_initializations_; + else + ++failed_sub_initializations_; + + DCHECK_LE(failed_sub_initializations_ + successful_sub_initializations_, 2); + + if (failed_sub_initializations_ + successful_sub_initializations_ == 2) { + if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) { + PersistentPrefStore::PrefReadError read_error = outer_->GetReadError(); + if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE) + outer_->read_error_delegate_->OnError(read_error); + } + + for (auto& observer : outer_->observers_) + observer.OnInitializationCompleted(successful_sub_initializations_ == 2); + } +} + +SegregatedPrefStore::SegregatedPrefStore( + scoped_refptr<PersistentPrefStore> default_pref_store, + scoped_refptr<PersistentPrefStore> selected_pref_store, + std::set<std::string> selected_pref_names) + : default_pref_store_(std::move(default_pref_store)), + selected_pref_store_(std::move(selected_pref_store)), + selected_preference_names_(std::move(selected_pref_names)), + aggregating_observer_(this) { + default_pref_store_->AddObserver(&aggregating_observer_); + selected_pref_store_->AddObserver(&aggregating_observer_); +} + +void SegregatedPrefStore::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void SegregatedPrefStore::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +bool SegregatedPrefStore::HasObservers() const { + return !observers_.empty(); +} + +bool SegregatedPrefStore::IsInitializationComplete() const { + return default_pref_store_->IsInitializationComplete() && + selected_pref_store_->IsInitializationComplete(); +} + +bool SegregatedPrefStore::GetValue(const std::string& key, + const base::Value** result) const { + return StoreForKey(key)->GetValue(key, result); +} + +std::unique_ptr<base::DictionaryValue> SegregatedPrefStore::GetValues() const { + auto values = default_pref_store_->GetValues(); + auto selected_pref_store_values = selected_pref_store_->GetValues(); + for (const auto& key : selected_preference_names_) { + const base::Value* value = nullptr; + if (selected_pref_store_values->Get(key, &value)) { + values->Set(key, base::Value::ToUniquePtrValue(value->Clone())); + } else { + values->Remove(key, nullptr); + } + } + return values; +} + +void SegregatedPrefStore::SetValue(const std::string& key, + std::unique_ptr<base::Value> value, + uint32_t flags) { + StoreForKey(key)->SetValue(key, std::move(value), flags); +} + +void SegregatedPrefStore::RemoveValue(const std::string& key, uint32_t flags) { + StoreForKey(key)->RemoveValue(key, flags); +} + +void SegregatedPrefStore::RemoveValuesByPrefixSilently( + const std::string& prefix) { + // Since we can't guarantee to have all the prefs in one the pref stores, we + // have to push the removal command down to both of them. + default_pref_store_->RemoveValuesByPrefixSilently(prefix); + selected_pref_store_->RemoveValuesByPrefixSilently(prefix); +} + +bool SegregatedPrefStore::GetMutableValue(const std::string& key, + base::Value** result) { + return StoreForKey(key)->GetMutableValue(key, result); +} + +void SegregatedPrefStore::ReportValueChanged(const std::string& key, + uint32_t flags) { + StoreForKey(key)->ReportValueChanged(key, flags); +} + +void SegregatedPrefStore::SetValueSilently(const std::string& key, + std::unique_ptr<base::Value> value, + uint32_t flags) { + StoreForKey(key)->SetValueSilently(key, std::move(value), flags); +} + +bool SegregatedPrefStore::ReadOnly() const { + return selected_pref_store_->ReadOnly() || default_pref_store_->ReadOnly(); +} + +PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const { + PersistentPrefStore::PrefReadError read_error = + default_pref_store_->GetReadError(); + if (read_error == PersistentPrefStore::PREF_READ_ERROR_NONE) { + read_error = selected_pref_store_->GetReadError(); + // Ignore NO_FILE from selected_pref_store_. + if (read_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE) + read_error = PersistentPrefStore::PREF_READ_ERROR_NONE; + } + return read_error; +} + +PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() { + // Note: Both of these stores own PrefFilters which makes ReadPrefs + // asynchronous. This is okay in this case as only the first call will be + // truly asynchronous, the second call will then unblock the migration in + // TrackedPreferencesMigrator and complete synchronously. + default_pref_store_->ReadPrefs(); + PersistentPrefStore::PrefReadError selected_store_read_error = + selected_pref_store_->ReadPrefs(); + DCHECK_NE(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE, + selected_store_read_error); + + return GetReadError(); +} + +void SegregatedPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { + read_error_delegate_.reset(error_delegate); + default_pref_store_->ReadPrefsAsync(NULL); + selected_pref_store_->ReadPrefsAsync(NULL); +} + +void SegregatedPrefStore::CommitPendingWrite( + base::OnceClosure reply_callback, + base::OnceClosure synchronous_done_callback) { + // A BarrierClosure will run its callback wherever the last instance of the + // returned wrapper is invoked. As such it is guaranteed to respect the reply + // vs synchronous semantics assuming |default_pref_store_| and + // |selected_pref_store_| honor it. + + base::RepeatingClosure reply_callback_wrapper = + reply_callback ? base::BarrierClosure(2, std::move(reply_callback)) + : base::RepeatingClosure(); + + base::RepeatingClosure synchronous_callback_wrapper = + synchronous_done_callback + ? base::BarrierClosure(2, std::move(synchronous_done_callback)) + : base::RepeatingClosure(); + + default_pref_store_->CommitPendingWrite(reply_callback_wrapper, + synchronous_callback_wrapper); + selected_pref_store_->CommitPendingWrite(reply_callback_wrapper, + synchronous_callback_wrapper); +} + +void SegregatedPrefStore::SchedulePendingLossyWrites() { + default_pref_store_->SchedulePendingLossyWrites(); + selected_pref_store_->SchedulePendingLossyWrites(); +} + +void SegregatedPrefStore::ClearMutableValues() { + NOTIMPLEMENTED(); +} + +void SegregatedPrefStore::OnStoreDeletionFromDisk() { + default_pref_store_->OnStoreDeletionFromDisk(); + selected_pref_store_->OnStoreDeletionFromDisk(); +} + +SegregatedPrefStore::~SegregatedPrefStore() { + default_pref_store_->RemoveObserver(&aggregating_observer_); + selected_pref_store_->RemoveObserver(&aggregating_observer_); +} + +PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) { + return (base::Contains(selected_preference_names_, key) ? selected_pref_store_ + : default_pref_store_) + .get(); +} + +const PersistentPrefStore* SegregatedPrefStore::StoreForKey( + const std::string& key) const { + return (base::Contains(selected_preference_names_, key) ? selected_pref_store_ + : default_pref_store_) + .get(); +} diff --git a/chromium/components/prefs/segregated_pref_store.h b/chromium/components/prefs/segregated_pref_store.h new file mode 100644 index 00000000000..9d9b6811c1f --- /dev/null +++ b/chromium/components/prefs/segregated_pref_store.h @@ -0,0 +1,118 @@ +// Copyright 2014 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. + +#ifndef COMPONENTS_PREFS_SEGREGATED_PREF_STORE_H_ +#define COMPONENTS_PREFS_SEGREGATED_PREF_STORE_H_ + +#include <stdint.h> + +#include <memory> +#include <set> +#include <string> + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" +#include "components/prefs/persistent_pref_store.h" +#include "components/prefs/prefs_export.h" + +// Provides a unified PersistentPrefStore implementation that splits its storage +// and retrieval between two underlying PersistentPrefStore instances: a set of +// preference names is used to partition the preferences. +// +// Combines properties of the two stores as follows: +// * The unified read error will be: +// Selected Store Error +// Default Store Error | NO_ERROR | NO_FILE | other selected | +// NO_ERROR | NO_ERROR | NO_ERROR | other selected | +// NO_FILE | NO_FILE | NO_FILE | NO_FILE | +// other default | other default | other default | other default | +// * The unified initialization success, initialization completion, and +// read-only state are the boolean OR of the underlying stores' properties. +class COMPONENTS_PREFS_EXPORT SegregatedPrefStore : public PersistentPrefStore { + public: + // Creates an instance that delegates to |selected_pref_store| for the + // preferences named in |selected_pref_names| and to |default_pref_store| + // for all others. If an unselected preference is present in + // |selected_pref_store| (i.e. because it was previously selected) it will + // be migrated back to |default_pref_store| upon access via a non-const + // method. + SegregatedPrefStore(scoped_refptr<PersistentPrefStore> default_pref_store, + scoped_refptr<PersistentPrefStore> selected_pref_store, + std::set<std::string> selected_pref_names); + + // PrefStore implementation + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + bool HasObservers() const override; + bool IsInitializationComplete() const override; + bool GetValue(const std::string& key, + const base::Value** result) const override; + std::unique_ptr<base::DictionaryValue> GetValues() const override; + + // WriteablePrefStore implementation + void SetValue(const std::string& key, + std::unique_ptr<base::Value> value, + uint32_t flags) override; + void RemoveValue(const std::string& key, uint32_t flags) override; + void RemoveValuesByPrefixSilently(const std::string& prefix) override; + + // PersistentPrefStore implementation + bool GetMutableValue(const std::string& key, base::Value** result) override; + void ReportValueChanged(const std::string& key, uint32_t flags) override; + void SetValueSilently(const std::string& key, + std::unique_ptr<base::Value> value, + uint32_t flags) override; + bool ReadOnly() const override; + PrefReadError GetReadError() const override; + PrefReadError ReadPrefs() override; + void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override; + void CommitPendingWrite( + base::OnceClosure reply_callback = base::OnceClosure(), + base::OnceClosure synchronous_done_callback = + base::OnceClosure()) override; + void SchedulePendingLossyWrites() override; + void ClearMutableValues() override; + void OnStoreDeletionFromDisk() override; + + protected: + ~SegregatedPrefStore() override; + + private: + // Aggregates events from the underlying stores and synthesizes external + // events via |on_initialization|, |read_error_delegate_|, and |observers_|. + class AggregatingObserver : public PrefStore::Observer { + public: + explicit AggregatingObserver(SegregatedPrefStore* outer); + + // PrefStore::Observer implementation + void OnPrefValueChanged(const std::string& key) override; + void OnInitializationCompleted(bool succeeded) override; + + private: + SegregatedPrefStore* outer_; + int failed_sub_initializations_; + int successful_sub_initializations_; + + DISALLOW_COPY_AND_ASSIGN(AggregatingObserver); + }; + + // Returns |selected_pref_store| if |key| is selected and |default_pref_store| + // otherwise. + PersistentPrefStore* StoreForKey(const std::string& key); + const PersistentPrefStore* StoreForKey(const std::string& key) const; + + const scoped_refptr<PersistentPrefStore> default_pref_store_; + const scoped_refptr<PersistentPrefStore> selected_pref_store_; + const std::set<std::string> selected_preference_names_; + + std::unique_ptr<PersistentPrefStore::ReadErrorDelegate> read_error_delegate_; + base::ObserverList<PrefStore::Observer, true>::Unchecked observers_; + AggregatingObserver aggregating_observer_; + + DISALLOW_COPY_AND_ASSIGN(SegregatedPrefStore); +}; + +#endif // COMPONENTS_PREFS_SEGREGATED_PREF_STORE_H_ diff --git a/chromium/components/prefs/segregated_pref_store_unittest.cc b/chromium/components/prefs/segregated_pref_store_unittest.cc new file mode 100644 index 00000000000..4e90ea8c8b1 --- /dev/null +++ b/chromium/components/prefs/segregated_pref_store_unittest.cc @@ -0,0 +1,380 @@ +// Copyright 2014 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/segregated_pref_store.h" + +#include <memory> +#include <set> +#include <string> +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "base/run_loop.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/task_environment.h" +#include "base/values.h" +#include "components/prefs/persistent_pref_store.h" +#include "components/prefs/pref_store_observer_mock.h" +#include "components/prefs/testing_pref_store.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char kSelectedPref[] = "selected_pref"; +const char kUnselectedPref[] = "unselected_pref"; +const char kSharedPref[] = "shared_pref"; + +const char kValue1[] = "value1"; +const char kValue2[] = "value2"; + +class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate { + public: + struct Data { + Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in) + : invoked(invoked_in), read_error(read_error_in) {} + + bool invoked; + PersistentPrefStore::PrefReadError read_error; + }; + + explicit MockReadErrorDelegate(Data* data) : data_(data) { + DCHECK(data_); + EXPECT_FALSE(data_->invoked); + } + + // PersistentPrefStore::ReadErrorDelegate implementation + void OnError(PersistentPrefStore::PrefReadError read_error) override { + EXPECT_FALSE(data_->invoked); + data_->invoked = true; + data_->read_error = read_error; + } + + private: + Data* data_; +}; + +enum class CommitPendingWriteMode { + // Basic mode. + WITHOUT_CALLBACK, + // With reply callback. + WITH_CALLBACK, + // With synchronous notify callback (synchronous after the write -- shouldn't + // require pumping messages to observe). + WITH_SYNCHRONOUS_CALLBACK, +}; + +class SegregatedPrefStoreTest + : public testing::TestWithParam<CommitPendingWriteMode> { + public: + SegregatedPrefStoreTest() + : read_error_delegate_data_(false, + PersistentPrefStore::PREF_READ_ERROR_NONE), + read_error_delegate_( + new MockReadErrorDelegate(&read_error_delegate_data_)) {} + + void SetUp() override { + selected_store_ = new TestingPrefStore; + default_store_ = new TestingPrefStore; + + std::set<std::string> selected_pref_names; + selected_pref_names.insert(kSelectedPref); + selected_pref_names.insert(kSharedPref); + + segregated_store_ = new SegregatedPrefStore(default_store_, selected_store_, + selected_pref_names); + + segregated_store_->AddObserver(&observer_); + } + + void TearDown() override { segregated_store_->RemoveObserver(&observer_); } + + protected: + std::unique_ptr<PersistentPrefStore::ReadErrorDelegate> + GetReadErrorDelegate() { + EXPECT_TRUE(read_error_delegate_); + return std::move(read_error_delegate_); + } + + base::test::TaskEnvironment task_environment_; + + PrefStoreObserverMock observer_; + + scoped_refptr<TestingPrefStore> default_store_; + scoped_refptr<TestingPrefStore> selected_store_; + scoped_refptr<SegregatedPrefStore> segregated_store_; + + MockReadErrorDelegate::Data read_error_delegate_data_; + + private: + std::unique_ptr<MockReadErrorDelegate> read_error_delegate_; +}; + +} // namespace + +TEST_P(SegregatedPrefStoreTest, StoreValues) { + ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->ReadPrefs()); + + // Properly stores new values. + segregated_store_->SetValue(kSelectedPref, + std::make_unique<base::Value>(kValue1), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + segregated_store_->SetValue(kUnselectedPref, + std::make_unique<base::Value>(kValue2), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + + ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL)); + ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL)); + ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL)); + ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL)); + + ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL)); + ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL)); + + ASSERT_FALSE(selected_store_->committed()); + ASSERT_FALSE(default_store_->committed()); + + switch (GetParam()) { + case CommitPendingWriteMode::WITHOUT_CALLBACK: { + segregated_store_->CommitPendingWrite(); + base::RunLoop().RunUntilIdle(); + break; + } + + case CommitPendingWriteMode::WITH_CALLBACK: { + base::RunLoop run_loop; + segregated_store_->CommitPendingWrite(run_loop.QuitClosure()); + run_loop.Run(); + break; + } + + case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK: { + base::WaitableEvent written; + segregated_store_->CommitPendingWrite( + base::OnceClosure(), + base::BindOnce(&base::WaitableEvent::Signal, Unretained(&written))); + written.Wait(); + break; + } + } + + ASSERT_TRUE(selected_store_->committed()); + ASSERT_TRUE(default_store_->committed()); +} + +TEST_F(SegregatedPrefStoreTest, ReadValues) { + selected_store_->SetValue(kSelectedPref, + std::make_unique<base::Value>(kValue1), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + default_store_->SetValue(kUnselectedPref, + std::make_unique<base::Value>(kValue2), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + + // Works properly with values that are already there. + ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->ReadPrefs()); + ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->GetReadError()); + + ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL)); + ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL)); + ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL)); + ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL)); + + ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL)); + ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL)); +} + +TEST_F(SegregatedPrefStoreTest, RemoveValuesByPrefix) { + const std::string subpref_name1 = kSelectedPref; + const std::string subpref_name2 = std::string(kSelectedPref) + "b"; + const std::string other_name = kUnselectedPref; + const std::string prefix = kSelectedPref; + + selected_store_->SetValue(subpref_name1, + std::make_unique<base::Value>(kValue1), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + default_store_->SetValue(subpref_name2, + std::make_unique<base::Value>(kValue2), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + default_store_->SetValue(other_name, std::make_unique<base::Value>(kValue2), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + + ASSERT_TRUE(selected_store_->GetValue(subpref_name1, nullptr)); + ASSERT_TRUE(default_store_->GetValue(subpref_name2, nullptr)); + ASSERT_TRUE(default_store_->GetValue(other_name, nullptr)); + + segregated_store_->RemoveValuesByPrefixSilently(kSelectedPref); + + ASSERT_FALSE(selected_store_->GetValue(subpref_name1, nullptr)); + ASSERT_FALSE(default_store_->GetValue(subpref_name2, nullptr)); + ASSERT_TRUE(default_store_->GetValue(other_name, nullptr)); +} + +TEST_F(SegregatedPrefStoreTest, Observer) { + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->ReadPrefs()); + EXPECT_TRUE(observer_.initialized); + EXPECT_TRUE(observer_.initialization_success); + EXPECT_TRUE(observer_.changed_keys.empty()); + segregated_store_->SetValue(kSelectedPref, + std::make_unique<base::Value>(kValue1), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + observer_.VerifyAndResetChangedKey(kSelectedPref); + segregated_store_->SetValue(kUnselectedPref, + std::make_unique<base::Value>(kValue2), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + observer_.VerifyAndResetChangedKey(kUnselectedPref); +} + +TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) { + // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted + // to PREF_READ_ERROR_NONE. + selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->ReadPrefs()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) { + selected_store_->set_read_error( + PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED, + segregated_store_->ReadPrefs()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileErrorAsync) { + // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted + // to PREF_READ_ERROR_NONE. + selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE); + + default_store_->SetBlockAsyncRead(true); + + EXPECT_FALSE(read_error_delegate_data_.invoked); + + segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release()); + + EXPECT_FALSE(read_error_delegate_data_.invoked); + + default_store_->SetBlockAsyncRead(false); + + // ReadErrorDelegate is not invoked for ERROR_NONE. + EXPECT_FALSE(read_error_delegate_data_.invoked); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->GetReadError()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadNoFileError) { + default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, + segregated_store_->ReadPrefs()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) { + default_store_->set_read_error( + PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED, + segregated_store_->ReadPrefs()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, BothPrefReadError) { + default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE); + selected_store_->set_read_error( + PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, + segregated_store_->ReadPrefs()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) { + default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE); + selected_store_->set_read_error( + PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED); + + selected_store_->SetBlockAsyncRead(true); + + EXPECT_FALSE(read_error_delegate_data_.invoked); + + segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release()); + + EXPECT_FALSE(read_error_delegate_data_.invoked); + + selected_store_->SetBlockAsyncRead(false); + + EXPECT_TRUE(read_error_delegate_data_.invoked); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, + segregated_store_->GetReadError()); + EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, + segregated_store_->GetReadError()); +} + +TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) { + EXPECT_FALSE(segregated_store_->IsInitializationComplete()); + segregated_store_->ReadPrefs(); + EXPECT_TRUE(segregated_store_->IsInitializationComplete()); +} + +TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) { + selected_store_->SetBlockAsyncRead(true); + default_store_->SetBlockAsyncRead(true); + EXPECT_FALSE(segregated_store_->IsInitializationComplete()); + segregated_store_->ReadPrefsAsync(NULL); + EXPECT_FALSE(segregated_store_->IsInitializationComplete()); + selected_store_->SetBlockAsyncRead(false); + EXPECT_FALSE(segregated_store_->IsInitializationComplete()); + default_store_->SetBlockAsyncRead(false); + EXPECT_TRUE(segregated_store_->IsInitializationComplete()); +} + +TEST_F(SegregatedPrefStoreTest, GetValues) { + // To check merge behavior, create selected and default stores so each has a + // key the other doesn't have and they have one key in common. + selected_store_->SetValue(kSelectedPref, + std::make_unique<base::Value>(kValue1), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + default_store_->SetValue(kUnselectedPref, + std::make_unique<base::Value>(kValue2), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + selected_store_->SetValue(kSharedPref, std::make_unique<base::Value>(kValue1), + WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); + + auto values = segregated_store_->GetValues(); + const base::Value* value = nullptr; + // Check that a selected preference is returned. + ASSERT_TRUE(values->Get(kSelectedPref, &value)); + EXPECT_TRUE(base::Value(kValue1).Equals(value)); + + // Check that a a default preference is returned. + ASSERT_TRUE(values->Get(kUnselectedPref, &value)); + EXPECT_TRUE(base::Value(kValue2).Equals(value)); + + // Check that the selected preference is preferred. + ASSERT_TRUE(values->Get(kSharedPref, &value)); + EXPECT_TRUE(base::Value(kValue1).Equals(value)); +} + +INSTANTIATE_TEST_SUITE_P( + WithoutCallback, + SegregatedPrefStoreTest, + ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK)); +INSTANTIATE_TEST_SUITE_P( + WithCallback, + SegregatedPrefStoreTest, + ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK)); +INSTANTIATE_TEST_SUITE_P( + WithSynchronousCallback, + SegregatedPrefStoreTest, + ::testing::Values(CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK)); diff --git a/chromium/components/prefs/testing_pref_store.cc b/chromium/components/prefs/testing_pref_store.cc index f81946d8ae3..5d3d1ec0b5c 100644 --- a/chromium/components/prefs/testing_pref_store.cc +++ b/chromium/components/prefs/testing_pref_store.cc @@ -160,7 +160,11 @@ bool TestingPrefStore::GetString(const std::string& key, if (!prefs_.GetValue(key, &stored_value) || !stored_value) return false; - return stored_value->GetAsString(value); + if (value && stored_value->is_string()) { + *value = stored_value->GetString(); + return true; + } + return stored_value->is_string(); } bool TestingPrefStore::GetInteger(const std::string& key, int* value) const { @@ -168,7 +172,11 @@ bool TestingPrefStore::GetInteger(const std::string& key, int* value) const { if (!prefs_.GetValue(key, &stored_value) || !stored_value) return false; - return stored_value->GetAsInteger(value); + if (value && stored_value->is_int()) { + *value = stored_value->GetInt(); + return true; + } + return stored_value->is_int(); } bool TestingPrefStore::GetBoolean(const std::string& key, bool* value) const { @@ -176,7 +184,11 @@ bool TestingPrefStore::GetBoolean(const std::string& key, bool* value) const { if (!prefs_.GetValue(key, &stored_value) || !stored_value) return false; - return stored_value->GetAsBoolean(value); + if (value && stored_value->is_bool()) { + *value = stored_value->GetBool(); + return true; + } + return stored_value->is_bool(); } void TestingPrefStore::SetBlockAsyncRead(bool block_async_read) { |