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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 token.append(filename.AsUTF8Unsafe()); | 143 token.append(filename.AsUTF8Unsafe()); |
144 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( | 144 return worker_pool->GetSequencedTaskRunnerWithShutdownBehavior( |
145 worker_pool->GetNamedSequenceToken(token), | 145 worker_pool->GetNamedSequenceToken(token), |
146 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 146 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
147 } | 147 } |
148 | 148 |
149 JsonPrefStore::JsonPrefStore( | 149 JsonPrefStore::JsonPrefStore( |
150 const base::FilePath& filename, | 150 const base::FilePath& filename, |
151 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, | 151 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, |
152 scoped_ptr<PrefFilter> pref_filter) | 152 scoped_ptr<PrefFilter> pref_filter) |
153 : path_(filename), | 153 : JsonPrefStore(filename, |
154 sequenced_task_runner_(sequenced_task_runner), | 154 base::FilePath(), |
155 prefs_(new base::DictionaryValue()), | 155 sequenced_task_runner, |
156 read_only_(false), | 156 pref_filter.Pass()) { |
157 writer_(filename, sequenced_task_runner), | |
158 pref_filter_(pref_filter.Pass()), | |
159 initialized_(false), | |
160 filtering_in_progress_(false), | |
161 read_error_(PREF_READ_ERROR_NONE), | |
162 write_count_histogram_(writer_.commit_interval(), path_) { | |
163 DCHECK(!path_.empty()); | |
164 } | 157 } |
165 | 158 |
166 JsonPrefStore::JsonPrefStore( | 159 JsonPrefStore::JsonPrefStore( |
167 const base::FilePath& filename, | 160 const base::FilePath& filename, |
168 const base::FilePath& alternate_filename, | 161 const base::FilePath& alternate_filename, |
169 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, | 162 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, |
170 scoped_ptr<PrefFilter> pref_filter) | 163 scoped_ptr<PrefFilter> pref_filter) |
| 164 : JsonPrefStore( |
| 165 filename, |
| 166 alternate_filename, |
| 167 sequenced_task_runner, |
| 168 scoped_ptr<base::ImportantFileWriter>( |
| 169 new base::ImportantFileWriterImpl(filename, |
| 170 sequenced_task_runner)), |
| 171 pref_filter.Pass()) { |
| 172 } |
| 173 |
| 174 JsonPrefStore::JsonPrefStore( |
| 175 const base::FilePath& filename, |
| 176 const base::FilePath& alternate_filename, |
| 177 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, |
| 178 scoped_ptr<base::ImportantFileWriter> file_writer, |
| 179 scoped_ptr<PrefFilter> pref_filter) |
171 : path_(filename), | 180 : path_(filename), |
172 alternate_path_(alternate_filename), | 181 alternate_path_(alternate_filename), |
173 sequenced_task_runner_(sequenced_task_runner), | 182 sequenced_task_runner_(sequenced_task_runner), |
174 prefs_(new base::DictionaryValue()), | 183 prefs_(new base::DictionaryValue()), |
175 read_only_(false), | 184 read_only_(false), |
176 writer_(filename, sequenced_task_runner), | 185 writer_(file_writer.Pass()), |
177 pref_filter_(pref_filter.Pass()), | 186 pref_filter_(pref_filter.Pass()), |
178 initialized_(false), | 187 initialized_(false), |
179 filtering_in_progress_(false), | 188 filtering_in_progress_(false), |
180 read_error_(PREF_READ_ERROR_NONE), | 189 read_error_(PREF_READ_ERROR_NONE), |
181 write_count_histogram_(writer_.commit_interval(), path_) { | 190 write_count_histogram_(writer_->CommitInterval(), path_) { |
182 DCHECK(!path_.empty()); | 191 DCHECK(!path_.empty()); |
183 } | 192 } |
184 | 193 |
185 bool JsonPrefStore::GetValue(const std::string& key, | 194 bool JsonPrefStore::GetValue(const std::string& key, |
186 const base::Value** result) const { | 195 const base::Value** result) const { |
187 DCHECK(CalledOnValidThread()); | 196 DCHECK(CalledOnValidThread()); |
188 | 197 |
189 base::Value* tmp = NULL; | 198 base::Value* tmp = NULL; |
190 if (!prefs_->Get(key, &tmp)) | 199 if (!prefs_->Get(key, &tmp)) |
191 return false; | 200 return false; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 base::Value* value, | 254 base::Value* value, |
246 uint32 flags) { | 255 uint32 flags) { |
247 DCHECK(CalledOnValidThread()); | 256 DCHECK(CalledOnValidThread()); |
248 | 257 |
249 DCHECK(value); | 258 DCHECK(value); |
250 scoped_ptr<base::Value> new_value(value); | 259 scoped_ptr<base::Value> new_value(value); |
251 base::Value* old_value = NULL; | 260 base::Value* old_value = NULL; |
252 prefs_->Get(key, &old_value); | 261 prefs_->Get(key, &old_value); |
253 if (!old_value || !value->Equals(old_value)) { | 262 if (!old_value || !value->Equals(old_value)) { |
254 prefs_->Set(key, new_value.release()); | 263 prefs_->Set(key, new_value.release()); |
255 if (!read_only_) | 264 ScheduleWrite(flags); |
256 writer_.ScheduleWrite(this); | |
257 } | 265 } |
258 } | 266 } |
259 | 267 |
260 void JsonPrefStore::RemoveValue(const std::string& key, uint32 flags) { | 268 void JsonPrefStore::RemoveValue(const std::string& key, uint32 flags) { |
261 DCHECK(CalledOnValidThread()); | 269 DCHECK(CalledOnValidThread()); |
262 | 270 |
263 if (prefs_->RemovePath(key, NULL)) | 271 if (prefs_->RemovePath(key, NULL)) |
264 ReportValueChanged(key, flags); | 272 ReportValueChanged(key, flags); |
265 } | 273 } |
266 | 274 |
267 void JsonPrefStore::RemoveValueSilently(const std::string& key, uint32 flags) { | 275 void JsonPrefStore::RemoveValueSilently(const std::string& key, uint32 flags) { |
268 DCHECK(CalledOnValidThread()); | 276 DCHECK(CalledOnValidThread()); |
269 | 277 |
270 prefs_->RemovePath(key, NULL); | 278 prefs_->RemovePath(key, NULL); |
271 if (!read_only_) | 279 ScheduleWrite(flags); |
272 writer_.ScheduleWrite(this); | |
273 } | 280 } |
274 | 281 |
275 bool JsonPrefStore::ReadOnly() const { | 282 bool JsonPrefStore::ReadOnly() const { |
276 DCHECK(CalledOnValidThread()); | 283 DCHECK(CalledOnValidThread()); |
277 | 284 |
278 return read_only_; | 285 return read_only_; |
279 } | 286 } |
280 | 287 |
281 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 288 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
282 DCHECK(CalledOnValidThread()); | 289 DCHECK(CalledOnValidThread()); |
(...skipping 19 matching lines...) Expand all Loading... |
302 base::PostTaskAndReplyWithResult( | 309 base::PostTaskAndReplyWithResult( |
303 sequenced_task_runner_.get(), | 310 sequenced_task_runner_.get(), |
304 FROM_HERE, | 311 FROM_HERE, |
305 base::Bind(&ReadPrefsFromDisk, path_, alternate_path_), | 312 base::Bind(&ReadPrefsFromDisk, path_, alternate_path_), |
306 base::Bind(&JsonPrefStore::OnFileRead, AsWeakPtr())); | 313 base::Bind(&JsonPrefStore::OnFileRead, AsWeakPtr())); |
307 } | 314 } |
308 | 315 |
309 void JsonPrefStore::CommitPendingWrite() { | 316 void JsonPrefStore::CommitPendingWrite() { |
310 DCHECK(CalledOnValidThread()); | 317 DCHECK(CalledOnValidThread()); |
311 | 318 |
312 if (writer_.HasPendingWrite() && !read_only_) | 319 // Schedule a write for any lossy writes that are outstanding to ensure that |
313 writer_.DoScheduledWrite(); | 320 // they get flushed when this function is called. |
| 321 if (pending_lossy_write_) |
| 322 writer_->ScheduleWrite(this); |
| 323 |
| 324 if (writer_->HasPendingWrite() && !read_only_) |
| 325 writer_->DoScheduledWrite(); |
314 } | 326 } |
315 | 327 |
316 void JsonPrefStore::ReportValueChanged(const std::string& key, uint32 flags) { | 328 void JsonPrefStore::ReportValueChanged(const std::string& key, uint32 flags) { |
317 DCHECK(CalledOnValidThread()); | 329 DCHECK(CalledOnValidThread()); |
318 | 330 |
319 if (pref_filter_) | 331 if (pref_filter_) |
320 pref_filter_->FilterUpdate(key); | 332 pref_filter_->FilterUpdate(key); |
321 | 333 |
322 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 334 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
323 | 335 |
324 if (!read_only_) | 336 ScheduleWrite(flags); |
325 writer_.ScheduleWrite(this); | |
326 } | 337 } |
327 | 338 |
328 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( | 339 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( |
329 const base::Closure& on_next_successful_write) { | 340 const base::Closure& on_next_successful_write) { |
330 DCHECK(CalledOnValidThread()); | 341 DCHECK(CalledOnValidThread()); |
331 | 342 |
332 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); | 343 writer_->RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); |
333 } | 344 } |
334 | 345 |
335 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { | 346 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { |
336 DCHECK(CalledOnValidThread()); | 347 DCHECK(CalledOnValidThread()); |
337 | 348 |
338 DCHECK(read_result); | 349 DCHECK(read_result); |
339 | 350 |
340 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); | 351 scoped_ptr<base::DictionaryValue> unfiltered_prefs(new base::DictionaryValue); |
341 | 352 |
342 read_error_ = read_result->error; | 353 read_error_ = read_result->error; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 } | 405 } |
395 } | 406 } |
396 | 407 |
397 JsonPrefStore::~JsonPrefStore() { | 408 JsonPrefStore::~JsonPrefStore() { |
398 CommitPendingWrite(); | 409 CommitPendingWrite(); |
399 } | 410 } |
400 | 411 |
401 bool JsonPrefStore::SerializeData(std::string* output) { | 412 bool JsonPrefStore::SerializeData(std::string* output) { |
402 DCHECK(CalledOnValidThread()); | 413 DCHECK(CalledOnValidThread()); |
403 | 414 |
| 415 pending_lossy_write_ = false; |
| 416 |
404 write_count_histogram_.RecordWriteOccured(); | 417 write_count_histogram_.RecordWriteOccured(); |
405 | 418 |
406 if (pref_filter_) | 419 if (pref_filter_) |
407 pref_filter_->FilterSerializeData(prefs_.get()); | 420 pref_filter_->FilterSerializeData(prefs_.get()); |
408 | 421 |
409 JSONStringValueSerializer serializer(output); | 422 JSONStringValueSerializer serializer(output); |
410 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain | 423 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain |
411 // readable prefs for debugging purposes, you can dump your prefs into any | 424 // readable prefs for debugging purposes, you can dump your prefs into any |
412 // command-line or online JSON pretty printing tool. | 425 // command-line or online JSON pretty printing tool. |
413 serializer.set_pretty_print(false); | 426 serializer.set_pretty_print(false); |
(...skipping 11 matching lines...) Expand all Loading... |
425 FOR_EACH_OBSERVER(PrefStore::Observer, | 438 FOR_EACH_OBSERVER(PrefStore::Observer, |
426 observers_, | 439 observers_, |
427 OnInitializationCompleted(false)); | 440 OnInitializationCompleted(false)); |
428 return; | 441 return; |
429 } | 442 } |
430 | 443 |
431 prefs_ = prefs.Pass(); | 444 prefs_ = prefs.Pass(); |
432 | 445 |
433 initialized_ = true; | 446 initialized_ = true; |
434 | 447 |
435 if (schedule_write && !read_only_) | 448 if (schedule_write) |
436 writer_.ScheduleWrite(this); | 449 ScheduleWrite(DEFAULT_PREF_WRITE_FLAGS); |
437 | 450 |
438 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | 451 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) |
439 error_delegate_->OnError(read_error_); | 452 error_delegate_->OnError(read_error_); |
440 | 453 |
441 FOR_EACH_OBSERVER(PrefStore::Observer, | 454 FOR_EACH_OBSERVER(PrefStore::Observer, |
442 observers_, | 455 observers_, |
443 OnInitializationCompleted(true)); | 456 OnInitializationCompleted(true)); |
444 | 457 |
445 return; | 458 return; |
446 } | 459 } |
447 | 460 |
| 461 void JsonPrefStore::ScheduleWrite(uint32 flags) { |
| 462 if (read_only_) |
| 463 return; |
| 464 |
| 465 if (flags & LOSSY_PREF_WRITE_FLAG) |
| 466 pending_lossy_write_ = true; |
| 467 else |
| 468 writer_->ScheduleWrite(this); |
| 469 } |
| 470 |
448 // NOTE: This value should NOT be changed without renaming the histogram | 471 // NOTE: This value should NOT be changed without renaming the histogram |
449 // otherwise it will create incompatible buckets. | 472 // otherwise it will create incompatible buckets. |
450 const int32_t | 473 const int32_t |
451 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins = 5; | 474 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins = 5; |
452 | 475 |
453 JsonPrefStore::WriteCountHistogram::WriteCountHistogram( | 476 JsonPrefStore::WriteCountHistogram::WriteCountHistogram( |
454 const base::TimeDelta& commit_interval, | 477 const base::TimeDelta& commit_interval, |
455 const base::FilePath& path) | 478 const base::FilePath& path) |
456 : WriteCountHistogram(commit_interval, | 479 : WriteCountHistogram(commit_interval, |
457 path, | 480 path, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 DCHECK_EQ(31, num_buckets); | 548 DCHECK_EQ(31, num_buckets); |
526 | 549 |
527 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS | 550 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS |
528 // macro adapted to allow for a dynamically suffixed histogram name. | 551 // macro adapted to allow for a dynamically suffixed histogram name. |
529 // Note: The factory creates and owns the histogram. | 552 // Note: The factory creates and owns the histogram. |
530 base::HistogramBase* histogram = base::Histogram::FactoryGet( | 553 base::HistogramBase* histogram = base::Histogram::FactoryGet( |
531 histogram_name, min_value, max_value, num_buckets, | 554 histogram_name, min_value, max_value, num_buckets, |
532 base::HistogramBase::kUmaTargetedHistogramFlag); | 555 base::HistogramBase::kUmaTargetedHistogramFlag); |
533 return histogram; | 556 return histogram; |
534 } | 557 } |
OLD | NEW |