summaryrefslogtreecommitdiff
path: root/chromium/components/prefs
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-03 13:32:17 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 14:31:55 +0200
commit21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch)
tree91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/components/prefs
parent03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff)
downloadqtwebengine-chromium-21ba0c5d4bf8fba15dddd97cd693bad2358b77fd.tar.gz
BASELINE: Update Chromium to 92.0.4515.166
Change-Id: I42a050486714e9e54fc271f2a8939223a02ae364
Diffstat (limited to 'chromium/components/prefs')
-rw-r--r--chromium/components/prefs/BUILD.gn3
-rw-r--r--chromium/components/prefs/DIR_METADATA2
-rw-r--r--chromium/components/prefs/android/DIR_METADATA3
-rw-r--r--chromium/components/prefs/command_line_pref_store.cc1
-rw-r--r--chromium/components/prefs/command_line_pref_store.h1
-rw-r--r--chromium/components/prefs/json_pref_store.cc4
-rw-r--r--chromium/components/prefs/json_pref_store_unittest.cc36
-rw-r--r--chromium/components/prefs/mock_pref_change_callback.h2
-rw-r--r--chromium/components/prefs/overlay_user_pref_store.cc2
-rw-r--r--chromium/components/prefs/overlay_user_pref_store_unittest.cc2
-rw-r--r--chromium/components/prefs/persistent_pref_store.h2
-rw-r--r--chromium/components/prefs/pref_member.cc37
-rw-r--r--chromium/components/prefs/pref_service.cc26
-rw-r--r--chromium/components/prefs/pref_service_unittest.cc35
-rw-r--r--chromium/components/prefs/pref_value_map.cc23
-rw-r--r--chromium/components/prefs/prefs_export.h6
-rw-r--r--chromium/components/prefs/scoped_user_pref_update_unittest.cc4
-rw-r--r--chromium/components/prefs/segregated_pref_store.cc224
-rw-r--r--chromium/components/prefs/segregated_pref_store.h118
-rw-r--r--chromium/components/prefs/segregated_pref_store_unittest.cc380
-rw-r--r--chromium/components/prefs/testing_pref_store.cc18
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) {