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 {}