Index: chrome/common/pref_service.cc |
diff --git a/chrome/common/pref_service.cc b/chrome/common/pref_service.cc |
index 12ed13eba22c4be6eae1cb03b0486c5e7c2e0c37..74d8805230a48892ec4c3e2bbb2b6ec557d9d995 100644 |
--- a/chrome/common/pref_service.cc |
+++ b/chrome/common/pref_service.cc |
@@ -4,12 +4,9 @@ |
#include "chrome/common/pref_service.h" |
-#include "base/compiler_specific.h" |
-#include "base/file_util.h" |
#include "base/logging.h" |
#include "base/message_loop.h" |
#include "base/string_util.h" |
-#include "base/task.h" |
#include "base/thread.h" |
#include "chrome/common/json_value_serializer.h" |
#include "chrome/common/l10n_util.h" |
@@ -19,43 +16,6 @@ |
namespace { |
-// The number of milliseconds we'll wait to do a write of chrome prefs to disk. |
-// This lets us batch together write operations. |
-static const int kCommitIntervalMs = 10000; |
- |
-// Replaces the given file's content with the given data. This allows the |
-// preferences to be written to disk on a background thread. |
-class SaveLaterTask : public Task { |
- public: |
- SaveLaterTask(const FilePath& file_name, |
- const std::string& data) |
- : file_name_(file_name), |
- data_(data) { |
- } |
- |
- void Run() { |
- // Write the data to a temp file then rename to avoid data loss if we crash |
- // while writing the file. |
- FilePath tmp_file_name(file_name_.value() + FILE_PATH_LITERAL(".tmp")); |
- int bytes_written = file_util::WriteFile(tmp_file_name, data_.c_str(), |
- static_cast<int>(data_.length())); |
- if (bytes_written != -1) { |
- if (!file_util::Move(tmp_file_name, file_name_)) { |
- // Rename failed. Try again on the off chance someone has locked either |
- // file and hope we're successful the second time through. |
- bool move_result = file_util::Move(tmp_file_name, file_name_); |
- DCHECK(move_result); |
- } |
- } |
- } |
- |
- private: |
- FilePath file_name_; |
- std::string data_; |
- |
- DISALLOW_COPY_AND_ASSIGN(SaveLaterTask); |
-}; |
- |
// A helper function for RegisterLocalized*Pref that creates a Value* based on |
// the string value in the locale dll. Because we control the values in a |
// locale dll, this should always return a Value of the appropriate type. |
@@ -99,18 +59,12 @@ Value* CreateLocaleDefaultValue(Value::ValueType type, int message_id) { |
} // namespace |
-PrefService::PrefService() |
+PrefService::PrefService(const FilePath& pref_filename, |
+ const base::Thread* backend_thread) |
: persistent_(new DictionaryValue), |
transient_(new DictionaryValue), |
- save_preferences_factory_(NULL) { |
-} |
- |
-PrefService::PrefService(const FilePath& pref_filename) |
- : persistent_(new DictionaryValue), |
- transient_(new DictionaryValue), |
- pref_filename_(pref_filename), |
- ALLOW_THIS_IN_INITIALIZER_LIST(save_preferences_factory_(this)) { |
- LoadPersistentPrefs(pref_filename_); |
+ writer_(pref_filename, backend_thread) { |
+ ReloadPersistentPrefs(); |
} |
PrefService::~PrefService() { |
@@ -132,11 +86,10 @@ PrefService::~PrefService() { |
pref_observers_.clear(); |
} |
-bool PrefService::LoadPersistentPrefs(const FilePath& file_path) { |
- DCHECK(!file_path.empty()); |
+bool PrefService::ReloadPersistentPrefs() { |
DCHECK(CalledOnValidThread()); |
- JSONFileValueSerializer serializer(file_path); |
+ JSONFileValueSerializer serializer(writer_.path()); |
scoped_ptr<Value> root(serializer.Deserialize(NULL)); |
if (!root.get()) |
return false; |
@@ -146,60 +99,34 @@ bool PrefService::LoadPersistentPrefs(const FilePath& file_path) { |
return false; |
persistent_.reset(static_cast<DictionaryValue*>(root.release())); |
- return true; |
-} |
- |
-void PrefService::ReloadPersistentPrefs() { |
- DCHECK(CalledOnValidThread()); |
- |
- JSONFileValueSerializer serializer(pref_filename_); |
- scoped_ptr<Value> root(serializer.Deserialize(NULL)); |
- if (!root.get()) |
- return; |
- |
- // Preferences should always have a dictionary root. |
- if (!root->IsType(Value::TYPE_DICTIONARY)) |
- return; |
- |
- persistent_.reset(static_cast<DictionaryValue*>(root.release())); |
for (PreferenceSet::iterator it = prefs_.begin(); |
it != prefs_.end(); ++it) { |
(*it)->root_pref_ = persistent_.get(); |
} |
+ |
+ return true; |
} |
-bool PrefService::SavePersistentPrefs(base::Thread* thread) const { |
- DCHECK(!pref_filename_.empty()); |
+bool PrefService::SavePersistentPrefs() { |
DCHECK(CalledOnValidThread()); |
- // TODO(tc): Do we want to prune webkit preferences that match the default |
- // value? |
std::string data; |
- JSONStringValueSerializer serializer(&data); |
- serializer.set_pretty_print(true); |
- if (!serializer.Serialize(*(persistent_.get()))) |
+ if (!SerializePrefData(&data)) |
return false; |
- SaveLaterTask* task = new SaveLaterTask(pref_filename_, data); |
- if (thread != NULL) { |
- // We can use the background thread, it will take ownership of the task. |
- thread->message_loop()->PostTask(FROM_HERE, task); |
- } else { |
- // In unit test mode, we have no background thread, just execute. |
- task->Run(); |
- delete task; |
- } |
+ writer_.WriteNow(data); |
return true; |
} |
-void PrefService::ScheduleSavePersistentPrefs(base::Thread* thread) { |
- if (!save_preferences_factory_.empty()) |
- return; |
+bool PrefService::ScheduleSavePersistentPrefs() { |
+ DCHECK(CalledOnValidThread()); |
- MessageLoop::current()->PostDelayedTask(FROM_HERE, |
- save_preferences_factory_.NewRunnableMethod( |
- &PrefService::SavePersistentPrefs, thread), |
- kCommitIntervalMs); |
+ std::string data; |
+ if (!SerializePrefData(&data)) |
+ return false; |
+ |
+ writer_.ScheduleWrite(data); |
+ return true; |
} |
void PrefService::RegisterBooleanPref(const wchar_t* path, |
@@ -717,6 +644,14 @@ void PrefService::FireObservers(const wchar_t* path) { |
} |
} |
+bool PrefService::SerializePrefData(std::string* output) const { |
+ // TODO(tc): Do we want to prune webkit preferences that match the default |
+ // value? |
+ JSONStringValueSerializer serializer(output); |
+ serializer.set_pretty_print(true); |
+ return serializer.Serialize(*(persistent_.get())); |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
// PrefService::Preference |