Upload upstream chromium 94.0.4606.31
[platform/framework/web/chromium-efl.git] / components / prefs / pref_service.cc
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 "components/prefs/pref_service.h"
6
7 #include <algorithm>
8 #include <map>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/check_op.h"
13 #include "base/debug/alias.h"
14 #include "base/debug/dump_without_crashing.h"
15 #include "base/files/file_path.h"
16 #include "base/json/values_util.h"
17 #include "base/location.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/metrics/histogram.h"
20 #include "base/notreached.h"
21 #include "base/single_thread_task_runner.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_util.h"
24 #include "base/threading/thread_task_runner_handle.h"
25 #include "base/values.h"
26 #include "build/build_config.h"
27 #include "components/prefs/default_pref_store.h"
28 #include "components/prefs/pref_notifier_impl.h"
29 #include "components/prefs/pref_registry.h"
30
31 #if defined(OS_ANDROID)
32 #include "components/prefs/android/pref_service_android.h"
33 #endif
34
35 namespace {
36
37 class ReadErrorHandler : public PersistentPrefStore::ReadErrorDelegate {
38  public:
39   using ErrorCallback =
40       base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>;
41   explicit ReadErrorHandler(ErrorCallback cb) : callback_(cb) {}
42
43   void OnError(PersistentPrefStore::PrefReadError error) override {
44     callback_.Run(error);
45   }
46
47  private:
48   ErrorCallback callback_;
49
50   DISALLOW_COPY_AND_ASSIGN(ReadErrorHandler);
51 };
52
53 // Returns the WriteablePrefStore::PrefWriteFlags for the pref with the given
54 // |path|.
55 uint32_t GetWriteFlags(const PrefService::Preference* pref) {
56   uint32_t write_flags = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
57
58   if (!pref)
59     return write_flags;
60
61   if (pref->registration_flags() & PrefRegistry::LOSSY_PREF)
62     write_flags |= WriteablePrefStore::LOSSY_PREF_WRITE_FLAG;
63   return write_flags;
64 }
65
66 // For prefs names in |pref_store| that are not presented in |pref_changed_map|,
67 // check if their values differ from those in pref_service->FindPreference() and
68 // add the result into |pref_changed_map|.
69 void CheckForNewPrefChangesInPrefStore(
70     std::map<std::string, bool>* pref_changed_map,
71     PrefStore* pref_store,
72     PrefService* pref_service) {
73   if (!pref_store)
74     return;
75   auto values = pref_store->GetValues();
76   for (auto item : values->DictItems()) {
77     // If the key already presents, skip it as a store with higher precedence
78     // already sets the entry.
79     if (pref_changed_map->find(item.first) != pref_changed_map->end())
80       continue;
81     const PrefService::Preference* pref =
82         pref_service->FindPreference(item.first);
83     if (!pref)
84       continue;
85     pref_changed_map->emplace(item.first, *(pref->GetValue()) != item.second);
86   }
87 }
88
89 }  // namespace
90
91 PrefService::PrefService(
92     std::unique_ptr<PrefNotifierImpl> pref_notifier,
93     std::unique_ptr<PrefValueStore> pref_value_store,
94     scoped_refptr<PersistentPrefStore> user_prefs,
95     scoped_refptr<PrefRegistry> pref_registry,
96     base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
97         read_error_callback,
98     bool async)
99     : pref_notifier_(std::move(pref_notifier)),
100       pref_value_store_(std::move(pref_value_store)),
101       user_pref_store_(std::move(user_prefs)),
102       read_error_callback_(std::move(read_error_callback)),
103       pref_registry_(std::move(pref_registry)) {
104   pref_notifier_->SetPrefService(this);
105
106   DCHECK(pref_registry_);
107   DCHECK(pref_value_store_);
108
109   InitFromStorage(async);
110 }
111
112 PrefService::~PrefService() {
113   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
114
115   // TODO(crbug.com/942491, 946668, 945772) The following code collects
116   // augments stack dumps created by ~PrefNotifierImpl() with information
117   // whether the profile owning the PrefService is an incognito profile.
118   // Delete this, once the bugs are closed.
119   const bool is_incognito_profile = user_pref_store_->IsInMemoryPrefStore();
120   base::debug::Alias(&is_incognito_profile);
121   // Export value of is_incognito_profile to a string so that `grep`
122   // is a sufficient tool to analyze crashdumps.
123   char is_incognito_profile_string[32];
124   strncpy(is_incognito_profile_string,
125           is_incognito_profile ? "is_incognito: yes" : "is_incognito: no",
126           sizeof(is_incognito_profile_string));
127   base::debug::Alias(&is_incognito_profile_string);
128 }
129
130 void PrefService::InitFromStorage(bool async) {
131   if (user_pref_store_->IsInitializationComplete()) {
132     read_error_callback_.Run(user_pref_store_->GetReadError());
133   } else if (!async) {
134     read_error_callback_.Run(user_pref_store_->ReadPrefs());
135   } else {
136     // Guarantee that initialization happens after this function returned.
137     base::ThreadTaskRunnerHandle::Get()->PostTask(
138         FROM_HERE,
139         base::BindOnce(&PersistentPrefStore::ReadPrefsAsync, user_pref_store_,
140                        new ReadErrorHandler(read_error_callback_)));
141   }
142 }
143
144 void PrefService::CommitPendingWrite(
145     base::OnceClosure reply_callback,
146     base::OnceClosure synchronous_done_callback) {
147   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
148   user_pref_store_->CommitPendingWrite(std::move(reply_callback),
149                                        std::move(synchronous_done_callback));
150 }
151
152 void PrefService::SchedulePendingLossyWrites() {
153   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
154   user_pref_store_->SchedulePendingLossyWrites();
155 }
156
157 bool PrefService::GetBoolean(const std::string& path) const {
158   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
159
160   const base::Value* value = GetPreferenceValueChecked(path);
161   if (!value || !value->is_bool())
162     return false;
163   return value->GetBool();
164 }
165
166 int PrefService::GetInteger(const std::string& path) const {
167   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
168
169   const base::Value* value = GetPreferenceValueChecked(path);
170   if (!value || !value->is_int())
171     return 0;
172   return value->GetInt();
173 }
174
175 double PrefService::GetDouble(const std::string& path) const {
176   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
177
178   const base::Value* value = GetPreferenceValueChecked(path);
179   if (!value || !value->is_double())
180     return 0.0;
181   return value->GetDouble();
182 }
183
184 std::string PrefService::GetString(const std::string& path) const {
185   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
186
187   const base::Value* value = GetPreferenceValueChecked(path);
188   if (!value || !value->is_string())
189     return std::string();
190   return value->GetString();
191 }
192
193 base::FilePath PrefService::GetFilePath(const std::string& path) const {
194   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
195
196   const base::Value* value = GetPreferenceValueChecked(path);
197   if (!value)
198     return base::FilePath();
199   absl::optional<base::FilePath> result = base::ValueToFilePath(*value);
200   DCHECK(result);
201   return *result;
202 }
203
204 bool PrefService::HasPrefPath(const std::string& path) const {
205   const Preference* pref = FindPreference(path);
206   return pref && !pref->IsDefaultValue();
207 }
208
209 void PrefService::IteratePreferenceValues(
210     base::RepeatingCallback<void(const std::string& key,
211                                  const base::Value& value)> callback) const {
212   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
213   for (const auto& it : *pref_registry_)
214     callback.Run(it.first, *GetPreferenceValue(it.first));
215 }
216
217 base::Value PrefService::GetPreferenceValues(
218     IncludeDefaults include_defaults) const {
219   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
220
221   base::Value out(base::Value::Type::DICTIONARY);
222   for (const auto& it : *pref_registry_) {
223     if (include_defaults == INCLUDE_DEFAULTS) {
224       out.SetPath(it.first, GetPreferenceValue(it.first)->Clone());
225     } else {
226       const Preference* pref = FindPreference(it.first);
227       if (pref->IsDefaultValue())
228         continue;
229       out.SetPath(it.first, pref->GetValue()->Clone());
230     }
231   }
232   return out;
233 }
234
235 const PrefService::Preference* PrefService::FindPreference(
236     const std::string& pref_name) const {
237   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
238   auto it = prefs_map_.find(pref_name);
239   if (it != prefs_map_.end())
240     return &(it->second);
241   const base::Value* default_value = nullptr;
242   if (!pref_registry_->defaults()->GetValue(pref_name, &default_value))
243     return nullptr;
244   it = prefs_map_
245            .insert(std::make_pair(
246                pref_name, Preference(this, pref_name, default_value->type())))
247            .first;
248   return &(it->second);
249 }
250
251 bool PrefService::ReadOnly() const {
252   return user_pref_store_->ReadOnly();
253 }
254
255 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus()
256     const {
257   if (!user_pref_store_->IsInitializationComplete())
258     return INITIALIZATION_STATUS_WAITING;
259
260   switch (user_pref_store_->GetReadError()) {
261     case PersistentPrefStore::PREF_READ_ERROR_NONE:
262       return INITIALIZATION_STATUS_SUCCESS;
263     case PersistentPrefStore::PREF_READ_ERROR_NO_FILE:
264       return INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE;
265     default:
266       return INITIALIZATION_STATUS_ERROR;
267   }
268 }
269
270 PrefService::PrefInitializationStatus
271 PrefService::GetAllPrefStoresInitializationStatus() const {
272   if (!pref_value_store_->IsInitializationComplete())
273     return INITIALIZATION_STATUS_WAITING;
274
275   return GetInitializationStatus();
276 }
277
278 bool PrefService::IsManagedPreference(const std::string& pref_name) const {
279   const Preference* pref = FindPreference(pref_name);
280   return pref && pref->IsManaged();
281 }
282
283 bool PrefService::IsPreferenceManagedByCustodian(
284     const std::string& pref_name) const {
285   const Preference* pref = FindPreference(pref_name);
286   return pref && pref->IsManagedByCustodian();
287 }
288
289 bool PrefService::IsUserModifiablePreference(
290     const std::string& pref_name) const {
291   const Preference* pref = FindPreference(pref_name);
292   return pref && pref->IsUserModifiable();
293 }
294
295 const base::Value* PrefService::Get(const std::string& path) const {
296   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
297   return GetPreferenceValueChecked(path);
298 }
299
300 const base::DictionaryValue* PrefService::GetDictionary(
301     const std::string& path) const {
302   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
303
304   const base::Value* value = GetPreferenceValueChecked(path);
305   if (!value)
306     return nullptr;
307   if (value->type() != base::Value::Type::DICTIONARY) {
308     NOTREACHED();
309     return nullptr;
310   }
311   return static_cast<const base::DictionaryValue*>(value);
312 }
313
314 const base::Value* PrefService::GetUserPrefValue(
315     const std::string& path) const {
316   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
317
318   const Preference* pref = FindPreference(path);
319   if (!pref) {
320     NOTREACHED() << "Trying to get an unregistered pref: " << path;
321     return nullptr;
322   }
323
324   // Look for an existing preference in the user store. If it doesn't
325   // exist, return NULL.
326   base::Value* value = nullptr;
327   if (!user_pref_store_->GetMutableValue(path, &value))
328     return nullptr;
329
330   if (value->type() != pref->GetType()) {
331     NOTREACHED() << "Pref value type doesn't match registered type.";
332     return nullptr;
333   }
334
335   return value;
336 }
337
338 void PrefService::SetDefaultPrefValue(const std::string& path,
339                                       base::Value value) {
340   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
341   pref_registry_->SetDefaultPrefValue(path, std::move(value));
342 }
343
344 const base::Value* PrefService::GetDefaultPrefValue(
345     const std::string& path) const {
346   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
347   // Lookup the preference in the default store.
348   const base::Value* value = nullptr;
349   bool has_value = pref_registry_->defaults()->GetValue(path, &value);
350   DCHECK(has_value) << "Default value missing for pref: " << path;
351   return value;
352 }
353
354 const base::ListValue* PrefService::GetList(const std::string& path) const {
355   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
356
357   const base::Value* value = GetPreferenceValueChecked(path);
358   if (!value)
359     return nullptr;
360   if (value->type() != base::Value::Type::LIST) {
361     NOTREACHED();
362     return nullptr;
363   }
364   return static_cast<const base::ListValue*>(value);
365 }
366
367 void PrefService::AddPrefObserver(const std::string& path, PrefObserver* obs) {
368   pref_notifier_->AddPrefObserver(path, obs);
369 }
370
371 void PrefService::RemovePrefObserver(const std::string& path,
372                                      PrefObserver* obs) {
373   pref_notifier_->RemovePrefObserver(path, obs);
374 }
375
376 void PrefService::AddPrefInitObserver(base::OnceCallback<void(bool)> obs) {
377   pref_notifier_->AddInitObserver(std::move(obs));
378 }
379
380 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() {
381   return pref_registry_.get();
382 }
383
384 void PrefService::ClearPref(const std::string& path) {
385   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
386
387   const Preference* pref = FindPreference(path);
388   if (!pref) {
389     NOTREACHED() << "Trying to clear an unregistered pref: " << path;
390     return;
391   }
392   user_pref_store_->RemoveValue(path, GetWriteFlags(pref));
393 }
394
395 void PrefService::ClearPrefsWithPrefixSilently(const std::string& prefix) {
396   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
397   user_pref_store_->RemoveValuesByPrefixSilently(prefix);
398 }
399
400 void PrefService::ClearMutableValues() {
401   user_pref_store_->ClearMutableValues();
402 }
403
404 void PrefService::OnStoreDeletionFromDisk() {
405   user_pref_store_->OnStoreDeletionFromDisk();
406 }
407
408 void PrefService::ChangePrefValueStore(
409     PrefStore* managed_prefs,
410     PrefStore* supervised_user_prefs,
411     PrefStore* extension_prefs,
412     PrefStore* recommended_prefs,
413     std::unique_ptr<PrefValueStore::Delegate> delegate) {
414   // Only adding new pref stores are supported.
415   DCHECK(!pref_value_store_->HasPrefStore(PrefValueStore::MANAGED_STORE) ||
416          !managed_prefs);
417   DCHECK(
418       !pref_value_store_->HasPrefStore(PrefValueStore::SUPERVISED_USER_STORE) ||
419       !supervised_user_prefs);
420   DCHECK(!pref_value_store_->HasPrefStore(PrefValueStore::EXTENSION_STORE) ||
421          !extension_prefs);
422   DCHECK(!pref_value_store_->HasPrefStore(PrefValueStore::RECOMMENDED_STORE) ||
423          !recommended_prefs);
424
425   // If some of the stores are already initialized, check for pref value changes
426   // according to store precedence.
427   std::map<std::string, bool> pref_changed_map;
428   CheckForNewPrefChangesInPrefStore(&pref_changed_map, managed_prefs, this);
429   CheckForNewPrefChangesInPrefStore(&pref_changed_map, supervised_user_prefs,
430                                     this);
431   CheckForNewPrefChangesInPrefStore(&pref_changed_map, extension_prefs, this);
432   CheckForNewPrefChangesInPrefStore(&pref_changed_map, recommended_prefs, this);
433
434   pref_value_store_ = pref_value_store_->CloneAndSpecialize(
435       managed_prefs, supervised_user_prefs, extension_prefs,
436       nullptr /* command_line_prefs */, nullptr /* user_prefs */,
437       recommended_prefs, nullptr /* default_prefs */, pref_notifier_.get(),
438       std::move(delegate));
439
440   // Notify |pref_notifier_| on all changed values.
441   for (const auto& kv : pref_changed_map) {
442     if (kv.second)
443       pref_notifier_.get()->OnPreferenceChanged(kv.first);
444   }
445 }
446
447 void PrefService::AddPrefObserverAllPrefs(PrefObserver* obs) {
448   pref_notifier_->AddPrefObserverAllPrefs(obs);
449 }
450
451 void PrefService::RemovePrefObserverAllPrefs(PrefObserver* obs) {
452   pref_notifier_->RemovePrefObserverAllPrefs(obs);
453 }
454
455 #if defined(OS_ANDROID)
456 base::android::ScopedJavaLocalRef<jobject> PrefService::GetJavaObject() {
457   if (!pref_service_android_) {
458     pref_service_android_ = std::make_unique<PrefServiceAndroid>(this);
459   }
460   return pref_service_android_->GetJavaObject();
461 }
462 #endif
463
464 void PrefService::Set(const std::string& path, const base::Value& value) {
465   SetUserPrefValue(path, value.Clone());
466 }
467
468 void PrefService::SetBoolean(const std::string& path, bool value) {
469   SetUserPrefValue(path, base::Value(value));
470 }
471
472 void PrefService::SetInteger(const std::string& path, int value) {
473   SetUserPrefValue(path, base::Value(value));
474 }
475
476 void PrefService::SetDouble(const std::string& path, double value) {
477   SetUserPrefValue(path, base::Value(value));
478 }
479
480 void PrefService::SetString(const std::string& path, const std::string& value) {
481   SetUserPrefValue(path, base::Value(value));
482 }
483
484 void PrefService::SetFilePath(const std::string& path,
485                               const base::FilePath& value) {
486   SetUserPrefValue(path, base::FilePathToValue(value));
487 }
488
489 void PrefService::SetInt64(const std::string& path, int64_t value) {
490   SetUserPrefValue(path, base::Int64ToValue(value));
491 }
492
493 int64_t PrefService::GetInt64(const std::string& path) const {
494   const base::Value* value = GetPreferenceValueChecked(path);
495   absl::optional<int64_t> integer = base::ValueToInt64(value);
496   DCHECK(integer);
497   return integer.value_or(0);
498 }
499
500 void PrefService::SetUint64(const std::string& path, uint64_t value) {
501   SetUserPrefValue(path, base::Value(base::NumberToString(value)));
502 }
503
504 uint64_t PrefService::GetUint64(const std::string& path) const {
505   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
506
507   const base::Value* value = GetPreferenceValueChecked(path);
508   if (!value || !value->is_string())
509     return 0;
510
511   uint64_t result;
512   base::StringToUint64(value->GetString(), &result);
513   return result;
514 }
515
516 void PrefService::SetTime(const std::string& path, base::Time value) {
517   SetUserPrefValue(path, base::TimeToValue(value));
518 }
519
520 base::Time PrefService::GetTime(const std::string& path) const {
521   const base::Value* value = GetPreferenceValueChecked(path);
522   absl::optional<base::Time> time = base::ValueToTime(value);
523   DCHECK(time);
524   return time.value_or(base::Time());
525 }
526
527 void PrefService::SetTimeDelta(const std::string& path, base::TimeDelta value) {
528   SetUserPrefValue(path, base::TimeDeltaToValue(value));
529 }
530
531 base::TimeDelta PrefService::GetTimeDelta(const std::string& path) const {
532   const base::Value* value = GetPreferenceValueChecked(path);
533   absl::optional<base::TimeDelta> time_delta = base::ValueToTimeDelta(value);
534   DCHECK(time_delta);
535   return time_delta.value_or(base::TimeDelta());
536 }
537
538 base::Value* PrefService::GetMutableUserPref(const std::string& path,
539                                              base::Value::Type type) {
540   CHECK(type == base::Value::Type::DICTIONARY ||
541         type == base::Value::Type::LIST);
542   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
543
544   const Preference* pref = FindPreference(path);
545   if (!pref) {
546     NOTREACHED() << "Trying to get an unregistered pref: " << path;
547     return nullptr;
548   }
549   if (pref->GetType() != type) {
550     NOTREACHED() << "Wrong type for GetMutableValue: " << path;
551     return nullptr;
552   }
553
554   // Look for an existing preference in the user store. Return it in case it
555   // exists and has the correct type.
556   base::Value* value = nullptr;
557   if (user_pref_store_->GetMutableValue(path, &value) &&
558       value->type() == type) {
559     return value;
560   }
561
562   // If no user preference of the correct type exists, clone default value.
563   const base::Value* default_value = nullptr;
564   pref_registry_->defaults()->GetValue(path, &default_value);
565   DCHECK_EQ(default_value->type(), type);
566   user_pref_store_->SetValueSilently(
567       path, base::Value::ToUniquePtrValue(default_value->Clone()),
568       GetWriteFlags(pref));
569   user_pref_store_->GetMutableValue(path, &value);
570   return value;
571 }
572
573 void PrefService::ReportUserPrefChanged(const std::string& key) {
574   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
575   user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
576 }
577
578 void PrefService::ReportUserPrefChanged(
579     const std::string& key,
580     std::set<std::vector<std::string>> path_components) {
581   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
582   user_pref_store_->ReportSubValuesChanged(key, std::move(path_components),
583                                            GetWriteFlags(FindPreference(key)));
584 }
585
586 void PrefService::SetUserPrefValue(const std::string& path,
587                                    base::Value new_value) {
588   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
589
590   const Preference* pref = FindPreference(path);
591   if (!pref) {
592     NOTREACHED() << "Trying to write an unregistered pref: " << path;
593     return;
594   }
595   if (pref->GetType() != new_value.type()) {
596     NOTREACHED() << "Trying to set pref " << path << " of type "
597                  << pref->GetType() << " to value of type " << new_value.type();
598     return;
599   }
600
601   user_pref_store_->SetValue(
602       path, base::Value::ToUniquePtrValue(std::move(new_value)),
603       GetWriteFlags(pref));
604 }
605
606 void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) {
607   pref_value_store_->UpdateCommandLinePrefStore(command_line_store);
608 }
609
610 ///////////////////////////////////////////////////////////////////////////////
611 // PrefService::Preference
612
613 PrefService::Preference::Preference(const PrefService* service,
614                                     std::string name,
615                                     base::Value::Type type)
616     : name_(std::move(name)),
617       type_(type),
618       // Cache the registration flags at creation time to avoid multiple map
619       // lookups later.
620       registration_flags_(service->pref_registry_->GetRegistrationFlags(name_)),
621       pref_service_(service) {}
622
623 const base::Value* PrefService::Preference::GetValue() const {
624   return pref_service_->GetPreferenceValueChecked(name_);
625 }
626
627 const base::Value* PrefService::Preference::GetRecommendedValue() const {
628   DCHECK(pref_service_->FindPreference(name_))
629       << "Must register pref before getting its value";
630
631   const base::Value* found_value = nullptr;
632   if (pref_value_store()->GetRecommendedValue(name_, type_, &found_value)) {
633     DCHECK(found_value->type() == type_);
634     return found_value;
635   }
636
637   // The pref has no recommended value.
638   return nullptr;
639 }
640
641 bool PrefService::Preference::IsManaged() const {
642   return pref_value_store()->PrefValueInManagedStore(name_);
643 }
644
645 bool PrefService::Preference::IsManagedByCustodian() const {
646   return pref_value_store()->PrefValueInSupervisedStore(name_);
647 }
648
649 bool PrefService::Preference::IsRecommended() const {
650   return pref_value_store()->PrefValueFromRecommendedStore(name_);
651 }
652
653 bool PrefService::Preference::HasExtensionSetting() const {
654   return pref_value_store()->PrefValueInExtensionStore(name_);
655 }
656
657 bool PrefService::Preference::HasUserSetting() const {
658   return pref_value_store()->PrefValueInUserStore(name_);
659 }
660
661 bool PrefService::Preference::IsExtensionControlled() const {
662   return pref_value_store()->PrefValueFromExtensionStore(name_);
663 }
664
665 bool PrefService::Preference::IsUserControlled() const {
666   return pref_value_store()->PrefValueFromUserStore(name_);
667 }
668
669 bool PrefService::Preference::IsDefaultValue() const {
670   return pref_value_store()->PrefValueFromDefaultStore(name_);
671 }
672
673 bool PrefService::Preference::IsUserModifiable() const {
674   return pref_value_store()->PrefValueUserModifiable(name_);
675 }
676
677 bool PrefService::Preference::IsExtensionModifiable() const {
678   return pref_value_store()->PrefValueExtensionModifiable(name_);
679 }
680
681 const base::Value* PrefService::GetPreferenceValue(
682     const std::string& path) const {
683   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
684
685   // TODO(battre): This is a check for crbug.com/435208. After analyzing some
686   // crash dumps it looks like the PrefService is accessed even though it has
687   // been cleared already.
688   CHECK(pref_registry_);
689   CHECK(pref_registry_->defaults());
690   CHECK(pref_value_store_);
691
692   const base::Value* default_value = nullptr;
693   if (!pref_registry_->defaults()->GetValue(path, &default_value))
694     return nullptr;
695
696   const base::Value* found_value = nullptr;
697   base::Value::Type default_type = default_value->type();
698   if (!pref_value_store_->GetValue(path, default_type, &found_value)) {
699     // Every registered preference has at least a default value.
700     NOTREACHED() << "no valid value found for registered pref " << path;
701     return nullptr;
702   }
703
704   DCHECK_EQ(found_value->type(), default_type);
705   return found_value;
706 }
707
708 const base::Value* PrefService::GetPreferenceValueChecked(
709     const std::string& path) const {
710   const base::Value* value = GetPreferenceValue(path);
711   DCHECK(value) << "Trying to read an unregistered pref: " << path;
712   return value;
713 }
714
715 void PrefService::CommitPendingWriteSynchronously() {
716   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
717   user_pref_store_->CommitPendingWriteSynchronously();
718 }