summaryrefslogtreecommitdiffstats
path: root/chrome/common/json_pref_store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common/json_pref_store.cc')
-rw-r--r--chrome/common/json_pref_store.cc130
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()));
+}
+