OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/prefs/json_pref_store.h" | 5 #include "base/prefs/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" |
(...skipping 21 matching lines...) Expand all Loading... |
32 base::SequencedTaskRunner* sequenced_task_runner) | 32 base::SequencedTaskRunner* sequenced_task_runner) |
33 : no_dir_(false), | 33 : no_dir_(false), |
34 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), | 34 error_(PersistentPrefStore::PREF_READ_ERROR_NONE), |
35 delegate_(delegate), | 35 delegate_(delegate), |
36 sequenced_task_runner_(sequenced_task_runner), | 36 sequenced_task_runner_(sequenced_task_runner), |
37 origin_loop_proxy_(base::MessageLoopProxy::current()) { | 37 origin_loop_proxy_(base::MessageLoopProxy::current()) { |
38 } | 38 } |
39 | 39 |
40 void Start(const base::FilePath& path) { | 40 void Start(const base::FilePath& path) { |
41 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | 41 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); |
42 // TODO(gab): This should use PostTaskAndReplyWithResult instead of using | |
43 // the |error_| member to pass data across tasks. | |
44 sequenced_task_runner_->PostTask( | 42 sequenced_task_runner_->PostTask( |
45 FROM_HERE, | 43 FROM_HERE, |
46 base::Bind(&FileThreadDeserializer::ReadFileAndReport, | 44 base::Bind(&FileThreadDeserializer::ReadFileAndReport, |
47 this, path)); | 45 this, path)); |
48 } | 46 } |
49 | 47 |
50 // Deserializes JSON on the sequenced task runner. | 48 // Deserializes JSON on the sequenced task runner. |
51 void ReadFileAndReport(const base::FilePath& path) { | 49 void ReadFileAndReport(const base::FilePath& path) { |
52 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); | 50 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); |
53 | 51 |
54 value_.reset(DoReading(path, &error_, &no_dir_)); | 52 value_.reset(DoReading(path, &error_, &no_dir_)); |
55 | 53 |
56 origin_loop_proxy_->PostTask( | 54 origin_loop_proxy_->PostTask( |
57 FROM_HERE, | 55 FROM_HERE, |
58 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); | 56 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); |
59 } | 57 } |
60 | 58 |
61 // Reports deserialization result on the origin thread. | 59 // Reports deserialization result on the origin thread. |
62 void ReportOnOriginThread() { | 60 void ReportOnOriginThread() { |
63 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | 61 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); |
64 delegate_->OnFileRead(value_.Pass(), error_, no_dir_); | 62 delegate_->OnFileRead(value_.release(), error_, no_dir_); |
65 } | 63 } |
66 | 64 |
67 static base::Value* DoReading(const base::FilePath& path, | 65 static base::Value* DoReading(const base::FilePath& path, |
68 PersistentPrefStore::PrefReadError* error, | 66 PersistentPrefStore::PrefReadError* error, |
69 bool* no_dir) { | 67 bool* no_dir) { |
70 int error_code; | 68 int error_code; |
71 std::string error_msg; | 69 std::string error_msg; |
72 JSONFileValueSerializer serializer(path); | 70 JSONFileValueSerializer serializer(path); |
73 base::Value* value = serializer.Deserialize(&error_code, &error_msg); | 71 base::Value* value = serializer.Deserialize(&error_code, &error_msg); |
74 HandleErrors(value, path, error_code, error_msg, error); | 72 HandleErrors(value, path, error_code, error_msg, error); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, | 154 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, |
157 base::SequencedTaskRunner* sequenced_task_runner, | 155 base::SequencedTaskRunner* sequenced_task_runner, |
158 scoped_ptr<PrefFilter> pref_filter) | 156 scoped_ptr<PrefFilter> pref_filter) |
159 : path_(filename), | 157 : path_(filename), |
160 sequenced_task_runner_(sequenced_task_runner), | 158 sequenced_task_runner_(sequenced_task_runner), |
161 prefs_(new base::DictionaryValue()), | 159 prefs_(new base::DictionaryValue()), |
162 read_only_(false), | 160 read_only_(false), |
163 writer_(filename, sequenced_task_runner), | 161 writer_(filename, sequenced_task_runner), |
164 pref_filter_(pref_filter.Pass()), | 162 pref_filter_(pref_filter.Pass()), |
165 initialized_(false), | 163 initialized_(false), |
166 filtering_in_progress_(false), | 164 read_error_(PREF_READ_ERROR_OTHER) {} |
167 read_error_(PREF_READ_ERROR_NONE) { | |
168 } | |
169 | 165 |
170 bool JsonPrefStore::GetValue(const std::string& key, | 166 bool JsonPrefStore::GetValue(const std::string& key, |
171 const base::Value** result) const { | 167 const base::Value** result) const { |
172 base::Value* tmp = NULL; | 168 base::Value* tmp = NULL; |
173 if (!prefs_->Get(key, &tmp)) | 169 if (!prefs_->Get(key, &tmp)) |
174 return false; | 170 return false; |
175 | 171 |
176 if (result) | 172 if (result) |
177 *result = tmp; | 173 *result = tmp; |
178 return true; | 174 return true; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 if (!read_only_) | 217 if (!read_only_) |
222 writer_.ScheduleWrite(this); | 218 writer_.ScheduleWrite(this); |
223 } | 219 } |
224 } | 220 } |
225 | 221 |
226 void JsonPrefStore::RemoveValue(const std::string& key) { | 222 void JsonPrefStore::RemoveValue(const std::string& key) { |
227 if (prefs_->RemovePath(key, NULL)) | 223 if (prefs_->RemovePath(key, NULL)) |
228 ReportValueChanged(key); | 224 ReportValueChanged(key); |
229 } | 225 } |
230 | 226 |
231 void JsonPrefStore::RemoveValueSilently(const std::string& key) { | |
232 prefs_->RemovePath(key, NULL); | |
233 if (!read_only_) | |
234 writer_.ScheduleWrite(this); | |
235 } | |
236 | |
237 bool JsonPrefStore::ReadOnly() const { | 227 bool JsonPrefStore::ReadOnly() const { |
238 return read_only_; | 228 return read_only_; |
239 } | 229 } |
240 | 230 |
241 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 231 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
242 return read_error_; | 232 return read_error_; |
243 } | 233 } |
244 | 234 |
245 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 235 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
246 if (path_.empty()) { | 236 if (path_.empty()) { |
247 OnFileRead( | 237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
248 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | |
249 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 238 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
250 } | 239 } |
251 | 240 |
252 PrefReadError error; | 241 PrefReadError error; |
253 bool no_dir; | 242 bool no_dir; |
254 scoped_ptr<base::Value> value( | 243 base::Value* value = |
255 FileThreadDeserializer::DoReading(path_, &error, &no_dir)); | 244 FileThreadDeserializer::DoReading(path_, &error, &no_dir); |
256 OnFileRead(value.Pass(), error, no_dir); | 245 OnFileRead(value, error, no_dir); |
257 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE : | 246 return error; |
258 error; | |
259 } | 247 } |
260 | 248 |
261 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { | 249 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { |
262 initialized_ = false; | 250 initialized_ = false; |
263 error_delegate_.reset(error_delegate); | 251 error_delegate_.reset(error_delegate); |
264 if (path_.empty()) { | 252 if (path_.empty()) { |
265 OnFileRead( | 253 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
266 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | |
267 return; | 254 return; |
268 } | 255 } |
269 | 256 |
270 // Start async reading of the preferences file. It will delete itself | 257 // Start async reading of the preferences file. It will delete itself |
271 // in the end. | 258 // in the end. |
272 scoped_refptr<FileThreadDeserializer> deserializer( | 259 scoped_refptr<FileThreadDeserializer> deserializer( |
273 new FileThreadDeserializer(this, sequenced_task_runner_.get())); | 260 new FileThreadDeserializer(this, sequenced_task_runner_.get())); |
274 deserializer->Start(path_); | 261 deserializer->Start(path_); |
275 } | 262 } |
276 | 263 |
277 void JsonPrefStore::CommitPendingWrite() { | 264 void JsonPrefStore::CommitPendingWrite() { |
278 if (writer_.HasPendingWrite() && !read_only_) | 265 if (writer_.HasPendingWrite() && !read_only_) |
279 writer_.DoScheduledWrite(); | 266 writer_.DoScheduledWrite(); |
280 } | 267 } |
281 | 268 |
282 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 269 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
283 if (pref_filter_) | 270 if (pref_filter_) |
284 pref_filter_->FilterUpdate(key); | 271 pref_filter_->FilterUpdate(key); |
285 | 272 |
286 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 273 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
287 | 274 |
288 if (!read_only_) | 275 if (!read_only_) |
289 writer_.ScheduleWrite(this); | 276 writer_.ScheduleWrite(this); |
290 } | 277 } |
291 | 278 |
292 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( | 279 void JsonPrefStore::OnFileRead(base::Value* value_owned, |
293 const base::Closure& on_next_successful_write) { | |
294 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); | |
295 } | |
296 | |
297 void JsonPrefStore::OnFileRead(scoped_ptr<base::Value> value, | |
298 PersistentPrefStore::PrefReadError error, | 280 PersistentPrefStore::PrefReadError error, |
299 bool no_dir) { | 281 bool no_dir) { |
300 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); | 282 scoped_ptr<base::Value> value(value_owned); |
301 | |
302 read_error_ = error; | 283 read_error_ = error; |
303 | 284 |
304 bool initialization_successful = !no_dir; | 285 if (no_dir) { |
305 | 286 FOR_EACH_OBSERVER(PrefStore::Observer, |
306 if (initialization_successful) { | 287 observers_, |
307 switch (read_error_) { | 288 OnInitializationCompleted(false)); |
308 case PREF_READ_ERROR_ACCESS_DENIED: | 289 return; |
309 case PREF_READ_ERROR_FILE_OTHER: | |
310 case PREF_READ_ERROR_FILE_LOCKED: | |
311 case PREF_READ_ERROR_JSON_TYPE: | |
312 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | |
313 read_only_ = true; | |
314 break; | |
315 case PREF_READ_ERROR_NONE: | |
316 DCHECK(value.get()); | |
317 unfiltered_prefs.reset( | |
318 static_cast<base::DictionaryValue*>(value.release())); | |
319 break; | |
320 case PREF_READ_ERROR_NO_FILE: | |
321 // If the file just doesn't exist, maybe this is first run. In any case | |
322 // there's no harm in writing out default prefs in this case. | |
323 break; | |
324 case PREF_READ_ERROR_JSON_PARSE: | |
325 case PREF_READ_ERROR_JSON_REPEAT: | |
326 break; | |
327 case PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE: | |
328 // This is a special error code to be returned by ReadPrefs when it | |
329 // can't complete synchronously, it should never be returned by the read | |
330 // operation itself. | |
331 NOTREACHED(); | |
332 break; | |
333 case PREF_READ_ERROR_MAX_ENUM: | |
334 NOTREACHED(); | |
335 break; | |
336 } | |
337 } | 290 } |
338 | 291 |
339 if (pref_filter_) { | 292 initialized_ = true; |
340 filtering_in_progress_ = true; | 293 |
341 const PrefFilter::PostFilterOnLoadCallback post_filter_on_load_callback( | 294 switch (error) { |
342 base::Bind( | 295 case PREF_READ_ERROR_ACCESS_DENIED: |
343 &JsonPrefStore::FinalizeFileRead, this, initialization_successful)); | 296 case PREF_READ_ERROR_FILE_OTHER: |
344 pref_filter_->FilterOnLoad(post_filter_on_load_callback, | 297 case PREF_READ_ERROR_FILE_LOCKED: |
345 unfiltered_prefs.Pass()); | 298 case PREF_READ_ERROR_JSON_TYPE: |
346 } else { | 299 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: |
347 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); | 300 read_only_ = true; |
| 301 break; |
| 302 case PREF_READ_ERROR_NONE: |
| 303 DCHECK(value.get()); |
| 304 prefs_.reset(static_cast<base::DictionaryValue*>(value.release())); |
| 305 break; |
| 306 case PREF_READ_ERROR_NO_FILE: |
| 307 // If the file just doesn't exist, maybe this is first run. In any case |
| 308 // there's no harm in writing out default prefs in this case. |
| 309 break; |
| 310 case PREF_READ_ERROR_JSON_PARSE: |
| 311 case PREF_READ_ERROR_JSON_REPEAT: |
| 312 break; |
| 313 default: |
| 314 NOTREACHED() << "Unknown error: " << error; |
348 } | 315 } |
| 316 |
| 317 if (pref_filter_ && pref_filter_->FilterOnLoad(prefs_.get())) |
| 318 writer_.ScheduleWrite(this); |
| 319 |
| 320 if (error_delegate_.get() && error != PREF_READ_ERROR_NONE) |
| 321 error_delegate_->OnError(error); |
| 322 |
| 323 FOR_EACH_OBSERVER(PrefStore::Observer, |
| 324 observers_, |
| 325 OnInitializationCompleted(true)); |
349 } | 326 } |
350 | 327 |
351 JsonPrefStore::~JsonPrefStore() { | 328 JsonPrefStore::~JsonPrefStore() { |
352 CommitPendingWrite(); | 329 CommitPendingWrite(); |
353 } | 330 } |
354 | 331 |
355 bool JsonPrefStore::SerializeData(std::string* output) { | 332 bool JsonPrefStore::SerializeData(std::string* output) { |
356 if (pref_filter_) | 333 if (pref_filter_) |
357 pref_filter_->FilterSerializeData(prefs_.get()); | 334 pref_filter_->FilterSerializeData(prefs_.get()); |
358 | 335 |
359 JSONStringValueSerializer serializer(output); | 336 JSONStringValueSerializer serializer(output); |
360 serializer.set_pretty_print(true); | 337 serializer.set_pretty_print(true); |
361 return serializer.Serialize(*prefs_); | 338 return serializer.Serialize(*prefs_); |
362 } | 339 } |
363 | |
364 void JsonPrefStore::FinalizeFileRead(bool initialization_successful, | |
365 scoped_ptr<base::DictionaryValue> prefs, | |
366 bool schedule_write) { | |
367 filtering_in_progress_ = false; | |
368 | |
369 if (!initialization_successful) { | |
370 FOR_EACH_OBSERVER(PrefStore::Observer, | |
371 observers_, | |
372 OnInitializationCompleted(false)); | |
373 return; | |
374 } | |
375 | |
376 prefs_ = prefs.Pass(); | |
377 | |
378 initialized_ = true; | |
379 | |
380 if (schedule_write && !read_only_) | |
381 writer_.ScheduleWrite(this); | |
382 | |
383 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | |
384 error_delegate_->OnError(read_error_); | |
385 | |
386 FOR_EACH_OBSERVER(PrefStore::Observer, | |
387 observers_, | |
388 OnInitializationCompleted(true)); | |
389 | |
390 return; | |
391 } | |
OLD | NEW |