diff options
Diffstat (limited to 'chrome/common/json_pref_store.cc')
-rw-r--r-- | chrome/common/json_pref_store.cc | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/chrome/common/json_pref_store.cc b/chrome/common/json_pref_store.cc new file mode 100644 index 0000000..9acfcb2 --- /dev/null +++ b/chrome/common/json_pref_store.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/json_pref_store.h" + +#include <algorithm> + +#include "base/file_util.h" +#include "base/values.h" +#include "chrome/common/json_value_serializer.h" + +namespace { + +// Some extensions we'll tack on to copies of the Preferences files. +const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); + +} // namespace + +JsonPrefStore::JsonPrefStore(const FilePath& filename, + base::MessageLoopProxy* file_message_loop_proxy) + : path_(filename), + prefs_(new DictionaryValue()), + read_only_(false), + writer_(filename, file_message_loop_proxy) { +} + +JsonPrefStore::~JsonPrefStore() { + if (writer_.HasPendingWrite() && !read_only_) + writer_.DoScheduledWrite(); +} + +PrefStore::PrefReadError JsonPrefStore::ReadPrefs() { + JSONFileValueSerializer serializer(path_); + + int error_code = 0; + std::string error_msg; + scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg)); + if (!value.get()) { +#if defined(GOOGLE_CHROME_BUILD) + // This log could be used for more detailed client-side error diagnosis, + // but since this triggers often with unit tests, we need to disable it + // in non-official builds. + PLOG(ERROR) << "Error reading Preferences: " << error_msg << " " << + path_.value(); +#endif + PrefReadError error; + switch (error_code) { + case JSONFileValueSerializer::JSON_ACCESS_DENIED: + // If the file exists but is simply unreadable, put the file into a + // state where we don't try to save changes. Otherwise, we could + // clobber the existing prefs. + error = PREF_READ_ERROR_ACCESS_DENIED; + read_only_ = true; + break; + case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: + error = PREF_READ_ERROR_FILE_OTHER; + read_only_ = true; + break; + case JSONFileValueSerializer::JSON_FILE_LOCKED: + error = PREF_READ_ERROR_FILE_LOCKED; + read_only_ = true; + break; + case JSONFileValueSerializer::JSON_NO_SUCH_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. + error = PREF_READ_ERROR_NO_FILE; + break; + default: + error = PREF_READ_ERROR_JSON_PARSE; + // JSON errors indicate file corruption of some sort. + // Since the file is corrupt, move it to the side and continue with + // empty preferences. This will result in them losing their settings. + // We keep the old file for possible support and debugging assistance + // as well as to detect if they're seeing these errors repeatedly. + // TODO(erikkay) Instead, use the last known good file. + FilePath bad = path_.ReplaceExtension(kBadExtension); + + // If they've ever had a parse error before, put them in another bucket. + // TODO(erikkay) if we keep this error checking for very long, we may + // want to differentiate between recent and long ago errors. + if (file_util::PathExists(bad)) + error = PREF_READ_ERROR_JSON_REPEAT; + file_util::Move(path_, bad); + break; + } + return error; + } + + // Preferences should always have a dictionary root. + if (!value->IsType(Value::TYPE_DICTIONARY)) { + // See comment for the default case above. + read_only_ = true; + return PREF_READ_ERROR_JSON_TYPE; + } + + prefs_.reset(static_cast<DictionaryValue*>(value.release())); + + return PREF_READ_ERROR_NONE; +} + +bool JsonPrefStore::WritePrefs() { + std::string data; + if (!SerializeData(&data)) + return false; + + // Lie about our ability to save. + if (read_only_) + return true; + + writer_.WriteNow(data); + return true; +} + +void JsonPrefStore::ScheduleWritePrefs() { + if (read_only_) + return; + + writer_.ScheduleWrite(this); +} + +bool JsonPrefStore::SerializeData(std::string* output) { + // TODO(tc): Do we want to prune webkit preferences that match the default + // value? + JSONStringValueSerializer serializer(output); + serializer.set_pretty_print(true); + scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); + return serializer.Serialize(*(copy.get())); +} + |