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) |
171 : path_(filename), | 164 : path_(filename), |
172 alternate_path_(alternate_filename), | 165 alternate_path_(alternate_filename), |
173 sequenced_task_runner_(sequenced_task_runner), | 166 sequenced_task_runner_(sequenced_task_runner), |
174 prefs_(new base::DictionaryValue()), | 167 prefs_(new base::DictionaryValue()), |
175 read_only_(false), | 168 read_only_(false), |
176 writer_(filename, sequenced_task_runner), | 169 writer_(filename, sequenced_task_runner), |
177 pref_filter_(pref_filter.Pass()), | 170 pref_filter_(pref_filter.Pass()), |
178 initialized_(false), | 171 initialized_(false), |
179 filtering_in_progress_(false), | 172 filtering_in_progress_(false), |
| 173 pending_lossy_write_(false), |
180 read_error_(PREF_READ_ERROR_NONE), | 174 read_error_(PREF_READ_ERROR_NONE), |
181 write_count_histogram_(writer_.commit_interval(), path_) { | 175 write_count_histogram_(writer_.commit_interval(), path_) { |
182 DCHECK(!path_.empty()); | 176 DCHECK(!path_.empty()); |
183 } | 177 } |
184 | 178 |
185 bool JsonPrefStore::GetValue(const std::string& key, | 179 bool JsonPrefStore::GetValue(const std::string& key, |
186 const base::Value** result) const { | 180 const base::Value** result) const { |
187 DCHECK(CalledOnValidThread()); | 181 DCHECK(CalledOnValidThread()); |
188 | 182 |
189 base::Value* tmp = NULL; | 183 base::Value* tmp = NULL; |
(...skipping 29 matching lines...) Expand all Loading... |
219 return initialized_; | 213 return initialized_; |
220 } | 214 } |
221 | 215 |
222 bool JsonPrefStore::GetMutableValue(const std::string& key, | 216 bool JsonPrefStore::GetMutableValue(const std::string& key, |
223 base::Value** result) { | 217 base::Value** result) { |
224 DCHECK(CalledOnValidThread()); | 218 DCHECK(CalledOnValidThread()); |
225 | 219 |
226 return prefs_->Get(key, result); | 220 return prefs_->Get(key, result); |
227 } | 221 } |
228 | 222 |
229 void JsonPrefStore::SetValue(const std::string& key, base::Value* value) { | 223 void JsonPrefStore::SetValue(const std::string& key, |
| 224 base::Value* value, |
| 225 uint32 flags) { |
230 DCHECK(CalledOnValidThread()); | 226 DCHECK(CalledOnValidThread()); |
231 | 227 |
232 DCHECK(value); | 228 DCHECK(value); |
233 scoped_ptr<base::Value> new_value(value); | 229 scoped_ptr<base::Value> new_value(value); |
234 base::Value* old_value = NULL; | 230 base::Value* old_value = NULL; |
235 prefs_->Get(key, &old_value); | 231 prefs_->Get(key, &old_value); |
236 if (!old_value || !value->Equals(old_value)) { | 232 if (!old_value || !value->Equals(old_value)) { |
237 prefs_->Set(key, new_value.release()); | 233 prefs_->Set(key, new_value.Pass()); |
238 ReportValueChanged(key); | 234 ReportValueChanged(key, flags); |
239 } | 235 } |
240 } | 236 } |
241 | 237 |
242 void JsonPrefStore::SetValueSilently(const std::string& key, | 238 void JsonPrefStore::SetValueSilently(const std::string& key, |
243 base::Value* value) { | 239 base::Value* value, |
| 240 uint32 flags) { |
244 DCHECK(CalledOnValidThread()); | 241 DCHECK(CalledOnValidThread()); |
245 | 242 |
246 DCHECK(value); | 243 DCHECK(value); |
247 scoped_ptr<base::Value> new_value(value); | 244 scoped_ptr<base::Value> new_value(value); |
248 base::Value* old_value = NULL; | 245 base::Value* old_value = NULL; |
249 prefs_->Get(key, &old_value); | 246 prefs_->Get(key, &old_value); |
250 if (!old_value || !value->Equals(old_value)) { | 247 if (!old_value || !value->Equals(old_value)) { |
251 prefs_->Set(key, new_value.release()); | 248 prefs_->Set(key, new_value.Pass()); |
252 if (!read_only_) | 249 ScheduleWrite(flags); |
253 writer_.ScheduleWrite(this); | |
254 } | 250 } |
255 } | 251 } |
256 | 252 |
257 void JsonPrefStore::RemoveValue(const std::string& key) { | 253 void JsonPrefStore::RemoveValue(const std::string& key, uint32 flags) { |
258 DCHECK(CalledOnValidThread()); | 254 DCHECK(CalledOnValidThread()); |
259 | 255 |
260 if (prefs_->RemovePath(key, NULL)) | 256 if (prefs_->RemovePath(key, NULL)) |
261 ReportValueChanged(key); | 257 ReportValueChanged(key, flags); |
262 } | 258 } |
263 | 259 |
264 void JsonPrefStore::RemoveValueSilently(const std::string& key) { | 260 void JsonPrefStore::RemoveValueSilently(const std::string& key, uint32 flags) { |
265 DCHECK(CalledOnValidThread()); | 261 DCHECK(CalledOnValidThread()); |
266 | 262 |
267 prefs_->RemovePath(key, NULL); | 263 prefs_->RemovePath(key, NULL); |
268 if (!read_only_) | 264 ScheduleWrite(flags); |
269 writer_.ScheduleWrite(this); | |
270 } | 265 } |
271 | 266 |
272 bool JsonPrefStore::ReadOnly() const { | 267 bool JsonPrefStore::ReadOnly() const { |
273 DCHECK(CalledOnValidThread()); | 268 DCHECK(CalledOnValidThread()); |
274 | 269 |
275 return read_only_; | 270 return read_only_; |
276 } | 271 } |
277 | 272 |
278 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { | 273 PersistentPrefStore::PrefReadError JsonPrefStore::GetReadError() const { |
279 DCHECK(CalledOnValidThread()); | 274 DCHECK(CalledOnValidThread()); |
(...skipping 19 matching lines...) Expand all Loading... |
299 base::PostTaskAndReplyWithResult( | 294 base::PostTaskAndReplyWithResult( |
300 sequenced_task_runner_.get(), | 295 sequenced_task_runner_.get(), |
301 FROM_HERE, | 296 FROM_HERE, |
302 base::Bind(&ReadPrefsFromDisk, path_, alternate_path_), | 297 base::Bind(&ReadPrefsFromDisk, path_, alternate_path_), |
303 base::Bind(&JsonPrefStore::OnFileRead, AsWeakPtr())); | 298 base::Bind(&JsonPrefStore::OnFileRead, AsWeakPtr())); |
304 } | 299 } |
305 | 300 |
306 void JsonPrefStore::CommitPendingWrite() { | 301 void JsonPrefStore::CommitPendingWrite() { |
307 DCHECK(CalledOnValidThread()); | 302 DCHECK(CalledOnValidThread()); |
308 | 303 |
| 304 // Schedule a write for any lossy writes that are outstanding to ensure that |
| 305 // they get flushed when this function is called. |
| 306 if (pending_lossy_write_) |
| 307 writer_.ScheduleWrite(this); |
| 308 |
309 if (writer_.HasPendingWrite() && !read_only_) | 309 if (writer_.HasPendingWrite() && !read_only_) |
310 writer_.DoScheduledWrite(); | 310 writer_.DoScheduledWrite(); |
311 } | 311 } |
312 | 312 |
313 void JsonPrefStore::ReportValueChanged(const std::string& key) { | 313 void JsonPrefStore::ReportValueChanged(const std::string& key, uint32 flags) { |
314 DCHECK(CalledOnValidThread()); | 314 DCHECK(CalledOnValidThread()); |
315 | 315 |
316 if (pref_filter_) | 316 if (pref_filter_) |
317 pref_filter_->FilterUpdate(key); | 317 pref_filter_->FilterUpdate(key); |
318 | 318 |
319 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); | 319 FOR_EACH_OBSERVER(PrefStore::Observer, observers_, OnPrefValueChanged(key)); |
320 | 320 |
321 if (!read_only_) | 321 ScheduleWrite(flags); |
322 writer_.ScheduleWrite(this); | |
323 } | 322 } |
324 | 323 |
325 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( | 324 void JsonPrefStore::RegisterOnNextSuccessfulWriteCallback( |
326 const base::Closure& on_next_successful_write) { | 325 const base::Closure& on_next_successful_write) { |
327 DCHECK(CalledOnValidThread()); | 326 DCHECK(CalledOnValidThread()); |
328 | 327 |
329 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); | 328 writer_.RegisterOnNextSuccessfulWriteCallback(on_next_successful_write); |
330 } | 329 } |
331 | 330 |
332 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { | 331 void JsonPrefStore::OnFileRead(scoped_ptr<ReadResult> read_result) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 } | 390 } |
392 } | 391 } |
393 | 392 |
394 JsonPrefStore::~JsonPrefStore() { | 393 JsonPrefStore::~JsonPrefStore() { |
395 CommitPendingWrite(); | 394 CommitPendingWrite(); |
396 } | 395 } |
397 | 396 |
398 bool JsonPrefStore::SerializeData(std::string* output) { | 397 bool JsonPrefStore::SerializeData(std::string* output) { |
399 DCHECK(CalledOnValidThread()); | 398 DCHECK(CalledOnValidThread()); |
400 | 399 |
| 400 pending_lossy_write_ = false; |
| 401 |
401 write_count_histogram_.RecordWriteOccured(); | 402 write_count_histogram_.RecordWriteOccured(); |
402 | 403 |
403 if (pref_filter_) | 404 if (pref_filter_) |
404 pref_filter_->FilterSerializeData(prefs_.get()); | 405 pref_filter_->FilterSerializeData(prefs_.get()); |
405 | 406 |
406 JSONStringValueSerializer serializer(output); | 407 JSONStringValueSerializer serializer(output); |
407 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain | 408 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain |
408 // readable prefs for debugging purposes, you can dump your prefs into any | 409 // readable prefs for debugging purposes, you can dump your prefs into any |
409 // command-line or online JSON pretty printing tool. | 410 // command-line or online JSON pretty printing tool. |
410 serializer.set_pretty_print(false); | 411 serializer.set_pretty_print(false); |
(...skipping 11 matching lines...) Expand all Loading... |
422 FOR_EACH_OBSERVER(PrefStore::Observer, | 423 FOR_EACH_OBSERVER(PrefStore::Observer, |
423 observers_, | 424 observers_, |
424 OnInitializationCompleted(false)); | 425 OnInitializationCompleted(false)); |
425 return; | 426 return; |
426 } | 427 } |
427 | 428 |
428 prefs_ = prefs.Pass(); | 429 prefs_ = prefs.Pass(); |
429 | 430 |
430 initialized_ = true; | 431 initialized_ = true; |
431 | 432 |
432 if (schedule_write && !read_only_) | 433 if (schedule_write) |
433 writer_.ScheduleWrite(this); | 434 ScheduleWrite(DEFAULT_PREF_WRITE_FLAGS); |
434 | 435 |
435 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | 436 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) |
436 error_delegate_->OnError(read_error_); | 437 error_delegate_->OnError(read_error_); |
437 | 438 |
438 FOR_EACH_OBSERVER(PrefStore::Observer, | 439 FOR_EACH_OBSERVER(PrefStore::Observer, |
439 observers_, | 440 observers_, |
440 OnInitializationCompleted(true)); | 441 OnInitializationCompleted(true)); |
441 | 442 |
442 return; | 443 return; |
443 } | 444 } |
444 | 445 |
| 446 void JsonPrefStore::ScheduleWrite(uint32 flags) { |
| 447 if (read_only_) |
| 448 return; |
| 449 |
| 450 if (flags & LOSSY_PREF_WRITE_FLAG) |
| 451 pending_lossy_write_ = true; |
| 452 else |
| 453 writer_.ScheduleWrite(this); |
| 454 } |
| 455 |
445 // NOTE: This value should NOT be changed without renaming the histogram | 456 // NOTE: This value should NOT be changed without renaming the histogram |
446 // otherwise it will create incompatible buckets. | 457 // otherwise it will create incompatible buckets. |
447 const int32_t | 458 const int32_t |
448 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins = 5; | 459 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins = 5; |
449 | 460 |
450 JsonPrefStore::WriteCountHistogram::WriteCountHistogram( | 461 JsonPrefStore::WriteCountHistogram::WriteCountHistogram( |
451 const base::TimeDelta& commit_interval, | 462 const base::TimeDelta& commit_interval, |
452 const base::FilePath& path) | 463 const base::FilePath& path) |
453 : WriteCountHistogram(commit_interval, | 464 : WriteCountHistogram(commit_interval, |
454 path, | 465 path, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 DCHECK_EQ(31, num_buckets); | 533 DCHECK_EQ(31, num_buckets); |
523 | 534 |
524 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS | 535 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS |
525 // macro adapted to allow for a dynamically suffixed histogram name. | 536 // macro adapted to allow for a dynamically suffixed histogram name. |
526 // Note: The factory creates and owns the histogram. | 537 // Note: The factory creates and owns the histogram. |
527 base::HistogramBase* histogram = base::Histogram::FactoryGet( | 538 base::HistogramBase* histogram = base::Histogram::FactoryGet( |
528 histogram_name, min_value, max_value, num_buckets, | 539 histogram_name, min_value, max_value, num_buckets, |
529 base::HistogramBase::kUmaTargetedHistogramFlag); | 540 base::HistogramBase::kUmaTargetedHistogramFlag); |
530 return histogram; | 541 return histogram; |
531 } | 542 } |
OLD | NEW |