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

Side by Side Diff: base/prefs/pref_service.cc

Issue 1648403002: Move base/prefs to components/prefs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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
« no previous file with comments | « base/prefs/pref_service.h ('k') | base/prefs/pref_service_factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/prefs/pref_service.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/prefs/default_pref_store.h"
16 #include "base/prefs/pref_notifier_impl.h"
17 #include "base/prefs/pref_registry.h"
18 #include "base/prefs/pref_value_store.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_util.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "base/value_conversions.h"
25 #include "build/build_config.h"
26
27 namespace {
28
29 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate {
30 public:
31 ReadErrorHandler(base::Callback<void(PersistentPrefStore::PrefReadError)> cb)
32 : callback_(cb) {}
33
34 void OnError(PersistentPrefStore::PrefReadError error) override {
35 callback_.Run(error);
36 }
37
38 private:
39 base::Callback<void(PersistentPrefStore::PrefReadError)> callback_;
40 };
41
42 // Returns the WriteablePrefStore::PrefWriteFlags for the pref with the given
43 // |path|.
44 uint32_t GetWriteFlags(const PrefService::Preference* pref) {
45 uint32_t write_flags = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
46
47 if (!pref)
48 return write_flags;
49
50 if (pref->registration_flags() & PrefRegistry::LOSSY_PREF)
51 write_flags |= WriteablePrefStore::LOSSY_PREF_WRITE_FLAG;
52 return write_flags;
53 }
54
55 } // namespace
56
57 PrefService::PrefService(
58 PrefNotifierImpl* pref_notifier,
59 PrefValueStore* pref_value_store,
60 PersistentPrefStore* user_prefs,
61 PrefRegistry* pref_registry,
62 base::Callback<void(PersistentPrefStore::PrefReadError)>
63 read_error_callback,
64 bool async)
65 : pref_notifier_(pref_notifier),
66 pref_value_store_(pref_value_store),
67 pref_registry_(pref_registry),
68 user_pref_store_(user_prefs),
69 read_error_callback_(read_error_callback) {
70 pref_notifier_->SetPrefService(this);
71
72 // TODO(battre): This is a check for crbug.com/435208 to make sure that
73 // access violations are caused by a use-after-free bug and not by an
74 // initialization bug.
75 CHECK(pref_registry_);
76 CHECK(pref_value_store_);
77
78 InitFromStorage(async);
79 }
80
81 PrefService::~PrefService() {
82 DCHECK(CalledOnValidThread());
83
84 // Reset pointers so accesses after destruction reliably crash.
85 pref_value_store_.reset();
86 pref_registry_ = NULL;
87 user_pref_store_ = NULL;
88 pref_notifier_.reset();
89 }
90
91 void PrefService::InitFromStorage(bool async) {
92 if (user_pref_store_->IsInitializationComplete()) {
93 read_error_callback_.Run(user_pref_store_->GetReadError());
94 } else if (!async) {
95 read_error_callback_.Run(user_pref_store_->ReadPrefs());
96 } else {
97 // Guarantee that initialization happens after this function returned.
98 base::ThreadTaskRunnerHandle::Get()->PostTask(
99 FROM_HERE,
100 base::Bind(&PersistentPrefStore::ReadPrefsAsync, user_pref_store_.get(),
101 new ReadErrorHandler(read_error_callback_)));
102 }
103 }
104
105 void PrefService::CommitPendingWrite() {
106 DCHECK(CalledOnValidThread());
107 user_pref_store_->CommitPendingWrite();
108 }
109
110 void PrefService::SchedulePendingLossyWrites() {
111 DCHECK(CalledOnValidThread());
112 user_pref_store_->SchedulePendingLossyWrites();
113 }
114
115 bool PrefService::GetBoolean(const std::string& path) const {
116 DCHECK(CalledOnValidThread());
117
118 bool result = false;
119
120 const base::Value* value = GetPreferenceValue(path);
121 if (!value) {
122 NOTREACHED() << "Trying to read an unregistered pref: " << path;
123 return result;
124 }
125 bool rv = value->GetAsBoolean(&result);
126 DCHECK(rv);
127 return result;
128 }
129
130 int PrefService::GetInteger(const std::string& path) const {
131 DCHECK(CalledOnValidThread());
132
133 int result = 0;
134
135 const base::Value* value = GetPreferenceValue(path);
136 if (!value) {
137 NOTREACHED() << "Trying to read an unregistered pref: " << path;
138 return result;
139 }
140 bool rv = value->GetAsInteger(&result);
141 DCHECK(rv);
142 return result;
143 }
144
145 double PrefService::GetDouble(const std::string& path) const {
146 DCHECK(CalledOnValidThread());
147
148 double result = 0.0;
149
150 const base::Value* value = GetPreferenceValue(path);
151 if (!value) {
152 NOTREACHED() << "Trying to read an unregistered pref: " << path;
153 return result;
154 }
155 bool rv = value->GetAsDouble(&result);
156 DCHECK(rv);
157 return result;
158 }
159
160 std::string PrefService::GetString(const std::string& path) const {
161 DCHECK(CalledOnValidThread());
162
163 std::string result;
164
165 const base::Value* value = GetPreferenceValue(path);
166 if (!value) {
167 NOTREACHED() << "Trying to read an unregistered pref: " << path;
168 return result;
169 }
170 bool rv = value->GetAsString(&result);
171 DCHECK(rv);
172 return result;
173 }
174
175 base::FilePath PrefService::GetFilePath(const std::string& path) const {
176 DCHECK(CalledOnValidThread());
177
178 base::FilePath result;
179
180 const base::Value* value = GetPreferenceValue(path);
181 if (!value) {
182 NOTREACHED() << "Trying to read an unregistered pref: " << path;
183 return base::FilePath(result);
184 }
185 bool rv = base::GetValueAsFilePath(*value, &result);
186 DCHECK(rv);
187 return result;
188 }
189
190 bool PrefService::HasPrefPath(const std::string& path) const {
191 const Preference* pref = FindPreference(path);
192 return pref && !pref->IsDefaultValue();
193 }
194
195 scoped_ptr<base::DictionaryValue> PrefService::GetPreferenceValues() const {
196 DCHECK(CalledOnValidThread());
197 scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue);
198 for (const auto& it : *pref_registry_) {
199 out->Set(it.first, GetPreferenceValue(it.first)->CreateDeepCopy());
200 }
201 return out;
202 }
203
204 scoped_ptr<base::DictionaryValue> PrefService::GetPreferenceValuesOmitDefaults()
205 const {
206 DCHECK(CalledOnValidThread());
207 scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue);
208 for (const auto& it : *pref_registry_) {
209 const Preference* pref = FindPreference(it.first);
210 if (pref->IsDefaultValue())
211 continue;
212 out->Set(it.first, pref->GetValue()->CreateDeepCopy());
213 }
214 return out;
215 }
216
217 scoped_ptr<base::DictionaryValue>
218 PrefService::GetPreferenceValuesWithoutPathExpansion() const {
219 DCHECK(CalledOnValidThread());
220 scoped_ptr<base::DictionaryValue> out(new base::DictionaryValue);
221 for (const auto& it : *pref_registry_) {
222 const base::Value* value = GetPreferenceValue(it.first);
223 DCHECK(value);
224 out->SetWithoutPathExpansion(it.first, value->CreateDeepCopy());
225 }
226 return out;
227 }
228
229 const PrefService::Preference* PrefService::FindPreference(
230 const std::string& pref_name) const {
231 DCHECK(CalledOnValidThread());
232 PreferenceMap::iterator it = prefs_map_.find(pref_name);
233 if (it != prefs_map_.end())
234 return &(it->second);
235 const base::Value* default_value = NULL;
236 if (!pref_registry_->defaults()->GetValue(pref_name, &default_value))
237 return NULL;
238 it = prefs_map_.insert(
239 std::make_pair(pref_name, Preference(
240 this, pref_name, default_value->GetType()))).first;
241 return &(it->second);
242 }
243
244 bool PrefService::ReadOnly() const {
245 return user_pref_store_->ReadOnly();
246 }
247
248 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus()
249 const {
250 if (!user_pref_store_->IsInitializationComplete())
251 return INITIALIZATION_STATUS_WAITING;
252
253 switch (user_pref_store_->GetReadError()) {
254 case PersistentPrefStore::PREF_READ_ERROR_NONE:
255 return INITIALIZATION_STATUS_SUCCESS;
256 case PersistentPrefStore::PREF_READ_ERROR_NO_FILE:
257 return INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE;
258 default:
259 return INITIALIZATION_STATUS_ERROR;
260 }
261 }
262
263 bool PrefService::IsManagedPreference(const std::string& pref_name) const {
264 const Preference* pref = FindPreference(pref_name);
265 return pref && pref->IsManaged();
266 }
267
268 bool PrefService::IsPreferenceManagedByCustodian(
269 const std::string& pref_name) const {
270 const Preference* pref = FindPreference(pref_name);
271 return pref && pref->IsManagedByCustodian();
272 }
273
274 bool PrefService::IsUserModifiablePreference(
275 const std::string& pref_name) const {
276 const Preference* pref = FindPreference(pref_name);
277 return pref && pref->IsUserModifiable();
278 }
279
280 const base::DictionaryValue* PrefService::GetDictionary(
281 const std::string& path) const {
282 DCHECK(CalledOnValidThread());
283
284 const base::Value* value = GetPreferenceValue(path);
285 if (!value) {
286 NOTREACHED() << "Trying to read an unregistered pref: " << path;
287 return NULL;
288 }
289 if (value->GetType() != base::Value::TYPE_DICTIONARY) {
290 NOTREACHED();
291 return NULL;
292 }
293 return static_cast<const base::DictionaryValue*>(value);
294 }
295
296 const base::Value* PrefService::GetUserPrefValue(
297 const std::string& path) const {
298 DCHECK(CalledOnValidThread());
299
300 const Preference* pref = FindPreference(path);
301 if (!pref) {
302 NOTREACHED() << "Trying to get an unregistered pref: " << path;
303 return NULL;
304 }
305
306 // Look for an existing preference in the user store. If it doesn't
307 // exist, return NULL.
308 base::Value* value = NULL;
309 if (!user_pref_store_->GetMutableValue(path, &value))
310 return NULL;
311
312 if (!value->IsType(pref->GetType())) {
313 NOTREACHED() << "Pref value type doesn't match registered type.";
314 return NULL;
315 }
316
317 return value;
318 }
319
320 void PrefService::SetDefaultPrefValue(const std::string& path,
321 base::Value* value) {
322 DCHECK(CalledOnValidThread());
323 pref_registry_->SetDefaultPrefValue(path, value);
324 }
325
326 const base::Value* PrefService::GetDefaultPrefValue(
327 const std::string& path) const {
328 DCHECK(CalledOnValidThread());
329 // Lookup the preference in the default store.
330 const base::Value* value = NULL;
331 if (!pref_registry_->defaults()->GetValue(path, &value)) {
332 NOTREACHED() << "Default value missing for pref: " << path;
333 return NULL;
334 }
335 return value;
336 }
337
338 const base::ListValue* PrefService::GetList(const std::string& path) const {
339 DCHECK(CalledOnValidThread());
340
341 const base::Value* value = GetPreferenceValue(path);
342 if (!value) {
343 NOTREACHED() << "Trying to read an unregistered pref: " << path;
344 return NULL;
345 }
346 if (value->GetType() != base::Value::TYPE_LIST) {
347 NOTREACHED();
348 return NULL;
349 }
350 return static_cast<const base::ListValue*>(value);
351 }
352
353 void PrefService::AddPrefObserver(const std::string& path, PrefObserver* obs) {
354 pref_notifier_->AddPrefObserver(path, obs);
355 }
356
357 void PrefService::RemovePrefObserver(const std::string& path,
358 PrefObserver* obs) {
359 pref_notifier_->RemovePrefObserver(path, obs);
360 }
361
362 void PrefService::AddPrefInitObserver(base::Callback<void(bool)> obs) {
363 pref_notifier_->AddInitObserver(obs);
364 }
365
366 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() {
367 return pref_registry_.get();
368 }
369
370 void PrefService::ClearPref(const std::string& path) {
371 DCHECK(CalledOnValidThread());
372
373 const Preference* pref = FindPreference(path);
374 if (!pref) {
375 NOTREACHED() << "Trying to clear an unregistered pref: " << path;
376 return;
377 }
378 user_pref_store_->RemoveValue(path, GetWriteFlags(pref));
379 }
380
381 void PrefService::Set(const std::string& path, const base::Value& value) {
382 SetUserPrefValue(path, value.DeepCopy());
383 }
384
385 void PrefService::SetBoolean(const std::string& path, bool value) {
386 SetUserPrefValue(path, new base::FundamentalValue(value));
387 }
388
389 void PrefService::SetInteger(const std::string& path, int value) {
390 SetUserPrefValue(path, new base::FundamentalValue(value));
391 }
392
393 void PrefService::SetDouble(const std::string& path, double value) {
394 SetUserPrefValue(path, new base::FundamentalValue(value));
395 }
396
397 void PrefService::SetString(const std::string& path, const std::string& value) {
398 SetUserPrefValue(path, new base::StringValue(value));
399 }
400
401 void PrefService::SetFilePath(const std::string& path,
402 const base::FilePath& value) {
403 SetUserPrefValue(path, base::CreateFilePathValue(value));
404 }
405
406 void PrefService::SetInt64(const std::string& path, int64_t value) {
407 SetUserPrefValue(path, new base::StringValue(base::Int64ToString(value)));
408 }
409
410 int64_t PrefService::GetInt64(const std::string& path) const {
411 DCHECK(CalledOnValidThread());
412
413 const base::Value* value = GetPreferenceValue(path);
414 if (!value) {
415 NOTREACHED() << "Trying to read an unregistered pref: " << path;
416 return 0;
417 }
418 std::string result("0");
419 bool rv = value->GetAsString(&result);
420 DCHECK(rv);
421
422 int64_t val;
423 base::StringToInt64(result, &val);
424 return val;
425 }
426
427 void PrefService::SetUint64(const std::string& path, uint64_t value) {
428 SetUserPrefValue(path, new base::StringValue(base::Uint64ToString(value)));
429 }
430
431 uint64_t PrefService::GetUint64(const std::string& path) const {
432 DCHECK(CalledOnValidThread());
433
434 const base::Value* value = GetPreferenceValue(path);
435 if (!value) {
436 NOTREACHED() << "Trying to read an unregistered pref: " << path;
437 return 0;
438 }
439 std::string result("0");
440 bool rv = value->GetAsString(&result);
441 DCHECK(rv);
442
443 uint64_t val;
444 base::StringToUint64(result, &val);
445 return val;
446 }
447
448 base::Value* PrefService::GetMutableUserPref(const std::string& path,
449 base::Value::Type type) {
450 CHECK(type == base::Value::TYPE_DICTIONARY || type == base::Value::TYPE_LIST);
451 DCHECK(CalledOnValidThread());
452
453 const Preference* pref = FindPreference(path);
454 if (!pref) {
455 NOTREACHED() << "Trying to get an unregistered pref: " << path;
456 return NULL;
457 }
458 if (pref->GetType() != type) {
459 NOTREACHED() << "Wrong type for GetMutableValue: " << path;
460 return NULL;
461 }
462
463 // Look for an existing preference in the user store. If it doesn't
464 // exist or isn't the correct type, create a new user preference.
465 base::Value* value = NULL;
466 if (!user_pref_store_->GetMutableValue(path, &value) ||
467 !value->IsType(type)) {
468 if (type == base::Value::TYPE_DICTIONARY) {
469 value = new base::DictionaryValue;
470 } else if (type == base::Value::TYPE_LIST) {
471 value = new base::ListValue;
472 } else {
473 NOTREACHED();
474 }
475 user_pref_store_->SetValueSilently(path, make_scoped_ptr(value),
476 GetWriteFlags(pref));
477 }
478 return value;
479 }
480
481 void PrefService::ReportUserPrefChanged(const std::string& key) {
482 DCHECK(CalledOnValidThread());
483 user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
484 }
485
486 void PrefService::SetUserPrefValue(const std::string& path,
487 base::Value* new_value) {
488 scoped_ptr<base::Value> owned_value(new_value);
489 DCHECK(CalledOnValidThread());
490
491 const Preference* pref = FindPreference(path);
492 if (!pref) {
493 NOTREACHED() << "Trying to write an unregistered pref: " << path;
494 return;
495 }
496 if (pref->GetType() != new_value->GetType()) {
497 NOTREACHED() << "Trying to set pref " << path
498 << " of type " << pref->GetType()
499 << " to value of type " << new_value->GetType();
500 return;
501 }
502
503 user_pref_store_->SetValue(path, std::move(owned_value), GetWriteFlags(pref));
504 }
505
506 void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) {
507 pref_value_store_->UpdateCommandLinePrefStore(command_line_store);
508 }
509
510 ///////////////////////////////////////////////////////////////////////////////
511 // PrefService::Preference
512
513 PrefService::Preference::Preference(const PrefService* service,
514 const std::string& name,
515 base::Value::Type type)
516 : name_(name), type_(type), pref_service_(service) {
517 DCHECK(service);
518 // Cache the registration flags at creation time to avoid multiple map lookups
519 // later.
520 registration_flags_ = service->pref_registry_->GetRegistrationFlags(name_);
521 }
522
523 const std::string PrefService::Preference::name() const {
524 return name_;
525 }
526
527 base::Value::Type PrefService::Preference::GetType() const {
528 return type_;
529 }
530
531 const base::Value* PrefService::Preference::GetValue() const {
532 const base::Value* result= pref_service_->GetPreferenceValue(name_);
533 DCHECK(result) << "Must register pref before getting its value";
534 return result;
535 }
536
537 const base::Value* PrefService::Preference::GetRecommendedValue() const {
538 DCHECK(pref_service_->FindPreference(name_))
539 << "Must register pref before getting its value";
540
541 const base::Value* found_value = NULL;
542 if (pref_value_store()->GetRecommendedValue(name_, type_, &found_value)) {
543 DCHECK(found_value->IsType(type_));
544 return found_value;
545 }
546
547 // The pref has no recommended value.
548 return NULL;
549 }
550
551 bool PrefService::Preference::IsManaged() const {
552 return pref_value_store()->PrefValueInManagedStore(name_);
553 }
554
555 bool PrefService::Preference::IsManagedByCustodian() const {
556 return pref_value_store()->PrefValueInSupervisedStore(name_.c_str());
557 }
558
559 bool PrefService::Preference::IsRecommended() const {
560 return pref_value_store()->PrefValueFromRecommendedStore(name_);
561 }
562
563 bool PrefService::Preference::HasExtensionSetting() const {
564 return pref_value_store()->PrefValueInExtensionStore(name_);
565 }
566
567 bool PrefService::Preference::HasUserSetting() const {
568 return pref_value_store()->PrefValueInUserStore(name_);
569 }
570
571 bool PrefService::Preference::IsExtensionControlled() const {
572 return pref_value_store()->PrefValueFromExtensionStore(name_);
573 }
574
575 bool PrefService::Preference::IsUserControlled() const {
576 return pref_value_store()->PrefValueFromUserStore(name_);
577 }
578
579 bool PrefService::Preference::IsDefaultValue() const {
580 return pref_value_store()->PrefValueFromDefaultStore(name_);
581 }
582
583 bool PrefService::Preference::IsUserModifiable() const {
584 return pref_value_store()->PrefValueUserModifiable(name_);
585 }
586
587 bool PrefService::Preference::IsExtensionModifiable() const {
588 return pref_value_store()->PrefValueExtensionModifiable(name_);
589 }
590
591 const base::Value* PrefService::GetPreferenceValue(
592 const std::string& path) const {
593 DCHECK(CalledOnValidThread());
594
595 // TODO(battre): This is a check for crbug.com/435208. After analyzing some
596 // crash dumps it looks like the PrefService is accessed even though it has
597 // been cleared already.
598 CHECK(pref_registry_);
599 CHECK(pref_registry_->defaults());
600 CHECK(pref_value_store_);
601
602 const base::Value* default_value = NULL;
603 if (pref_registry_->defaults()->GetValue(path, &default_value)) {
604 const base::Value* found_value = NULL;
605 base::Value::Type default_type = default_value->GetType();
606 if (pref_value_store_->GetValue(path, default_type, &found_value)) {
607 DCHECK(found_value->IsType(default_type));
608 return found_value;
609 } else {
610 // Every registered preference has at least a default value.
611 NOTREACHED() << "no valid value found for registered pref " << path;
612 }
613 }
614
615 return NULL;
616 }
OLDNEW
« no previous file with comments | « base/prefs/pref_service.h ('k') | base/prefs/pref_service_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698