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