Update from https://crrev.com/329939
Includes an update to build_v8.patch. https://crrev.com/329939 includes
mac->android cross compilation fixes.
TBR=cstout@chromium.org
Review URL: https://codereview.chromium.org/1141793003
diff --git a/base/prefs/json_pref_store.cc b/base/prefs/json_pref_store.cc
index 416e43f..da545b8 100644
--- a/base/prefs/json_pref_store.cc
+++ b/base/prefs/json_pref_store.cc
@@ -150,17 +150,10 @@
const base::FilePath& filename,
const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner,
scoped_ptr<PrefFilter> pref_filter)
- : path_(filename),
- sequenced_task_runner_(sequenced_task_runner),
- prefs_(new base::DictionaryValue()),
- read_only_(false),
- writer_(filename, sequenced_task_runner),
- pref_filter_(pref_filter.Pass()),
- initialized_(false),
- filtering_in_progress_(false),
- read_error_(PREF_READ_ERROR_NONE),
- write_count_histogram_(writer_.commit_interval(), path_) {
- DCHECK(!path_.empty());
+ : JsonPrefStore(filename,
+ base::FilePath(),
+ sequenced_task_runner,
+ pref_filter.Pass()) {
}
JsonPrefStore::JsonPrefStore(
@@ -177,6 +170,7 @@
pref_filter_(pref_filter.Pass()),
initialized_(false),
filtering_in_progress_(false),
+ pending_lossy_write_(false),
read_error_(PREF_READ_ERROR_NONE),
write_count_histogram_(writer_.commit_interval(), path_) {
DCHECK(!path_.empty());
@@ -226,7 +220,9 @@
return prefs_->Get(key, result);
}
-void JsonPrefStore::SetValue(const std::string& key, base::Value* value) {
+void JsonPrefStore::SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) {
DCHECK(CalledOnValidThread());
DCHECK(value);
@@ -234,13 +230,14 @@
base::Value* old_value = NULL;
prefs_->Get(key, &old_value);
if (!old_value || !value->Equals(old_value)) {
- prefs_->Set(key, new_value.release());
- ReportValueChanged(key);
+ prefs_->Set(key, new_value.Pass());
+ ReportValueChanged(key, flags);
}
}
void JsonPrefStore::SetValueSilently(const std::string& key,
- base::Value* value) {
+ base::Value* value,
+ uint32 flags) {
DCHECK(CalledOnValidThread());
DCHECK(value);
@@ -248,25 +245,23 @@
base::Value* old_value = NULL;
prefs_->Get(key, &old_value);
if (!old_value || !value->Equals(old_value)) {
- prefs_->Set(key, new_value.release());
- if (!read_only_)
- writer_.ScheduleWrite(this);
+ prefs_->Set(key, new_value.Pass());
+ ScheduleWrite(flags);
}
}
-void JsonPrefStore::RemoveValue(const std::string& key) {
+void JsonPrefStore::RemoveValue(const std::string& key, uint32 flags) {
DCHECK(CalledOnValidThread());
if (prefs_->RemovePath(key, NULL))
- ReportValueChanged(key);
+ ReportValueChanged(key, flags);
}
-void JsonPrefStore::RemoveValueSilently(const std::string& key) {
+void JsonPrefStore::RemoveValueSilently(const std::string& key, uint32 flags) {
DCHECK(CalledOnValidThread());
prefs_->RemovePath(key, NULL);
- if (!read_only_)
- writer_.ScheduleWrite(this);
+ ScheduleWrite(flags);
}
bool JsonPrefStore::ReadOnly() const {
@@ -306,11 +301,16 @@
void JsonPrefStore::CommitPendingWrite() {
DCHECK(CalledOnValidThread());
+ // Schedule a write for any lossy writes that are outstanding to ensure that
+ // they get flushed when this function is called.
+ if (pending_lossy_write_)
+ writer_.ScheduleWrite(this);
+
if (writer_.HasPendingWrite() && !read_only_)
writer_.DoScheduledWrite();
}
-void JsonPrefStore::ReportValueChanged(const std::string& key) {
+void JsonPrefStore::ReportValueChanged(const std::string& key, uint32 flags) {
DCHECK(CalledOnValidThread());
if (pref_filter_)
@@ -318,8 +318,7 @@
FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
- if (!read_only_)
- writer_.ScheduleWrite(this);
+ ScheduleWrite(flags);
}
void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback(
@@ -398,6 +397,8 @@
bool JsonPrefStore::SerializeData(std::string* output) {
DCHECK(CalledOnValidThread());
+ pending_lossy_write_ = false;
+
write_count_histogram_.RecordWriteOccured();
if (pref_filter_)
@@ -429,8 +430,8 @@
initialized_ = true;
- if (schedule_write && !read_only_)
- writer_.ScheduleWrite(this);
+ if (schedule_write)
+ ScheduleWrite(DEFAULT_PREF_WRITE_FLAGS);
if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE)
error_delegate_->OnError(read_error_);
@@ -442,6 +443,16 @@
return;
}
+void JsonPrefStore::ScheduleWrite(uint32 flags) {
+ if (read_only_)
+ return;
+
+ if (flags & LOSSY_PREF_WRITE_FLAG)
+ pending_lossy_write_ = true;
+ else
+ writer_.ScheduleWrite(this);
+}
+
// NOTE: This value should NOT be changed without renaming the histogram
// otherwise it will create incompatible buckets.
const int32_t
diff --git a/base/prefs/json_pref_store.h b/base/prefs/json_pref_store.h
index 1badcf2..ef260eb 100644
--- a/base/prefs/json_pref_store.h
+++ b/base/prefs/json_pref_store.h
@@ -29,6 +29,7 @@
class DictionaryValue;
class FilePath;
class HistogramBase;
+class JsonPrefStoreLossyWriteTest;
class SequencedTaskRunner;
class SequencedWorkerPool;
class Value;
@@ -82,9 +83,13 @@
// PersistentPrefStore overrides:
bool GetMutableValue(const std::string& key, base::Value** result) override;
- void SetValue(const std::string& key, base::Value* value) override;
- void SetValueSilently(const std::string& key, base::Value* value) override;
- void RemoveValue(const std::string& key) override;
+ void SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void SetValueSilently(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void RemoveValue(const std::string& key, uint32 flags) override;
bool ReadOnly() const override;
PrefReadError GetReadError() const override;
// Note this method may be asynchronous if this instance has a |pref_filter_|
@@ -93,11 +98,11 @@
PrefReadError ReadPrefs() override;
void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
void CommitPendingWrite() override;
- void ReportValueChanged(const std::string& key) override;
+ void ReportValueChanged(const std::string& key, uint32 flags) override;
// Just like RemoveValue(), but doesn't notify observers. Used when doing some
// cleanup that shouldn't otherwise alert observers.
- void RemoveValueSilently(const std::string& key);
+ void RemoveValueSilently(const std::string& key, uint32 flags);
// Registers |on_next_successful_write| to be called once, on the next
// successful write event of |writer_|.
@@ -161,6 +166,7 @@
WriteCountHistogramTestMultiplePeriods);
FRIEND_TEST_ALL_PREFIXES(base::JsonPrefStoreTest,
WriteCountHistogramTestPeriodWithGaps);
+ friend class base::JsonPrefStoreLossyWriteTest;
~JsonPrefStore() override;
@@ -186,6 +192,10 @@
scoped_ptr<base::DictionaryValue> prefs,
bool schedule_write);
+ // Schedule a write with the file writer as long as |flags| doesn't contain
+ // WriteablePrefStore::LOSSY_PREF_WRITE_FLAG.
+ void ScheduleWrite(uint32 flags);
+
const base::FilePath path_;
const base::FilePath alternate_path_;
const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
@@ -204,6 +214,7 @@
bool initialized_;
bool filtering_in_progress_;
+ bool pending_lossy_write_;
PrefReadError read_error_;
std::set<std::string> keys_need_empty_value_;
diff --git a/base/prefs/json_pref_store_unittest.cc b/base/prefs/json_pref_store_unittest.cc
index 728a57d..67a8adb 100644
--- a/base/prefs/json_pref_store_unittest.cc
+++ b/base/prefs/json_pref_store_unittest.cc
@@ -108,9 +108,7 @@
void TearDown() override {
// Make sure all pending tasks have been processed (e.g., deleting the
// JsonPrefStore may post write tasks).
- message_loop_.task_runner()->PostTask(FROM_HERE,
- MessageLoop::QuitWhenIdleClosure());
- message_loop_.Run();
+ RunLoop().RunUntilIdle();
}
// The path to temporary directory used to contain the test operations.
@@ -127,7 +125,7 @@
// Test fallback behavior for a nonexistent file.
TEST_F(JsonPrefStoreTest, NonExistentFile) {
- base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
+ base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
ASSERT_FALSE(PathExists(bogus_input_file));
scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
@@ -138,9 +136,9 @@
// Test fallback behavior for a nonexistent file and alternate file.
TEST_F(JsonPrefStoreTest, NonExistentFileAndAlternateFile) {
- base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
+ base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
base::FilePath bogus_alternate_input_file =
- data_dir_.AppendASCII("read_alternate.txt");
+ temp_dir_.path().AppendASCII("read_alternate.txt");
ASSERT_FALSE(PathExists(bogus_input_file));
ASSERT_FALSE(PathExists(bogus_alternate_input_file));
scoped_refptr<JsonPrefStore> pref_store =
@@ -194,7 +192,8 @@
EXPECT_EQ(base::FilePath::StringType(FILE_PATH_LITERAL("/usr/local/")), path);
base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
- pref_store->SetValue(kSomeDirectory, new StringValue(some_path.value()));
+ pref_store->SetValue(kSomeDirectory, new StringValue(some_path.value()),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
EXPECT_TRUE(actual->GetAsString(&path));
EXPECT_EQ(some_path.value(), path);
@@ -205,7 +204,8 @@
EXPECT_TRUE(actual->GetAsBoolean(&boolean));
EXPECT_TRUE(boolean);
- pref_store->SetValue(kNewWindowsInTabs, new FundamentalValue(false));
+ pref_store->SetValue(kNewWindowsInTabs, new FundamentalValue(false),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
EXPECT_TRUE(actual->GetAsBoolean(&boolean));
EXPECT_FALSE(boolean);
@@ -214,13 +214,15 @@
int integer = 0;
EXPECT_TRUE(actual->GetAsInteger(&integer));
EXPECT_EQ(20, integer);
- pref_store->SetValue(kMaxTabs, new FundamentalValue(10));
+ pref_store->SetValue(kMaxTabs, new FundamentalValue(10),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
EXPECT_TRUE(actual->GetAsInteger(&integer));
EXPECT_EQ(10, integer);
pref_store->SetValue(kLongIntPref,
- new StringValue(base::Int64ToString(214748364842LL)));
+ new StringValue(base::Int64ToString(214748364842LL)),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
EXPECT_TRUE(actual->GetAsString(&string_value));
int64 value;
@@ -310,12 +312,14 @@
pref_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
// Set some keys with empty values.
- pref_store->SetValue("list", new base::ListValue);
- pref_store->SetValue("dict", new base::DictionaryValue);
+ pref_store->SetValue("list", new base::ListValue,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ pref_store->SetValue("dict", new base::DictionaryValue,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
// Write to file.
pref_store->CommitPendingWrite();
- MessageLoop::current()->RunUntilIdle();
+ RunLoop().RunUntilIdle();
// Reload.
pref_store = new JsonPrefStore(pref_file, message_loop_.task_runner(),
@@ -341,9 +345,11 @@
base::DictionaryValue* dict = new base::DictionaryValue;
dict->SetString("key", "value");
- pref_store->SetValue("dict", dict);
+ pref_store->SetValue("dict", dict,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- pref_store->RemoveValue("dict.key");
+ pref_store->RemoveValue("dict.key",
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
const base::Value* retrieved_dict = NULL;
bool has_dict = pref_store->GetValue("dict", &retrieved_dict);
@@ -352,7 +358,7 @@
// Tests asynchronous reading of the file when there is no file.
TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) {
- base::FilePath bogus_input_file = data_dir_.AppendASCII("read.txt");
+ base::FilePath bogus_input_file = temp_dir_.path().AppendASCII("read.txt");
ASSERT_FALSE(PathExists(bogus_input_file));
scoped_refptr<JsonPrefStore> pref_store = new JsonPrefStore(
bogus_input_file, message_loop_.task_runner(), scoped_ptr<PrefFilter>());
@@ -801,4 +807,125 @@
ASSERT_EQ(6, samples->TotalCount());
}
+class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
+ protected:
+ void SetUp() override {
+ JsonPrefStoreTest::SetUp();
+ test_file_ = temp_dir_.path().AppendASCII("test.json");
+ }
+
+ // Creates a JsonPrefStore with the given |file_writer|.
+ scoped_refptr<JsonPrefStore> CreatePrefStore() {
+ return new JsonPrefStore(test_file_, message_loop_.task_runner(),
+ scoped_ptr<PrefFilter>());
+ }
+
+ // Return the ImportantFileWriter for a given JsonPrefStore.
+ ImportantFileWriter* GetImportantFileWriter(
+ scoped_refptr<JsonPrefStore> pref_store) {
+ return &(pref_store->writer_);
+ }
+
+ // Get the contents of kTestFile. Pumps the message loop before returning the
+ // result.
+ std::string GetTestFileContents() {
+ RunLoop().RunUntilIdle();
+ std::string file_contents;
+ ReadFileToString(test_file_, &file_contents);
+ return file_contents;
+ }
+
+ private:
+ base::FilePath test_file_;
+};
+
+TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) {
+ scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
+
+ // Set a normal pref and check that it gets scheduled to be written.
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ pref_store->SetValue("normal", new base::StringValue("normal"),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ ASSERT_TRUE(file_writer->HasPendingWrite());
+ file_writer->DoScheduledWrite();
+ ASSERT_EQ("{\"normal\":\"normal\"}", GetTestFileContents());
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+
+ // Set a lossy pref and check that it is not scheduled to be written.
+ // SetValue/RemoveValue.
+ pref_store->SetValue("lossy", new base::StringValue("lossy"),
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ pref_store->RemoveValue("lossy", WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+
+ // SetValueSilently/RemoveValueSilently.
+ pref_store->SetValueSilently("lossy", new base::StringValue("lossy"),
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ pref_store->RemoveValueSilently("lossy",
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+
+ // ReportValueChanged.
+ pref_store->SetValue("lossy", new base::StringValue("lossy"),
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ pref_store->ReportValueChanged("lossy",
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+
+ // Call CommitPendingWrite and check that the lossy pref and the normal pref
+ // are there with the last values set above.
+ pref_store->CommitPendingWrite();
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
+ GetTestFileContents());
+}
+
+TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) {
+ scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
+
+ // Set a lossy pref and check that it is not scheduled to be written.
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ pref_store->SetValue("lossy", new base::StringValue("lossy"),
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+
+ // Set a normal pref and check that it is scheduled to be written.
+ pref_store->SetValue("normal", new base::StringValue("normal"),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ ASSERT_TRUE(file_writer->HasPendingWrite());
+
+ // Call DoScheduledWrite and check both prefs get written.
+ file_writer->DoScheduledWrite();
+ ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
+ GetTestFileContents());
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+}
+
+TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) {
+ scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore();
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store);
+
+ // Set a normal pref and check that it is scheduled to be written.
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+ pref_store->SetValue("normal", new base::StringValue("normal"),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ ASSERT_TRUE(file_writer->HasPendingWrite());
+
+ // Set a lossy pref and check that the write is still scheduled.
+ pref_store->SetValue("lossy", new base::StringValue("lossy"),
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG);
+ ASSERT_TRUE(file_writer->HasPendingWrite());
+
+ // Call DoScheduledWrite and check both prefs get written.
+ file_writer->DoScheduledWrite();
+ ASSERT_EQ("{\"lossy\":\"lossy\",\"normal\":\"normal\"}",
+ GetTestFileContents());
+ ASSERT_FALSE(file_writer->HasPendingWrite());
+}
+
} // namespace base
diff --git a/base/prefs/overlay_user_pref_store.cc b/base/prefs/overlay_user_pref_store.cc
index a708bb6..e93dffd 100644
--- a/base/prefs/overlay_user_pref_store.cc
+++ b/base/prefs/overlay_user_pref_store.cc
@@ -63,34 +63,36 @@
}
void OverlayUserPrefStore::SetValue(const std::string& key,
- base::Value* value) {
+ base::Value* value,
+ uint32 flags) {
if (!ShallBeStoredInOverlay(key)) {
- underlay_->SetValue(GetUnderlayKey(key), value);
+ underlay_->SetValue(GetUnderlayKey(key), value, flags);
return;
}
if (overlay_.SetValue(key, value))
- ReportValueChanged(key);
+ ReportValueChanged(key, flags);
}
void OverlayUserPrefStore::SetValueSilently(const std::string& key,
- base::Value* value) {
+ base::Value* value,
+ uint32 flags) {
if (!ShallBeStoredInOverlay(key)) {
- underlay_->SetValueSilently(GetUnderlayKey(key), value);
+ underlay_->SetValueSilently(GetUnderlayKey(key), value, flags);
return;
}
overlay_.SetValue(key, value);
}
-void OverlayUserPrefStore::RemoveValue(const std::string& key) {
+void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32 flags) {
if (!ShallBeStoredInOverlay(key)) {
- underlay_->RemoveValue(GetUnderlayKey(key));
+ underlay_->RemoveValue(GetUnderlayKey(key), flags);
return;
}
if (overlay_.RemoveValue(key))
- ReportValueChanged(key);
+ ReportValueChanged(key, flags);
}
bool OverlayUserPrefStore::ReadOnly() const {
@@ -119,13 +121,14 @@
// We do not write our content intentionally.
}
-void OverlayUserPrefStore::ReportValueChanged(const std::string& key) {
+void OverlayUserPrefStore::ReportValueChanged(const std::string& key,
+ uint32 flags) {
FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
}
void OverlayUserPrefStore::OnPrefValueChanged(const std::string& key) {
if (!overlay_.GetValue(GetOverlayKey(key), NULL))
- ReportValueChanged(GetOverlayKey(key));
+ ReportValueChanged(GetOverlayKey(key), DEFAULT_PREF_WRITE_FLAGS);
}
void OverlayUserPrefStore::OnInitializationCompleted(bool succeeded) {
diff --git a/base/prefs/overlay_user_pref_store.h b/base/prefs/overlay_user_pref_store.h
index 5194a7b..04c309d 100644
--- a/base/prefs/overlay_user_pref_store.h
+++ b/base/prefs/overlay_user_pref_store.h
@@ -39,15 +39,19 @@
// Methods of PersistentPrefStore.
bool GetMutableValue(const std::string& key, base::Value** result) override;
- void SetValue(const std::string& key, base::Value* value) override;
- void SetValueSilently(const std::string& key, base::Value* value) override;
- void RemoveValue(const std::string& key) override;
+ void SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void SetValueSilently(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void RemoveValue(const std::string& key, uint32 flags) override;
bool ReadOnly() const override;
PrefReadError GetReadError() const override;
PrefReadError ReadPrefs() override;
void ReadPrefsAsync(ReadErrorDelegate* delegate) override;
void CommitPendingWrite() override;
- void ReportValueChanged(const std::string& key) override;
+ void ReportValueChanged(const std::string& key, uint32 flags) override;
// Methods of PrefStore::Observer.
void OnPrefValueChanged(const std::string& key) override;
diff --git a/base/prefs/overlay_user_pref_store_unittest.cc b/base/prefs/overlay_user_pref_store_unittest.cc
index 9836fbf..06b4ec9 100644
--- a/base/prefs/overlay_user_pref_store_unittest.cc
+++ b/base/prefs/overlay_user_pref_store_unittest.cc
@@ -48,38 +48,47 @@
overlay_->AddObserver(&obs);
// Check that underlay first value is reported.
- underlay_->SetValue(overlay_key, new FundamentalValue(42));
+ underlay_->SetValue(overlay_key, new FundamentalValue(42),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(overlay_key);
// Check that underlay overwriting is reported.
- underlay_->SetValue(overlay_key, new FundamentalValue(43));
+ underlay_->SetValue(overlay_key, new FundamentalValue(43),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(overlay_key);
// Check that overwriting change in overlay is reported.
- overlay_->SetValue(overlay_key, new FundamentalValue(44));
+ overlay_->SetValue(overlay_key, new FundamentalValue(44),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(overlay_key);
// Check that hidden underlay change is not reported.
- underlay_->SetValue(overlay_key, new FundamentalValue(45));
+ underlay_->SetValue(overlay_key, new FundamentalValue(45),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
// Check that overlay remove is reported.
- overlay_->RemoveValue(overlay_key);
+ overlay_->RemoveValue(overlay_key,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(overlay_key);
// Check that underlay remove is reported.
- underlay_->RemoveValue(overlay_key);
+ underlay_->RemoveValue(overlay_key,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(overlay_key);
// Check respecting of silence.
- overlay_->SetValueSilently(overlay_key, new FundamentalValue(46));
+ overlay_->SetValueSilently(overlay_key, new FundamentalValue(46),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
overlay_->RemoveObserver(&obs);
// Check successful unsubscription.
- underlay_->SetValue(overlay_key, new FundamentalValue(47));
- overlay_->SetValue(overlay_key, new FundamentalValue(48));
+ underlay_->SetValue(overlay_key, new FundamentalValue(47),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ overlay_->SetValue(overlay_key, new FundamentalValue(48),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
}
@@ -88,7 +97,8 @@
EXPECT_FALSE(overlay_->GetValue(overlay_key, &value));
EXPECT_FALSE(underlay_->GetValue(overlay_key, &value));
- underlay_->SetValue(overlay_key, new FundamentalValue(42));
+ underlay_->SetValue(overlay_key, new FundamentalValue(42),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
// Value shines through:
EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
@@ -97,7 +107,8 @@
EXPECT_TRUE(underlay_->GetValue(overlay_key, &value));
EXPECT_TRUE(base::FundamentalValue(42).Equals(value));
- overlay_->SetValue(overlay_key, new FundamentalValue(43));
+ overlay_->SetValue(overlay_key, new FundamentalValue(43),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
@@ -105,7 +116,8 @@
EXPECT_TRUE(underlay_->GetValue(overlay_key, &value));
EXPECT_TRUE(base::FundamentalValue(42).Equals(value));
- overlay_->RemoveValue(overlay_key);
+ overlay_->RemoveValue(overlay_key,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
// Value shines through:
EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
@@ -117,7 +129,8 @@
// Check that GetMutableValue does not return the dictionary of the underlay.
TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) {
- underlay_->SetValue(overlay_key, new DictionaryValue);
+ underlay_->SetValue(overlay_key, new DictionaryValue,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
Value* modify = NULL;
EXPECT_TRUE(overlay_->GetMutableValue(overlay_key, &modify));
@@ -146,11 +159,13 @@
const Value* value = NULL;
// Check that underlay first value is reported.
- underlay_->SetValue(regular_key, new FundamentalValue(42));
+ underlay_->SetValue(regular_key, new FundamentalValue(42),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(regular_key);
// Check that underlay overwriting is reported.
- underlay_->SetValue(regular_key, new FundamentalValue(43));
+ underlay_->SetValue(regular_key, new FundamentalValue(43),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(regular_key);
// Check that we get this value from the overlay
@@ -158,7 +173,8 @@
EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
// Check that overwriting change in overlay is reported.
- overlay_->SetValue(regular_key, new FundamentalValue(44));
+ overlay_->SetValue(regular_key, new FundamentalValue(44),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(regular_key);
// Check that we get this value from the overlay and the underlay.
@@ -168,7 +184,8 @@
EXPECT_TRUE(base::FundamentalValue(44).Equals(value));
// Check that overlay remove is reported.
- overlay_->RemoveValue(regular_key);
+ overlay_->RemoveValue(regular_key,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(regular_key);
// Check that value was removed from overlay and underlay
@@ -176,14 +193,17 @@
EXPECT_FALSE(underlay_->GetValue(regular_key, &value));
// Check respecting of silence.
- overlay_->SetValueSilently(regular_key, new FundamentalValue(46));
+ overlay_->SetValueSilently(regular_key, new FundamentalValue(46),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
overlay_->RemoveObserver(&obs);
// Check successful unsubscription.
- underlay_->SetValue(regular_key, new FundamentalValue(47));
- overlay_->SetValue(regular_key, new FundamentalValue(48));
+ underlay_->SetValue(regular_key, new FundamentalValue(47),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ overlay_->SetValue(regular_key, new FundamentalValue(48),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
}
@@ -196,11 +216,13 @@
// Check that if there is no override in the overlay, changing underlay value
// is reported as changing an overlay value.
- underlay_->SetValue(mapped_underlay_key, new FundamentalValue(42));
+ underlay_->SetValue(mapped_underlay_key, new FundamentalValue(42),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(mapped_overlay_key);
// Check that underlay overwriting is reported.
- underlay_->SetValue(mapped_underlay_key, new FundamentalValue(43));
+ underlay_->SetValue(mapped_underlay_key, new FundamentalValue(43),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(mapped_overlay_key);
// Check that we get this value from the overlay with both keys
@@ -211,7 +233,8 @@
EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
// Check that overwriting change in overlay is reported.
- overlay_->SetValue(mapped_overlay_key, new FundamentalValue(44));
+ overlay_->SetValue(mapped_overlay_key, new FundamentalValue(44),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(mapped_overlay_key);
// Check that we get an overriden value from overlay, while reading the
@@ -224,15 +247,18 @@
EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
// Check that hidden underlay change is not reported.
- underlay_->SetValue(mapped_underlay_key, new FundamentalValue(45));
+ underlay_->SetValue(mapped_underlay_key, new FundamentalValue(45),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
// Check that overlay remove is reported.
- overlay_->RemoveValue(mapped_overlay_key);
+ overlay_->RemoveValue(mapped_overlay_key,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(mapped_overlay_key);
// Check that underlay remove is reported.
- underlay_->RemoveValue(mapped_underlay_key);
+ underlay_->RemoveValue(mapped_underlay_key,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
obs.VerifyAndResetChangedKey(mapped_overlay_key);
// Check that value was removed.
@@ -240,14 +266,17 @@
EXPECT_FALSE(overlay_->GetValue(mapped_underlay_key, &value));
// Check respecting of silence.
- overlay_->SetValueSilently(mapped_overlay_key, new FundamentalValue(46));
+ overlay_->SetValueSilently(mapped_overlay_key, new FundamentalValue(46),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
overlay_->RemoveObserver(&obs);
// Check successful unsubscription.
- underlay_->SetValue(mapped_underlay_key, new FundamentalValue(47));
- overlay_->SetValue(mapped_overlay_key, new FundamentalValue(48));
+ underlay_->SetValue(mapped_underlay_key, new FundamentalValue(47),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ overlay_->SetValue(mapped_overlay_key, new FundamentalValue(48),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(obs.changed_keys.empty());
}
diff --git a/base/prefs/pref_registry.h b/base/prefs/pref_registry.h
index cc5804e..caf2a1a 100644
--- a/base/prefs/pref_registry.h
+++ b/base/prefs/pref_registry.h
@@ -32,11 +32,15 @@
// behave or be stored. This will be passed in a bitmask when the pref is
// registered. Subclasses of PrefRegistry can specify their own flags. Care
// must be taken to ensure none of these overlap with the flags below.
- enum PrefRegistrationFlags {
+ enum PrefRegistrationFlags : uint32 {
// No flags are specified.
NO_REGISTRATION_FLAGS = 0,
// The first 8 bits are reserved for subclasses of PrefRegistry to use.
+
+ // This marks the pref as "lossy". There is no strict time guarantee on when
+ // a lossy pref will be persisted to permanent storage when it is modified.
+ LOSSY_PREF = 1 << 8,
};
typedef PrefValueMap::const_iterator const_iterator;
diff --git a/base/prefs/pref_service.cc b/base/prefs/pref_service.cc
index 3ccdae7..6e1d58c 100644
--- a/base/prefs/pref_service.cc
+++ b/base/prefs/pref_service.cc
@@ -38,6 +38,19 @@
base::Callback<void(PersistentPrefStore::PrefReadError)> callback_;
};
+// Returns the WriteablePrefStore::PrefWriteFlags for the pref with the given
+// |path|.
+uint32 GetWriteFlags(const PrefService::Preference* pref) {
+ uint32 write_flags = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
+
+ if (!pref)
+ return write_flags;
+
+ if (pref->registration_flags() & PrefRegistry::LOSSY_PREF)
+ write_flags |= WriteablePrefStore::LOSSY_PREF_WRITE_FLAG;
+ return write_flags;
+}
+
} // namespace
PrefService::PrefService(
@@ -177,8 +190,7 @@
DCHECK(CalledOnValidThread());
scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue);
for (const auto& it : *pref_registry_) {
- const base::Value* value = GetPreferenceValue(it.first);
- out->Set(it.first, value->DeepCopy());
+ out->Set(it.first, GetPreferenceValue(it.first)->CreateDeepCopy());
}
return out.Pass();
}
@@ -191,7 +203,7 @@
const Preference* pref = FindPreference(it.first);
if (pref->IsDefaultValue())
continue;
- out->Set(it.first, pref->GetValue()->DeepCopy());
+ out->Set(it.first, pref->GetValue()->CreateDeepCopy());
}
return out.Pass();
}
@@ -203,7 +215,7 @@
for (const auto& it : *pref_registry_) {
const base::Value* value = GetPreferenceValue(it.first);
DCHECK(value);
- out->SetWithoutPathExpansion(it.first, value->DeepCopy());
+ out->SetWithoutPathExpansion(it.first, value->CreateDeepCopy());
}
return out.Pass();
}
@@ -357,7 +369,7 @@
NOTREACHED() << "Trying to clear an unregistered pref: " << path;
return;
}
- user_pref_store_->RemoveValue(path);
+ user_pref_store_->RemoveValue(path, GetWriteFlags(pref));
}
void PrefService::Set(const std::string& path, const base::Value& value) {
@@ -454,14 +466,14 @@
} else {
NOTREACHED();
}
- user_pref_store_->SetValueSilently(path, value);
+ user_pref_store_->SetValueSilently(path, value, GetWriteFlags(pref));
}
return value;
}
void PrefService::ReportUserPrefChanged(const std::string& key) {
DCHECK(CalledOnValidThread());
- user_pref_store_->ReportValueChanged(key);
+ user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
}
void PrefService::SetUserPrefValue(const std::string& path,
@@ -481,7 +493,7 @@
return;
}
- user_pref_store_->SetValue(path, owned_value.release());
+ user_pref_store_->SetValue(path, owned_value.release(), GetWriteFlags(pref));
}
void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) {
@@ -496,6 +508,9 @@
base::Value::Type type)
: name_(name), type_(type), pref_service_(service) {
DCHECK(service);
+ // Cache the registration flags at creation time to avoid multiple map lookups
+ // later.
+ registration_flags_ = service->pref_registry_->GetRegistrationFlags(name_);
}
const std::string PrefService::Preference::name() const {
diff --git a/base/prefs/pref_service.h b/base/prefs/pref_service.h
index d9b03c9..1fc6c12 100644
--- a/base/prefs/pref_service.h
+++ b/base/prefs/pref_service.h
@@ -128,6 +128,10 @@
// the Preference.
bool IsExtensionModifiable() const;
+ // Return the registration flags for this pref as a bitmask of
+ // PrefRegistry::PrefRegistrationFlags.
+ uint32 registration_flags() const { return registration_flags_; }
+
private:
friend class PrefService;
@@ -139,6 +143,8 @@
const base::Value::Type type_;
+ uint32 registration_flags_;
+
// Reference to the PrefService in which this pref was created.
const PrefService* pref_service_;
};
@@ -307,6 +313,7 @@
// Give access to ReportUserPrefChanged() and GetMutableUserPref().
friend class subtle::ScopedUserPrefUpdateBase;
+ friend class PrefServiceTest_WriteablePrefStoreFlags_Test;
// Registration of pref change observers must be done using the
// PrefChangeRegistrar, which is declared as a friend here to grant it
diff --git a/base/prefs/pref_service_unittest.cc b/base/prefs/pref_service_unittest.cc
index 36ad887..262d7e9 100644
--- a/base/prefs/pref_service_unittest.cc
+++ b/base/prefs/pref_service_unittest.cc
@@ -8,6 +8,7 @@
#include "base/prefs/mock_pref_change_callback.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service_factory.h"
#include "base/prefs/pref_value_store.h"
#include "base/prefs/testing_pref_service.h"
#include "base/prefs/testing_pref_store.h"
@@ -227,6 +228,115 @@
EXPECT_EQ(kRecommendedValue, actual_int_value);
}
+// A PrefStore which just stores the last write flags that were used to write
+// values to it.
+class WriteFlagChecker : public TestingPrefStore {
+ public:
+ WriteFlagChecker() {}
+
+ void ReportValueChanged(const std::string& key, uint32 flags) override {
+ SetLastWriteFlags(flags);
+ }
+
+ void SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) override {
+ SetLastWriteFlags(flags);
+ delete value;
+ }
+
+ void SetValueSilently(const std::string& key,
+ base::Value* value,
+ uint32 flags) override {
+ SetLastWriteFlags(flags);
+ delete value;
+ }
+
+ void RemoveValue(const std::string& key, uint32 flags) override {
+ SetLastWriteFlags(flags);
+ }
+
+ uint32 GetLastFlagsAndClear() {
+ CHECK(last_write_flags_set_);
+ uint32 result = last_write_flags_;
+ last_write_flags_set_ = false;
+ last_write_flags_ = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
+ return result;
+ }
+
+ bool last_write_flags_set() { return last_write_flags_set_; }
+
+ private:
+ ~WriteFlagChecker() override {}
+
+ void SetLastWriteFlags(uint32 flags) {
+ CHECK(!last_write_flags_set_);
+ last_write_flags_set_ = true;
+ last_write_flags_ = flags;
+ }
+
+ bool last_write_flags_set_ = false;
+ uint32 last_write_flags_ = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
+};
+
+TEST(PrefServiceTest, WriteablePrefStoreFlags) {
+ scoped_refptr<WriteFlagChecker> flag_checker(new WriteFlagChecker);
+ scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple);
+ base::PrefServiceFactory factory;
+ factory.set_user_prefs(flag_checker);
+ scoped_ptr<PrefService> prefs(factory.Create(registry.get()));
+
+ // The first 8 bits of write flags are reserved for subclasses. Create a
+ // custom flag in this range
+ uint32 kCustomRegistrationFlag = 1 << 2;
+
+ // A map of the registration flags that will be tested and the write flags
+ // they are expected to convert to.
+ struct RegistrationToWriteFlags {
+ const char* pref_name;
+ uint32 registration_flags;
+ uint32 write_flags;
+ };
+ const RegistrationToWriteFlags kRegistrationToWriteFlags[] = {
+ {"none",
+ PrefRegistry::NO_REGISTRATION_FLAGS,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS},
+ {"lossy",
+ PrefRegistry::LOSSY_PREF,
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG},
+ {"custom",
+ kCustomRegistrationFlag,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS},
+ {"lossyandcustom",
+ PrefRegistry::LOSSY_PREF | kCustomRegistrationFlag,
+ WriteablePrefStore::LOSSY_PREF_WRITE_FLAG}};
+
+ for (size_t i = 0; i < arraysize(kRegistrationToWriteFlags); ++i) {
+ RegistrationToWriteFlags entry = kRegistrationToWriteFlags[i];
+ registry->RegisterDictionaryPref(
+ entry.pref_name, new base::DictionaryValue(), entry.registration_flags);
+
+ SCOPED_TRACE("Currently testing pref with name: " +
+ std::string(entry.pref_name));
+
+ prefs->GetMutableUserPref(entry.pref_name, base::Value::TYPE_DICTIONARY);
+ EXPECT_TRUE(flag_checker->last_write_flags_set());
+ EXPECT_EQ(entry.write_flags, flag_checker->GetLastFlagsAndClear());
+
+ prefs->ReportUserPrefChanged(entry.pref_name);
+ EXPECT_TRUE(flag_checker->last_write_flags_set());
+ EXPECT_EQ(entry.write_flags, flag_checker->GetLastFlagsAndClear());
+
+ prefs->ClearPref(entry.pref_name);
+ EXPECT_TRUE(flag_checker->last_write_flags_set());
+ EXPECT_EQ(entry.write_flags, flag_checker->GetLastFlagsAndClear());
+
+ prefs->SetUserPrefValue(entry.pref_name, new base::DictionaryValue());
+ EXPECT_TRUE(flag_checker->last_write_flags_set());
+ EXPECT_EQ(entry.write_flags, flag_checker->GetLastFlagsAndClear());
+ }
+}
+
class PrefServiceSetValueTest : public testing::Test {
protected:
static const char kName[];
diff --git a/base/prefs/testing_pref_service.h b/base/prefs/testing_pref_service.h
index 40fd66a..7587383 100644
--- a/base/prefs/testing_pref_service.h
+++ b/base/prefs/testing_pref_service.h
@@ -182,13 +182,14 @@
SetPref(TestingPrefStore* pref_store,
const std::string& path,
base::Value* value) {
- pref_store->SetValue(path, value);
+ pref_store->SetValue(path, value,
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
}
template <class SuperPrefService, class ConstructionPrefRegistry>
void TestingPrefServiceBase<SuperPrefService, ConstructionPrefRegistry>::
RemovePref(TestingPrefStore* pref_store, const std::string& path) {
- pref_store->RemoveValue(path);
+ pref_store->RemoveValue(path, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
}
#endif // BASE_PREFS_TESTING_PREF_SERVICE_H_
diff --git a/base/prefs/testing_pref_store.cc b/base/prefs/testing_pref_store.cc
index f20824e..35c9763 100644
--- a/base/prefs/testing_pref_store.cc
+++ b/base/prefs/testing_pref_store.cc
@@ -42,7 +42,9 @@
return init_complete_;
}
-void TestingPrefStore::SetValue(const std::string& key, base::Value* value) {
+void TestingPrefStore::SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) {
if (prefs_.SetValue(key, value)) {
committed_ = false;
NotifyPrefValueChanged(key);
@@ -50,12 +52,13 @@
}
void TestingPrefStore::SetValueSilently(const std::string& key,
- base::Value* value) {
+ base::Value* value,
+ uint32 flags) {
if (prefs_.SetValue(key, value))
committed_ = false;
}
-void TestingPrefStore::RemoveValue(const std::string& key) {
+void TestingPrefStore::RemoveValue(const std::string& key, uint32 flags) {
if (prefs_.RemoveValue(key)) {
committed_ = false;
NotifyPrefValueChanged(key);
@@ -103,21 +106,22 @@
Observer, observers_, OnInitializationCompleted(read_success_));
}
-void TestingPrefStore::ReportValueChanged(const std::string& key) {
+void TestingPrefStore::ReportValueChanged(const std::string& key,
+ uint32 flags) {
FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key));
}
void TestingPrefStore::SetString(const std::string& key,
const std::string& value) {
- SetValue(key, new base::StringValue(value));
+ SetValue(key, new base::StringValue(value), DEFAULT_PREF_WRITE_FLAGS);
}
void TestingPrefStore::SetInteger(const std::string& key, int value) {
- SetValue(key, new base::FundamentalValue(value));
+ SetValue(key, new base::FundamentalValue(value), DEFAULT_PREF_WRITE_FLAGS);
}
void TestingPrefStore::SetBoolean(const std::string& key, bool value) {
- SetValue(key, new base::FundamentalValue(value));
+ SetValue(key, new base::FundamentalValue(value), DEFAULT_PREF_WRITE_FLAGS);
}
bool TestingPrefStore::GetString(const std::string& key,
diff --git a/base/prefs/testing_pref_store.h b/base/prefs/testing_pref_store.h
index 866b4ae..3de5cac 100644
--- a/base/prefs/testing_pref_store.h
+++ b/base/prefs/testing_pref_store.h
@@ -30,10 +30,14 @@
// PersistentPrefStore overrides:
bool GetMutableValue(const std::string& key, base::Value** result) override;
- void ReportValueChanged(const std::string& key) override;
- void SetValue(const std::string& key, base::Value* value) override;
- void SetValueSilently(const std::string& key, base::Value* value) override;
- void RemoveValue(const std::string& key) override;
+ void ReportValueChanged(const std::string& key, uint32 flags) override;
+ void SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void SetValueSilently(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void RemoveValue(const std::string& key, uint32 flags) override;
bool ReadOnly() const override;
PrefReadError GetReadError() const override;
PersistentPrefStore::PrefReadError ReadPrefs() override;
diff --git a/base/prefs/value_map_pref_store.cc b/base/prefs/value_map_pref_store.cc
index 8af1282..d850150 100644
--- a/base/prefs/value_map_pref_store.cc
+++ b/base/prefs/value_map_pref_store.cc
@@ -28,12 +28,14 @@
return observers_.might_have_observers();
}
-void ValueMapPrefStore::SetValue(const std::string& key, base::Value* value) {
+void ValueMapPrefStore::SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) {
if (prefs_.SetValue(key, value))
FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key));
}
-void ValueMapPrefStore::RemoveValue(const std::string& key) {
+void ValueMapPrefStore::RemoveValue(const std::string& key, uint32 flags) {
if (prefs_.RemoveValue(key))
FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key));
}
@@ -43,12 +45,14 @@
return prefs_.GetValue(key, value);
}
-void ValueMapPrefStore::ReportValueChanged(const std::string& key) {
+void ValueMapPrefStore::ReportValueChanged(const std::string& key,
+ uint32 flags) {
FOR_EACH_OBSERVER(Observer, observers_, OnPrefValueChanged(key));
}
void ValueMapPrefStore::SetValueSilently(const std::string& key,
- base::Value* value) {
+ base::Value* value,
+ uint32 flags) {
prefs_.SetValue(key, value);
}
diff --git a/base/prefs/value_map_pref_store.h b/base/prefs/value_map_pref_store.h
index 8c515ed..86c94bb 100644
--- a/base/prefs/value_map_pref_store.h
+++ b/base/prefs/value_map_pref_store.h
@@ -28,11 +28,15 @@
bool HasObservers() const override;
// WriteablePrefStore overrides:
- void SetValue(const std::string& key, base::Value* value) override;
- void RemoveValue(const std::string& key) override;
+ void SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
+ void RemoveValue(const std::string& key, uint32 flags) override;
bool GetMutableValue(const std::string& key, base::Value** value) override;
- void ReportValueChanged(const std::string& key) override;
- void SetValueSilently(const std::string& key, base::Value* value) override;
+ void ReportValueChanged(const std::string& key, uint32 flags) override;
+ void SetValueSilently(const std::string& key,
+ base::Value* value,
+ uint32 flags) override;
protected:
~ValueMapPrefStore() override;
diff --git a/base/prefs/writeable_pref_store.h b/base/prefs/writeable_pref_store.h
index 5ebab64..d85b4c8 100644
--- a/base/prefs/writeable_pref_store.h
+++ b/base/prefs/writeable_pref_store.h
@@ -17,14 +17,27 @@
// A pref store that can be written to as well as read from.
class BASE_PREFS_EXPORT WriteablePrefStore : public PrefStore {
public:
+ // PrefWriteFlags can be used to change the way a pref will be written to
+ // storage.
+ enum PrefWriteFlags : uint32 {
+ // No flags are specified.
+ DEFAULT_PREF_WRITE_FLAGS = 0,
+
+ // This marks the pref as "lossy". There is no strict time guarantee on when
+ // a lossy pref will be persisted to permanent storage when it is modified.
+ LOSSY_PREF_WRITE_FLAG = 1 << 1
+ };
+
WriteablePrefStore() {}
// Sets a |value| for |key| in the store. Assumes ownership of |value|, which
- // must be non-NULL.
- virtual void SetValue(const std::string& key, base::Value* value) = 0;
+ // must be non-NULL. |flags| is a bitmask of PrefWriteFlags.
+ virtual void SetValue(const std::string& key,
+ base::Value* value,
+ uint32 flags) = 0;
// Removes the value for |key|.
- virtual void RemoveValue(const std::string& key) = 0;
+ virtual void RemoveValue(const std::string& key, uint32 flags) = 0;
// Equivalent to PrefStore::GetValue but returns a mutable value.
virtual bool GetMutableValue(const std::string& key,
@@ -34,13 +47,17 @@
// if one retrieves a list or dictionary with GetMutableValue and change its
// value. SetValue takes care of notifications itself. Note that
// ReportValueChanged will trigger notifications even if nothing has changed.
- virtual void ReportValueChanged(const std::string& key) = 0;
+ // |flags| is a bitmask of PrefWriteFlags.
+ virtual void ReportValueChanged(const std::string& key, uint32 flags) = 0;
// Same as SetValue, but doesn't generate notifications. This is used by
// PrefService::GetMutableUserPref() in order to put empty entries
// into the user pref store. Using SetValue is not an option since existing
- // tests rely on the number of notifications generated.
- virtual void SetValueSilently(const std::string& key, base::Value* value) = 0;
+ // tests rely on the number of notifications generated. |flags| is a bitmask
+ // of PrefWriteFlags.
+ virtual void SetValueSilently(const std::string& key,
+ base::Value* value,
+ uint32 flags) = 0;
protected:
~WriteablePrefStore() override {}