1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// Use of this source code is governed by a BSD-style license that can be
306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// found in the LICENSE file.
406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "chrome/common/json_pref_store.h"
606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include <algorithm>
806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/bind.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/callback.h"
1106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/file_util.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
1306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/values.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/json_value_serializer.h"
1606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
1706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochnamespace {
1806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
1906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// Some extensions we'll tack on to copies of the Preferences files.
2006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochconst FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad");
2106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Differentiates file loading between UI and FILE threads.
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass FileThreadDeserializer
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : public base::RefCountedThreadSafe<FileThreadDeserializer> {
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  explicit FileThreadDeserializer(JsonPrefStore* delegate)
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      : delegate_(delegate) {
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void Start(const FilePath& path) {
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::FILE,
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        FROM_HERE,
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(this,
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          &FileThreadDeserializer::ReadFileAndReport,
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          path));
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Deserializes JSON on the FILE thread.
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ReadFileAndReport(const FilePath& path) {
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int error_code;
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string error_msg;
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    JSONFileValueSerializer serializer(path);
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    value_.reset(serializer.Deserialize(&error_code, &error_msg));
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    HandleErrors(value_.get(), path, error_code, error_msg, &error_);
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    no_dir_ = !file_util::PathExists(path.DirName());
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        BrowserThread::UI,
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        FROM_HERE,
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread));
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Reports deserialization result on the UI thread.
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void ReportOnUIThread() {
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    delegate_->OnFileRead(value_.release(), error_, no_dir_);
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static void HandleErrors(const Value* value,
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           const FilePath& path,
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           int error_code,
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           const std::string& error_msg,
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           PersistentPrefStore::PrefReadError* error);
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  friend class base::RefCountedThreadSafe<FileThreadDeserializer>;
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool no_dir_;
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PersistentPrefStore::PrefReadError error_;
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<Value> value_;
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<JsonPrefStore> delegate_;
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileThreadDeserializer::HandleErrors(
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const Value* value,
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const FilePath& path,
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int error_code,
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& error_msg,
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PersistentPrefStore::PrefReadError* error) {
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *error = PersistentPrefStore::PREF_READ_ERROR_NONE;
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!value) {
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DLOG(ERROR) << "Error while loading JSON file: " << error_msg;
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    switch (error_code) {
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case JSONFileValueSerializer::JSON_ACCESS_DENIED:
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED;
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case JSONFileValueSerializer::JSON_CANNOT_READ_FILE:
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = PersistentPrefStore::PREF_READ_ERROR_FILE_OTHER;
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case JSONFileValueSerializer::JSON_FILE_LOCKED:
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = PersistentPrefStore::PREF_READ_ERROR_FILE_LOCKED;
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case JSONFileValueSerializer::JSON_NO_SUCH_FILE:
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = PersistentPrefStore::PREF_READ_ERROR_NO_FILE;
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      default:
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *error = PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE;
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // JSON errors indicate file corruption of some sort.
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Since the file is corrupt, move it to the side and continue with
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // empty preferences.  This will result in them losing their settings.
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // We keep the old file for possible support and debugging assistance
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // as well as to detect if they're seeing these errors repeatedly.
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // TODO(erikkay) Instead, use the last known good file.
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        FilePath bad = path.ReplaceExtension(kBadExtension);
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // If they've ever had a parse error before, put them in another bucket.
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // TODO(erikkay) if we keep this error checking for very long, we may
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // want to differentiate between recent and long ago errors.
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (file_util::PathExists(bad))
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          *error = PersistentPrefStore::PREF_READ_ERROR_JSON_REPEAT;
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        file_util::Move(path, bad);
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (!value->IsType(Value::TYPE_DICTIONARY)) {
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE;
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
12606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}  // namespace
12706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
12806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochJsonPrefStore::JsonPrefStore(const FilePath& filename,
12906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch                             base::MessageLoopProxy* file_message_loop_proxy)
13006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch    : path_(filename),
13106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch      prefs_(new DictionaryValue()),
13206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch      read_only_(false),
13306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch      writer_(filename, file_message_loop_proxy) {
13406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}
13506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
13606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochJsonPrefStore::~JsonPrefStore() {
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CommitPendingWrite();
13806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}
13906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key,
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                              const Value** result) const {
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Value* tmp = NULL;
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (prefs_->Get(key, &tmp)) {
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *result = tmp;
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return READ_OK;
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return READ_NO_VALUE;
14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::AddObserver(PrefStore::Observer* observer) {
15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  observers_.AddObserver(observer);
15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) {
15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  observers_.RemoveObserver(observer);
15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPrefStore::ReadResult JsonPrefStore::GetMutableValue(const std::string& key,
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                     Value** result) {
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return prefs_->Get(key, result) ? READ_OK : READ_NO_VALUE;
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::SetValue(const std::string& key, Value* value) {
16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(value);
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  scoped_ptr<Value> new_value(value);
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  Value* old_value = NULL;
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  prefs_->Get(key, &old_value);
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!old_value || !value->Equals(old_value)) {
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs_->Set(key, new_value.release());
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::SetValueSilently(const std::string& key, Value* value) {
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(value);
17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  scoped_ptr<Value> new_value(value);
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  Value* old_value = NULL;
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  prefs_->Get(key, &old_value);
17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!old_value || !value->Equals(old_value))
18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    prefs_->Set(key, new_value.release());
18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid JsonPrefStore::RemoveValue(const std::string& key) {
18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (prefs_->Remove(key, NULL)) {
18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool JsonPrefStore::ReadOnly() const {
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return read_only_;
19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid JsonPrefStore::OnFileRead(Value* value_owned,
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               PersistentPrefStore::PrefReadError error,
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               bool no_dir) {
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<Value> value(value_owned);
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (error) {
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_ACCESS_DENIED:
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_FILE_OTHER:
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_FILE_LOCKED:
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_JSON_TYPE:
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      read_only_ = true;
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_NONE:
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK(value.get());
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      prefs_.reset(static_cast<DictionaryValue*>(value.release()));
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_NO_FILE:
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // If the file just doesn't exist, maybe this is first run.  In any case
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // there's no harm in writing out default prefs in this case.
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_JSON_PARSE:
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case PREF_READ_ERROR_JSON_REPEAT:
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default:
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED() << "Unknown error: " << error;
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (delegate_)
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    delegate_->OnPrefsRead(error, no_dir);
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid JsonPrefStore::ReadPrefs(Delegate* delegate) {
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(delegate);
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  delegate_ = delegate;
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (path_.empty()) {
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    read_only_ = true;
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    delegate_->OnPrefsRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This guarantees that class will not be deleted while JSON is readed.
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Start async reading of the preferences file. It will delete itself
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // in the end.
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<FileThreadDeserializer> deserializer(
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new FileThreadDeserializer(this));
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  deserializer->Start(path_);
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  delegate_ = NULL;
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (path_.empty()) {
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    read_only_ = true;
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
25006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
25106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  int error_code = 0;
25206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  std::string error_msg;
25306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  JSONFileValueSerializer serializer(path_);
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg));
25606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PersistentPrefStore::PrefReadError error;
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FileThreadDeserializer::HandleErrors(value.get(),
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       path_,
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       error_code,
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       error_msg,
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       &error);
26306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnFileRead(value.release(), error, false);
26506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return error;
26706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}
26806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
26906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochbool JsonPrefStore::WritePrefs() {
27006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  std::string data;
27106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  if (!SerializeData(&data))
27206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch    return false;
27306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
27406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  // Lie about our ability to save.
27506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  if (read_only_)
27606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch    return true;
27706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
27806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  writer_.WriteNow(data);
27906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  return true;
28006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}
28106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
28206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochvoid JsonPrefStore::ScheduleWritePrefs() {
28306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  if (read_only_)
28406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch    return;
28506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
28606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  writer_.ScheduleWrite(this);
28706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}
28806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid JsonPrefStore::CommitPendingWrite() {
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (writer_.HasPendingWrite() && !read_only_)
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    writer_.DoScheduledWrite();
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid JsonPrefStore::ReportValueChanged(const std::string& key) {
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key));
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
29806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochbool JsonPrefStore::SerializeData(std::string* output) {
29906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  // TODO(tc): Do we want to prune webkit preferences that match the default
30006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  // value?
30106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  JSONStringValueSerializer serializer(output);
30206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  serializer.set_pretty_print(true);
30306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren());
30406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch  return serializer.Serialize(*(copy.get()));
30506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}
306