| Index: base/prefs/json_pref_store.cc
|
| diff --git a/base/prefs/json_pref_store.cc b/base/prefs/json_pref_store.cc
|
| index b0a16cc11431e01fd8661949388c11cdc972f156..e99d64fc40c68525881ea808802708dd38c3f3be 100644
|
| --- a/base/prefs/json_pref_store.cc
|
| +++ b/base/prefs/json_pref_store.cc
|
| @@ -39,6 +39,8 @@ class FileThreadDeserializer
|
|
|
| void Start(const base::FilePath& path) {
|
| DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
|
| + // TODO(gab): This should use PostTaskAndReplyWithResult instead of using
|
| + // the |error_| member to pass data across tasks.
|
| sequenced_task_runner_->PostTask(
|
| FROM_HERE,
|
| base::Bind(&FileThreadDeserializer::ReadFileAndReport,
|
| @@ -59,7 +61,7 @@ class FileThreadDeserializer
|
| // Reports deserialization result on the origin thread.
|
| void ReportOnOriginThread() {
|
| DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
|
| - delegate_->OnFileRead(value_.release(), error_, no_dir_);
|
| + delegate_->OnFileRead(value_.Pass(), error_, no_dir_);
|
| }
|
|
|
| static base::Value* DoReading(const base::FilePath& path,
|
| @@ -161,7 +163,9 @@ JsonPrefStore::JsonPrefStore(const base::FilePath& filename,
|
| writer_(filename, sequenced_task_runner),
|
| pref_filter_(pref_filter.Pass()),
|
| initialized_(false),
|
| - read_error_(PREF_READ_ERROR_OTHER) {}
|
| + filtering_in_progress_(false),
|
| + read_error_(PREF_READ_ERROR_NONE) {
|
| +}
|
|
|
| bool JsonPrefStore::GetValue(const std::string& key,
|
| const base::Value** result) const {
|
| @@ -224,6 +228,12 @@ void JsonPrefStore::RemoveValue(const std::string& key) {
|
| ReportValueChanged(key);
|
| }
|
|
|
| +void JsonPrefStore::RemoveValueSilently(const std::string& key) {
|
| + prefs_->RemovePath(key, NULL);
|
| + if (!read_only_)
|
| + writer_.ScheduleWrite(this);
|
| +}
|
| +
|
| bool JsonPrefStore::ReadOnly() const {
|
| return read_only_;
|
| }
|
| @@ -234,23 +244,26 @@ PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const {
|
|
|
| PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
|
| if (path_.empty()) {
|
| - OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
|
| + OnFileRead(
|
| + scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
|
| return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
|
| }
|
|
|
| PrefReadError error;
|
| bool no_dir;
|
| - base::Value* value =
|
| - FileThreadDeserializer::DoReading(path_, &error, &no_dir);
|
| - OnFileRead(value, error, no_dir);
|
| - return error;
|
| + scoped_ptr<base::Value> value(
|
| + FileThreadDeserializer::DoReading(path_, &error, &no_dir));
|
| + OnFileRead(value.Pass(), error, no_dir);
|
| + return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE :
|
| + error;
|
| }
|
|
|
| -void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) {
|
| +void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
|
| initialized_ = false;
|
| error_delegate_.reset(error_delegate);
|
| if (path_.empty()) {
|
| - OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
|
| + OnFileRead(
|
| + scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
|
| return;
|
| }
|
|
|
| @@ -276,53 +289,63 @@ void JsonPrefStore::ReportValueChanged(const std::string& key) {
|
| writer_.ScheduleWrite(this);
|
| }
|
|
|
| -void JsonPrefStore::OnFileRead(base::Value* value_owned,
|
| +void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback(
|
| + const base::Closure& on_next_successful_write) {
|
| + writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write);
|
| +}
|
| +
|
| +void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value,
|
| PersistentPrefStore::PrefReadError error,
|
| bool no_dir) {
|
| - scoped_ptr<base::Value> value(value_owned);
|
| - read_error_ = error;
|
| + scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue);
|
|
|
| - if (no_dir) {
|
| - FOR_EACH_OBSERVER(PrefStore::Observer,
|
| - observers_,
|
| - OnInitializationCompleted(false));
|
| - return;
|
| - }
|
| + read_error_ = error;
|
|
|
| - initialized_ = true;
|
| + bool initialization_successful = !no_dir;
|
|
|
| - switch (error) {
|
| - case PREF_READ_ERROR_ACCESS_DENIED:
|
| - case PREF_READ_ERROR_FILE_OTHER:
|
| - case PREF_READ_ERROR_FILE_LOCKED:
|
| - case PREF_READ_ERROR_JSON_TYPE:
|
| - case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
|
| - read_only_ = true;
|
| - break;
|
| - case PREF_READ_ERROR_NONE:
|
| - DCHECK(value.get());
|
| - prefs_.reset(static_cast<base::DictionaryValue*>(value.release()));
|
| - break;
|
| - case PREF_READ_ERROR_NO_FILE:
|
| - // If the file just doesn't exist, maybe this is first run. In any case
|
| - // there's no harm in writing out default prefs in this case.
|
| - break;
|
| - case PREF_READ_ERROR_JSON_PARSE:
|
| - case PREF_READ_ERROR_JSON_REPEAT:
|
| - break;
|
| - default:
|
| - NOTREACHED() << "Unknown error: " << error;
|
| + if (initialization_successful) {
|
| + switch (read_error_) {
|
| + case PREF_READ_ERROR_ACCESS_DENIED:
|
| + case PREF_READ_ERROR_FILE_OTHER:
|
| + case PREF_READ_ERROR_FILE_LOCKED:
|
| + case PREF_READ_ERROR_JSON_TYPE:
|
| + case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
|
| + read_only_ = true;
|
| + break;
|
| + case PREF_READ_ERROR_NONE:
|
| + DCHECK(value.get());
|
| + unfiltered_prefs.reset(
|
| + static_cast<base::DictionaryValue*>(value.release()));
|
| + break;
|
| + case PREF_READ_ERROR_NO_FILE:
|
| + // If the file just doesn't exist, maybe this is first run. In any case
|
| + // there's no harm in writing out default prefs in this case.
|
| + break;
|
| + case PREF_READ_ERROR_JSON_PARSE:
|
| + case PREF_READ_ERROR_JSON_REPEAT:
|
| + break;
|
| + case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE:
|
| + // This is a special error code to be returned by ReadPrefs when it
|
| + // can't complete synchronously, it should never be returned by the read
|
| + // operation itself.
|
| + NOTREACHED();
|
| + break;
|
| + case PREF_READ_ERROR_MAX_ENUM:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| }
|
|
|
| - if (pref_filter_ && pref_filter_->FilterOnLoad(prefs_.get()))
|
| - writer_.ScheduleWrite(this);
|
| -
|
| - if (error_delegate_.get() && error != PREF_READ_ERROR_NONE)
|
| - error_delegate_->OnError(error);
|
| -
|
| - FOR_EACH_OBSERVER(PrefStore::Observer,
|
| - observers_,
|
| - OnInitializationCompleted(true));
|
| + if (pref_filter_) {
|
| + filtering_in_progress_ = true;
|
| + const PrefFilter::PostFilterOnLoadCallback post_filter_on_load_callback(
|
| + base::Bind(
|
| + &JsonPrefStore::FinalizeFileRead, this, initialization_successful));
|
| + pref_filter_->FilterOnLoad(post_filter_on_load_callback,
|
| + unfiltered_prefs.Pass());
|
| + } else {
|
| + FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false);
|
| + }
|
| }
|
|
|
| JsonPrefStore::~JsonPrefStore() {
|
| @@ -337,3 +360,32 @@ bool JsonPrefStore::SerializeData(std::string* output) {
|
| serializer.set_pretty_print(true);
|
| return serializer.Serialize(*prefs_);
|
| }
|
| +
|
| +void JsonPrefStore::FinalizeFileRead(bool initialization_successful,
|
| + scoped_ptr<base::DictionaryValue> prefs,
|
| + bool schedule_write) {
|
| + filtering_in_progress_ = false;
|
| +
|
| + if (!initialization_successful) {
|
| + FOR_EACH_OBSERVER(PrefStore::Observer,
|
| + observers_,
|
| + OnInitializationCompleted(false));
|
| + return;
|
| + }
|
| +
|
| + prefs_ = prefs.Pass();
|
| +
|
| + initialized_ = true;
|
| +
|
| + if (schedule_write && !read_only_)
|
| + writer_.ScheduleWrite(this);
|
| +
|
| + if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE)
|
| + error_delegate_->OnError(read_error_);
|
| +
|
| + FOR_EACH_OBSERVER(PrefStore::Observer,
|
| + observers_,
|
| + OnInitializationCompleted(true));
|
| +
|
| + return;
|
| +}
|
|
|