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

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: nits Created 9 years, 7 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 origin 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 origin_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(origin_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
47 value_.reset(DoReading(path, &error_, &no_dir_));
48
49 origin_loop_proxy_->PostTask(
50 FROM_HERE,
51 NewRunnableMethod(this, &FileThreadDeserializer::ReportOnOriginThread));
52 }
53
54 // Reports deserialization result on the origin thread.
55 void ReportOnOriginThread() {
56 DCHECK(origin_loop_proxy_->BelongsToCurrentThread());
57 delegate_->OnFileRead(value_.release(), error_, no_dir_);
58 }
59
60 static Value* DoReading(const FilePath& path,
61 PersistentPrefStore::PrefReadError* error,
62 bool* no_dir) {
44 int error_code; 63 int error_code;
45 std::string error_msg; 64 std::string error_msg;
46 JSONFileValueSerializer serializer(path); 65 JSONFileValueSerializer serializer(path);
47 value_.reset(serializer.Deserialize(&error_code, &error_msg)); 66 Value* value = serializer.Deserialize(&error_code, &error_msg);
48 67 HandleErrors(value, path, error_code, error_msg, error);
49 HandleErrors(value_.get(), path, error_code, error_msg, &error_); 68 *no_dir = !file_util::PathExists(path.DirName());
50 69 return value;
51 no_dir_ = !file_util::PathExists(path.DirName());
52
53 BrowserThread::PostTask(
54 BrowserThread::UI,
55 FROM_HERE,
56 NewRunnableMethod(this, &FileThreadDeserializer::ReportOnUIThread));
57 }
58
59 // Reports deserialization result on the UI thread.
60 void ReportOnUIThread() {
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62 delegate_->OnFileRead(value_.release(), error_, no_dir_);
63 } 70 }
64 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> origin_loop_proxy_;
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_delegate_(NULL),
145 initialized_(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)) {
144 *result = tmp; 156 *result = tmp;
145 return READ_OK; 157 return READ_OK;
146 } 158 }
147 return READ_NO_VALUE; 159 return READ_NO_VALUE;
148 } 160 }
149 161
150 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) { 162 void JsonPrefStore::AddObserver(PrefStore::Observer* observer) {
151 observers_.AddObserver(observer); 163 observers_.AddObserver(observer);
152 } 164 }
153 165
154 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) { 166 void JsonPrefStore::RemoveObserver(PrefStore::Observer* observer) {
155 observers_.RemoveObserver(observer); 167 observers_.RemoveObserver(observer);
156 } 168 }
157 169
170 bool JsonPrefStore::IsInitializationComplete() const {
171 return initialized_;
172 }
173
158 PrefStore::ReadResult JsonPrefStore::GetMutableValue(const std::string& key, 174 PrefStore::ReadResult JsonPrefStore::GetMutableValue(const std::string& key,
159 Value** result) { 175 Value** result) {
160 return prefs_->Get(key, result) ? READ_OK : READ_NO_VALUE; 176 return prefs_->Get(key, result) ? READ_OK : READ_NO_VALUE;
161 } 177 }
162 178
163 void JsonPrefStore::SetValue(const std::string& key, Value* value) { 179 void JsonPrefStore::SetValue(const std::string& key, Value* value) {
164 DCHECK(value); 180 DCHECK(value);
165 scoped_ptr<Value> new_value(value); 181 scoped_ptr<Value> new_value(value);
166 Value* old_value = NULL; 182 Value* old_value = NULL;
167 prefs_->Get(key, &old_value); 183 prefs_->Get(key, &old_value);
(...skipping 19 matching lines...) Expand all
187 } 203 }
188 204
189 bool JsonPrefStore::ReadOnly() const { 205 bool JsonPrefStore::ReadOnly() const {
190 return read_only_; 206 return read_only_;
191 } 207 }
192 208
193 void JsonPrefStore::OnFileRead(Value* value_owned, 209 void JsonPrefStore::OnFileRead(Value* value_owned,
194 PersistentPrefStore::PrefReadError error, 210 PersistentPrefStore::PrefReadError error,
195 bool no_dir) { 211 bool no_dir) {
196 scoped_ptr<Value> value(value_owned); 212 scoped_ptr<Value> value(value_owned);
213
214 if (no_dir) {
215 FOR_EACH_OBSERVER(PrefStore::Observer,
216 observers_,
217 OnInitializationCompleted(false));
218 return;
219 }
220
221 initialized_ = true;
222
197 switch (error) { 223 switch (error) {
198 case PREF_READ_ERROR_ACCESS_DENIED: 224 case PREF_READ_ERROR_ACCESS_DENIED:
199 case PREF_READ_ERROR_FILE_OTHER: 225 case PREF_READ_ERROR_FILE_OTHER:
200 case PREF_READ_ERROR_FILE_LOCKED: 226 case PREF_READ_ERROR_FILE_LOCKED:
201 case PREF_READ_ERROR_JSON_TYPE: 227 case PREF_READ_ERROR_JSON_TYPE:
228 case PREF_READ_ERROR_FILE_NOT_SPECIFIED:
202 read_only_ = true; 229 read_only_ = true;
203 break; 230 break;
204 case PREF_READ_ERROR_NONE: 231 case PREF_READ_ERROR_NONE:
205 DCHECK(value.get()); 232 DCHECK(value.get());
206 prefs_.reset(static_cast<DictionaryValue*>(value.release())); 233 prefs_.reset(static_cast<DictionaryValue*>(value.release()));
207 break; 234 break;
208 case PREF_READ_ERROR_NO_FILE: 235 case PREF_READ_ERROR_NO_FILE:
209 // If the file just doesn't exist, maybe this is first run. In any case 236 // 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. 237 // there's no harm in writing out default prefs in this case.
211 break; 238 break;
212 case PREF_READ_ERROR_JSON_PARSE: 239 case PREF_READ_ERROR_JSON_PARSE:
213 case PREF_READ_ERROR_JSON_REPEAT: 240 case PREF_READ_ERROR_JSON_REPEAT:
214 break; 241 break;
215 default: 242 default:
216 NOTREACHED() << "Unknown error: " << error; 243 NOTREACHED() << "Unknown error: " << error;
217 } 244 }
218 245
219 if (delegate_) 246 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE)
220 delegate_->OnPrefsRead(error, no_dir); 247 error_delegate_->OnError(error);
248
249 FOR_EACH_OBSERVER(PrefStore::Observer,
250 observers_,
251 OnInitializationCompleted(true));
221 } 252 }
222 253
223 void JsonPrefStore::ReadPrefs(Delegate* delegate) { 254 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) {
224 DCHECK(delegate); 255 initialized_ = false;
225 delegate_ = delegate; 256 error_delegate_.reset(error_delegate);
226
227 if (path_.empty()) { 257 if (path_.empty()) {
228 read_only_ = true; 258 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
229 delegate_->OnPrefsRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
230 return; 259 return;
231 } 260 }
232 261
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 262 // Start async reading of the preferences file. It will delete itself
237 // in the end. 263 // in the end.
238 scoped_refptr<FileThreadDeserializer> deserializer( 264 scoped_refptr<FileThreadDeserializer> deserializer(
239 new FileThreadDeserializer(this)); 265 new FileThreadDeserializer(this, file_message_loop_proxy_.get()));
240 deserializer->Start(path_); 266 deserializer->Start(path_);
241 } 267 }
242 268
243 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { 269 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() {
244 delegate_ = NULL;
245
246 if (path_.empty()) { 270 if (path_.empty()) {
247 read_only_ = true; 271 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false);
248 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; 272 return PREF_READ_ERROR_FILE_NOT_SPECIFIED;
249 } 273 }
250 274
251 int error_code = 0; 275 PrefReadError error;
252 std::string error_msg; 276 bool no_dir;
253 277 Value* value = FileThreadDeserializer::DoReading(path_, &error, &no_dir);
254 JSONFileValueSerializer serializer(path_); 278 OnFileRead(value, error, no_dir);
255 scoped_ptr<Value> value(serializer.Deserialize(&error_code, &error_msg));
256
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; 279 return error;
267 } 280 }
268 281
269 bool JsonPrefStore::WritePrefs() { 282 bool JsonPrefStore::WritePrefs() {
270 std::string data; 283 std::string data;
271 if (!SerializeData(&data)) 284 if (!SerializeData(&data))
272 return false; 285 return false;
273 286
274 // Lie about our ability to save. 287 // Lie about our ability to save.
275 if (read_only_) 288 if (read_only_)
(...skipping 20 matching lines...) Expand all
296 } 309 }
297 310
298 bool JsonPrefStore::SerializeData(std::string* output) { 311 bool JsonPrefStore::SerializeData(std::string* output) {
299 // TODO(tc): Do we want to prune webkit preferences that match the default 312 // TODO(tc): Do we want to prune webkit preferences that match the default
300 // value? 313 // value?
301 JSONStringValueSerializer serializer(output); 314 JSONStringValueSerializer serializer(output);
302 serializer.set_pretty_print(true); 315 serializer.set_pretty_print(true);
303 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren()); 316 scoped_ptr<DictionaryValue> copy(prefs_->DeepCopyWithoutEmptyChildren());
304 return serializer.Serialize(*(copy.get())); 317 return serializer.Serialize(*(copy.get()));
305 } 318 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698