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. |
42 sequenced_task_runner_->PostTask( | 44 sequenced_task_runner_->PostTask( |
43 FROM_HERE, | 45 FROM_HERE, |
44 base::Bind(&FileThreadDeserializer::ReadFileAndReport, | 46 base::Bind(&FileThreadDeserializer::ReadFileAndReport, |
45 this, path)); | 47 this, path)); |
46 } | 48 } |
47 | 49 |
48 // Deserializes JSON on the sequenced task runner. | 50 // Deserializes JSON on the sequenced task runner. |
49 void ReadFileAndReport(const base::FilePath& path) { | 51 void ReadFileAndReport(const base::FilePath& path) { |
50 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); | 52 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); |
51 | 53 |
52 value_.reset(DoReading(path, &error_, &no_dir_)); | 54 value_.reset(DoReading(path, &error_, &no_dir_)); |
53 | 55 |
54 origin_loop_proxy_->PostTask( | 56 origin_loop_proxy_->PostTask( |
55 FROM_HERE, | 57 FROM_HERE, |
56 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); | 58 base::Bind(&FileThreadDeserializer::ReportOnOriginThread, this)); |
57 } | 59 } |
58 | 60 |
59 // Reports deserialization result on the origin thread. | 61 // Reports deserialization result on the origin thread. |
60 void ReportOnOriginThread() { | 62 void ReportOnOriginThread() { |
61 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); | 63 DCHECK(origin_loop_proxy_->BelongsToCurrentThread()); |
62 delegate_->OnFileRead(value_.release(), error_, no_dir_); | 64 delegate_->OnFileRead(value_.Pass(), error_, no_dir_); |
63 } | 65 } |
64 | 66 |
65 static base::Value* DoReading(const base::FilePath& path, | 67 static base::Value* DoReading(const base::FilePath& path, |
66 PersistentPrefStore::PrefReadError* error, | 68 PersistentPrefStore::PrefReadError* error, |
67 bool* no_dir) { | 69 bool* no_dir) { |
68 int error_code; | 70 int error_code; |
69 std::string error_msg; | 71 std::string error_msg; |
70 JSONFileValueSerializer serializer(path); | 72 JSONFileValueSerializer serializer(path); |
71 base::Value* value = serializer.Deserialize(&error_code, &error_msg); | 73 base::Value* value = serializer.Deserialize(&error_code, &error_msg); |
72 HandleErrors(value, path, error_code, error_msg, error); | 74 HandleErrors(value, path, error_code, error_msg, error); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, | 156 JsonPrefStore::JsonPrefStore(const base::FilePath& filename, |
155 base::SequencedTaskRunner* sequenced_task_runner, | 157 base::SequencedTaskRunner* sequenced_task_runner, |
156 scoped_ptr<PrefFilter> pref_filter) | 158 scoped_ptr<PrefFilter> pref_filter) |
157 : path_(filename), | 159 : path_(filename), |
158 sequenced_task_runner_(sequenced_task_runner), | 160 sequenced_task_runner_(sequenced_task_runner), |
159 prefs_(new base::DictionaryValue()), | 161 prefs_(new base::DictionaryValue()), |
160 read_only_(false), | 162 read_only_(false), |
161 writer_(filename, sequenced_task_runner), | 163 writer_(filename, sequenced_task_runner), |
162 pref_filter_(pref_filter.Pass()), | 164 pref_filter_(pref_filter.Pass()), |
163 initialized_(false), | 165 initialized_(false), |
164 read_error_(PREF_READ_ERROR_OTHER) {} | 166 filtering_in_progress_(false), |
| 167 read_error_(PREF_READ_ERROR_NONE) { |
| 168 } |
165 | 169 |
166 bool JsonPrefStore::GetValue(const std::string& key, | 170 bool JsonPrefStore::GetValue(const std::string& key, |
167 const base::Value** result) const { | 171 const base::Value** result) const { |
168 base::Value* tmp = NULL; | 172 base::Value* tmp = NULL; |
169 if (!prefs_->Get(key, &tmp)) | 173 if (!prefs_->Get(key, &tmp)) |
170 return false; | 174 return false; |
171 | 175 |
172 if (result) | 176 if (result) |
173 *result = tmp; | 177 *result = tmp; |
174 return true; | 178 return true; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 if (!read_only_) | 221 if (!read_only_) |
218 writer_.ScheduleWrite(this); | 222 writer_.ScheduleWrite(this); |
219 } | 223 } |
220 } | 224 } |
221 | 225 |
222 void JsonPrefStore::RemoveValue(const std::string& key) { | 226 void JsonPrefStore::RemoveValue(const std::string& key) { |
223 if (prefs_->RemovePath(key, NULL)) | 227 if (prefs_->RemovePath(key, NULL)) |
224 ReportValueChanged(key); | 228 ReportValueChanged(key); |
225 } | 229 } |
226 | 230 |
| 231 void JsonPrefStore::RemoveValueSilently(const std::string& key) { |
| 232 prefs_->RemovePath(key, NULL); |
| 233 if (!read_only_) |
| 234 writer_.ScheduleWrite(this); |
| 235 } |
| 236 |
227 bool JsonPrefStore::ReadOnly() const { | 237 bool JsonPrefStore::ReadOnly() const { |
228 return read_only_; | 238 return read_only_; |
229 } | 239 } |
230 | 240 |
231 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 241 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
232 return read_error_; | 242 return read_error_; |
233 } | 243 } |
234 | 244 |
235 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { | 245 PersistentPrefStore::PrefReadError JsonPrefStore::ReadPrefs() { |
236 if (path_.empty()) { | 246 if (path_.empty()) { |
237 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 247 OnFileRead( |
| 248 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
238 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | 249 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; |
239 } | 250 } |
240 | 251 |
241 PrefReadError error; | 252 PrefReadError error; |
242 bool no_dir; | 253 bool no_dir; |
243 base::Value* value = | 254 scoped_ptr<base::Value> value( |
244 FileThreadDeserializer::DoReading(path_, &error, &no_dir); | 255 FileThreadDeserializer::DoReading(path_, &error, &no_dir)); |
245 OnFileRead(value, error, no_dir); | 256 OnFileRead(value.Pass(), error, no_dir); |
246 return error; | 257 return filtering_in_progress_ ? PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE : |
| 258 error; |
247 } | 259 } |
248 | 260 |
249 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate *error_delegate) { | 261 void JsonPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { |
250 initialized_ = false; | 262 initialized_ = false; |
251 error_delegate_.reset(error_delegate); | 263 error_delegate_.reset(error_delegate); |
252 if (path_.empty()) { | 264 if (path_.empty()) { |
253 OnFileRead(NULL, PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | 265 OnFileRead( |
| 266 scoped_ptr<base::Value>(), PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); |
254 return; | 267 return; |
255 } | 268 } |
256 | 269 |
257 // Start async reading of the preferences file. It will delete itself | 270 // Start async reading of the preferences file. It will delete itself |
258 // in the end. | 271 // in the end. |
259 scoped_refptr<FileThreadDeserializer> deserializer( | 272 scoped_refptr<FileThreadDeserializer> deserializer( |
260 new FileThreadDeserializer(this, sequenced_task_runner_.get())); | 273 new FileThreadDeserializer(this, sequenced_task_runner_.get())); |
261 deserializer->Start(path_); | 274 deserializer->Start(path_); |
262 } | 275 } |
263 | 276 |
264 void JsonPrefStore::CommitPendingWrite() { | 277 void JsonPrefStore::CommitPendingWrite() { |
265 if (writer_.HasPendingWrite() && !read_only_) | 278 if (writer_.HasPendingWrite() && !read_only_) |
266 writer_.DoScheduledWrite(); | 279 writer_.DoScheduledWrite(); |
267 } | 280 } |
268 | 281 |
269 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 282 void JsonPrefStore::ReportValueChanged(const std::string& key) { |
270 if (pref_filter_) | 283 if (pref_filter_) |
271 pref_filter_->FilterUpdate(key); | 284 pref_filter_->FilterUpdate(key); |
272 | 285 |
273 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 286 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
274 | 287 |
275 if (!read_only_) | 288 if (!read_only_) |
276 writer_.ScheduleWrite(this); | 289 writer_.ScheduleWrite(this); |
277 } | 290 } |
278 | 291 |
279 void JsonPrefStore::OnFileRead(base::Value* value_owned, | 292 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( |
| 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, |
280 PersistentPrefStore::PrefReadError error, | 298 PersistentPrefStore::PrefReadError error, |
281 bool no_dir) { | 299 bool no_dir) { |
282 scoped_ptr<base::Value> value(value_owned); | 300 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); |
| 301 |
283 read_error_ = error; | 302 read_error_ = error; |
284 | 303 |
285 if (no_dir) { | 304 bool initialization_successful = !no_dir; |
286 FOR_EACH_OBSERVER(PrefStore::Observer, | 305 |
287 observers_, | 306 if (initialization_successful) { |
288 OnInitializationCompleted(false)); | 307 switch (read_error_) { |
289 return; | 308 case PREF_READ_ERROR_ACCESS_DENIED: |
| 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 } |
290 } | 337 } |
291 | 338 |
292 initialized_ = true; | 339 if (pref_filter_) { |
293 | 340 filtering_in_progress_ = true; |
294 switch (error) { | 341 const PrefFilter::PostFilterOnLoadCallback post_filter_on_load_callback( |
295 case PREF_READ_ERROR_ACCESS_DENIED: | 342 base::Bind( |
296 case PREF_READ_ERROR_FILE_OTHER: | 343 &JsonPrefStore::FinalizeFileRead, this, initialization_successful)); |
297 case PREF_READ_ERROR_FILE_LOCKED: | 344 pref_filter_->FilterOnLoad(post_filter_on_load_callback, |
298 case PREF_READ_ERROR_JSON_TYPE: | 345 unfiltered_prefs.Pass()); |
299 case PREF_READ_ERROR_FILE_NOT_SPECIFIED: | 346 } else { |
300 read_only_ = true; | 347 FinalizeFileRead(initialization_successful, unfiltered_prefs.Pass(), false); |
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; | |
315 } | 348 } |
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)); | |
326 } | 349 } |
327 | 350 |
328 JsonPrefStore::~JsonPrefStore() { | 351 JsonPrefStore::~JsonPrefStore() { |
329 CommitPendingWrite(); | 352 CommitPendingWrite(); |
330 } | 353 } |
331 | 354 |
332 bool JsonPrefStore::SerializeData(std::string* output) { | 355 bool JsonPrefStore::SerializeData(std::string* output) { |
333 if (pref_filter_) | 356 if (pref_filter_) |
334 pref_filter_->FilterSerializeData(prefs_.get()); | 357 pref_filter_->FilterSerializeData(prefs_.get()); |
335 | 358 |
336 JSONStringValueSerializer serializer(output); | 359 JSONStringValueSerializer serializer(output); |
337 serializer.set_pretty_print(true); | 360 serializer.set_pretty_print(true); |
338 return serializer.Serialize(*prefs_); | 361 return serializer.Serialize(*prefs_); |
339 } | 362 } |
| 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 |