Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: chrome/common/json_pref_store.cc

Issue 6894020: Adds async interface method to PersistentPrefStore. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use Notifications. Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/json_pref_store.h" 5 #include "chrome/common/json_pref_store.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
13 #include "base/message_loop_proxy.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "content/browser/browser_thread.h"
15 #include "content/common/json_value_serializer.h" 15 #include "content/common/json_value_serializer.h"
16 16
17 namespace { 17 namespace {
18 18
19 // Some extensions we'll tack on to copies of the Preferences files. 19 // Some extensions we'll tack on to copies of the Preferences files.
20 const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad"); 20 const FilePath::CharType* kBadExtension = FILE_PATH_LITERAL("bad");
21 21
22 // Differentiates file loading between UI and FILE threads. 22 // Differentiates file loading between current (aka ui) thread and passed
23 // (aka file) thread.
23 class FileThreadDeserializer 24 class FileThreadDeserializer
24 : public base::RefCountedThreadSafe<FileThreadDeserializer> { 25 : public base::RefCountedThreadSafe<FileThreadDeserializer> {
25 public: 26 public:
26 explicit FileThreadDeserializer(JsonPrefStore* delegate) 27 explicit FileThreadDeserializer(JsonPrefStore* delegate,
27 : delegate_(delegate) { 28 base::MessageLoopProxy* file_loop_proxy)
29 : delegate_(delegate),
30 file_loop_proxy_(file_loop_proxy),
31 ui_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()) {
28 } 32 }
29 33
30 void Start(const FilePath& path) { 34 void Start(const FilePath& path) {
31 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 35 DCHECK(ui_loop_proxy_->BelongsToCurrentThread());
32 BrowserThread::PostTask( 36 file_loop_proxy_->PostTask(
33 BrowserThread::FILE,
34 FROM_HERE, 37 FROM_HERE,
35 NewRunnableMethod(this, 38 NewRunnableMethod(this,
36 &FileThreadDeserializer::ReadFileAndReport, 39 &FileThreadDeserializer::ReadFileAndReport,
37 path)); 40 path));
38 } 41 }
39 42
40 // Deserializes JSON on the FILE thread. 43 // Deserializes JSON on the file thread.
41 void ReadFileAndReport(const FilePath& path) { 44 void ReadFileAndReport(const FilePath& path) {
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 45 DCHECK(file_loop_proxy_->BelongsToCurrentThread());
43 46
44 int error_code; 47 value_.reset(DoReading(path, &error_, &no_dir_));
45 std::string error_msg;
46 JSONFileValueSerializer serializer(path);
47 value_.reset(serializer.Deserialize(&error_code, &error_msg));
48 48
49 HandleErrors(value_.get(), path, error_code, error_msg, &error_); 49 ui_loop_proxy_->PostTask(
50
51 no_dir_ = !file_util::PathExists(path.DirName());
52
53 BrowserThread::PostTask(
54 BrowserThread::UI,
55 FROM_HERE, 50 FROM_HERE,
56 NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread)); 51 NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread));
57 } 52 }
58 53
59 // Reports deserialization result on the UI thread. 54 // Reports deserialization result on the ui thread.
60 void ReportOnUIThread() { 55 void ReportOnUIThread() {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 56 DCHECK(ui_loop_proxy_->BelongsToCurrentThread());
62 delegate_->OnFileRead(value_.release(), error_, no_dir_); 57 delegate_->OnFileRead(value_.release(), error_, no_dir_);
63 } 58 }
64 59
60 static Value* DoReading(const FilePath& path,
61 PersistentPrefStore::PrefReadError* error,
62 bool* no_dir) {
63 int error_code;
64 std::string error_msg;
65 JSONFileValueSerializer serializer(path);
66 Value* value = serializer.Deserialize(&error_code, &error_msg);
67 HandleErrors(value, path, error_code, error_msg, error);
68 *no_dir = !file_util::PathExists(path.DirName());
69 return value;
70 }
71
65 static void HandleErrors(const Value* value, 72 static void HandleErrors(const Value* value,
66 const FilePath& path, 73 const FilePath& path,
67 int error_code, 74 int error_code,
68 const std::string& error_msg, 75 const std::string& error_msg,
69 PersistentPrefStore::PrefReadError* error); 76 PersistentPrefStore::PrefReadError* error);
70 77
71 private: 78 private:
72 friend class base::RefCountedThreadSafe<FileThreadDeserializer>; 79 friend class base::RefCountedThreadSafe<FileThreadDeserializer>;
73 80
74 bool no_dir_; 81 bool no_dir_;
75 PersistentPrefStore::PrefReadError error_; 82 PersistentPrefStore::PrefReadError error_;
76 scoped_ptr<Value> value_; 83 scoped_ptr<Value> value_;
77 scoped_refptr<JsonPrefStore> delegate_; 84 scoped_refptr<JsonPrefStore> delegate_;
85 scoped_refptr<base::MessageLoopProxy> file_loop_proxy_;
86 scoped_refptr<base::MessageLoopProxy> ui_loop_proxy_;
Mattias Nissler (ping if slow) 2011/04/27 12:16:30 ui_loop_proxy is a misnomer IMHO, the service proc
altimofeev 2011/05/04 13:46:14 Done.
78 }; 87 };
79 88
80 // static 89 // static
81 void FileThreadDeserializer::HandleErrors( 90 void FileThreadDeserializer::HandleErrors(
82 const Value* value, 91 const Value* value,
83 const FilePath& path, 92 const FilePath& path,
84 int error_code, 93 int error_code,
85 const std::string& error_msg, 94 const std::string& error_msg,
86 PersistentPrefStore::PrefReadError* error) { 95 PersistentPrefStore::PrefReadError* error) {
87 *error = PersistentPrefStore::PREF_READ_ERROR_NONE; 96 *error = PersistentPrefStore::PREF_READ_ERROR_NONE;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 } else if (!value->IsType(Value::TYPE_DICTIONARY)) { 130 } else if (!value->IsType(Value::TYPE_DICTIONARY)) {
122 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE; 131 *error = PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE;
123 } 132 }
124 } 133 }
125 134
126 } // namespace 135 } // namespace
127 136
128 JsonPrefStore::JsonPrefStore(const FilePath& filename, 137 JsonPrefStore::JsonPrefStore(const FilePath& filename,
129 base::MessageLoopProxy* file_message_loop_proxy) 138 base::MessageLoopProxy* file_message_loop_proxy)
130 : path_(filename), 139 : path_(filename),
140 file_message_loop_proxy_(file_message_loop_proxy),
131 prefs_(new DictionaryValue()), 141 prefs_(new DictionaryValue()),
132 read_only_(false), 142 read_only_(false),
133 writer_(filename, file_message_loop_proxy) { 143 writer_(filename, file_message_loop_proxy),
144 error_(PREF_READ_ERROR_NONE),
145 is_fatal_(false) {
134 } 146 }
135 147
136 JsonPrefStore::~JsonPrefStore() { 148 JsonPrefStore::~JsonPrefStore() {
137 CommitPendingWrite(); 149 CommitPendingWrite();
138 } 150 }
139 151
140 PrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key, 152 PrefStore::ReadResult JsonPrefStore::GetValue(const std::string& key,
141 const Value** result) const { 153 const Value** result) const {
142 Value* tmp = NULL; 154 Value* tmp = NULL;
143 if (prefs_->Get(key, &tmp)) { 155 if (prefs_->Get(key, &tmp)) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 } 198 }
187 } 199 }
188 200
189 bool JsonPrefStore::ReadOnly() const { 201 bool JsonPrefStore::ReadOnly() const {
190 return read_only_; 202 return read_only_;
191 } 203 }
192 204
193 void JsonPrefStore::OnFileRead(Value* value_owned, 205 void JsonPrefStore::OnFileRead(Value* value_owned,
194 PersistentPrefStore::PrefReadError error, 206 PersistentPrefStore::PrefReadError error,
195 bool no_dir) { 207 bool no_dir) {
208 error_ = error;
209 is_fatal_ = no_dir;
210
196 scoped_ptr<Value> value(value_owned); 211 scoped_ptr<Value> value(value_owned);
197 switch (error) { 212 switch (error) {
198 case PREF_READ_ERROR_ACCESS_DENIED: 213 case PREF_READ_ERROR_ACCESS_DENIED:
199 case PREF_READ_ERROR_FILE_OTHER: 214 case PREF_READ_ERROR_FILE_OTHER:
200 case PREF_READ_ERROR_FILE_LOCKED: 215 case PREF_READ_ERROR_FILE_LOCKED:
201 case PREF_READ_ERROR_JSON_TYPE: 216 case PREF_READ_ERROR_JSON_TYPE:
217 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
202 read_only_ = true; 218 read_only_ = true;
203 break; 219 break;
204 case PREF_READ_ERROR_NONE: 220 case PREF_READ_ERROR_NONE:
205 DCHECK(value.get()); 221 DCHECK(value.get());
206 prefs_.reset(static_cast<DictionaryValue*>(value.release())); 222 prefs_.reset(static_cast<DictionaryValue*>(value.release()));
207 break; 223 break;
208 case PREF_READ_ERROR_NO_FILE: 224 case PREF_READ_ERROR_NO_FILE:
209 // If the file just doesn't exist, maybe this is first run. In any case 225 // If the file just doesn't exist, maybe this is first run. In any case
210 // there's no harm in writing out default prefs in this case. 226 // there's no harm in writing out default prefs in this case.
211 break; 227 break;
212 case PREF_READ_ERROR_JSON_PARSE: 228 case PREF_READ_ERROR_JSON_PARSE:
213 case PREF_READ_ERROR_JSON_REPEAT: 229 case PREF_READ_ERROR_JSON_REPEAT:
214 break; 230 break;
215 default: 231 default:
216 NOTREACHED() << "Unknown error: " << error; 232 NOTREACHED() << "Unknown error: " << error;
217 } 233 }
218 234
219 if (delegate_) 235 FOR_EACH_OBSERVER(PrefStore::Observer,
220 delegate_->OnPrefsRead(error, no_dir); 236 observers_,
237 OnInitializationCompleted());
221 } 238 }
222 239
223 void JsonPrefStore::ReadPrefs(Delegate* delegate) { 240 void JsonPrefStore::ReadPrefsAsync() {
224 DCHECK(delegate);
225 delegate_ = delegate;
226
227 if (path_.empty()) { 241 if (path_.empty()) {
228 read_only_ = true; 242 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
229 delegate_->OnPrefsRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
230 return; 243 return;
231 } 244 }
232 245
233 // This guarantees that class will not be deleted while JSON is readed.
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235
236 // Start async reading of the preferences file. It will delete itself 246 // Start async reading of the preferences file. It will delete itself
237 // in the end. 247 // in the end.
238 scoped_refptr<FileThreadDeserializer> deserializer( 248 scoped_refptr<FileThreadDeserializer> deserializer(
239 new FileThreadDeserializer(this)); 249 new FileThreadDeserializer(this, file_message_loop_proxy_.get()));
240 deserializer->Start(path_); 250 deserializer->Start(path_);
241 } 251 }
242 252
243 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { 253 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
244 delegate_ = NULL;
245
246 if (path_.empty()) { 254 if (path_.empty()) {
247 read_only_ = true; 255 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
248 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; 256 return error_;
249 } 257 }
250 258
251 int error_code = 0; 259 Value* value = FileThreadDeserializer::DoReading(path_,
252 std::string error_msg; 260 &error_,
261 &is_fatal_);
262 OnFileRead(value, error_, is_fatal_);
263 return error_;
264 }
253 265
254 JSONFileValueSerializer serializer(path_); 266 void JsonPrefStore::GetErrors(PrefReadError* error, bool* is_fatal) {
255 scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg)); 267 *error = error_;
256 268 *is_fatal = is_fatal_;
257 PersistentPrefStore::PrefReadError error;
258 FileThreadDeserializer::HandleErrors(value.get(),
259 path_,
260 error_code,
261 error_msg,
262 &error);
263
264 OnFileRead(value.release(), error, false);
265
266 return error;
267 } 269 }
268 270
269 bool JsonPrefStore::WritePrefs() { 271 bool JsonPrefStore::WritePrefs() {
270 std::string data; 272 std::string data;
271 if (!SerializeData(&data)) 273 if (!SerializeData(&data))
272 return false; 274 return false;
273 275
274 // Lie about our ability to save. 276 // Lie about our ability to save.
275 if (read_only_) 277 if (read_only_)
276 return true; 278 return true;
(...skipping 19 matching lines...) Expand all
296 } 298 }
297 299
298 bool JsonPrefStore::SerializeData(std::string* output) { 300 bool JsonPrefStore::SerializeData(std::string* output) {
299 // TODO(tc): Do we want to prune webkit preferences that match the default 301 // TODO(tc): Do we want to prune webkit preferences that match the default
300 // value? 302 // value?
301 JSONStringValueSerializer serializer(output); 303 JSONStringValueSerializer serializer(output);
302 serializer.set_pretty_print(true); 304 serializer.set_pretty_print(true);
303 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); 305 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren());
304 return serializer.Serialize(*(copy.get())); 306 return serializer.Serialize(*(copy.get()));
305 } 307 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698