• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 <string>
10 #include <utility>
11 
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/functional/bind.h"
17 #include "base/json/values_util.h"
18 #include "base/location.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/metrics/histogram.h"
21 #include "base/notreached.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_piece.h"
24 #include "base/strings/string_util.h"
25 #include "base/task/sequenced_task_runner.h"
26 #include "base/values.h"
27 #include "build/chromeos_buildflags.h"
28 #include "components/prefs/default_pref_store.h"
29 #include "components/prefs/json_pref_store.h"
30 #include "components/prefs/pref_notifier_impl.h"
31 #include "components/prefs/pref_registry.h"
32 
33 #if BUILDFLAG(IS_CHROMEOS_ASH)
34 #include "components/prefs/value_map_pref_store.h"
35 #endif
36 
37 #if BUILDFLAG(IS_ANDROID)
38 #include "components/prefs/android/pref_service_android.h"
39 #endif
40 
41 namespace {
42 
43 
44 }  // namespace
45 
46 PrefService::PersistentPrefStoreLoadingObserver::
PersistentPrefStoreLoadingObserver(PrefService * pref_service)47     PersistentPrefStoreLoadingObserver(PrefService* pref_service)
48     : pref_service_(pref_service) {
49   DCHECK(pref_service_);
50 }
51 
OnInitializationCompleted(bool succeeded)52 void PrefService::PersistentPrefStoreLoadingObserver::OnInitializationCompleted(
53     bool succeeded) {
54   pref_service_->CheckPrefsLoaded();
55 }
56 
PrefService(std::unique_ptr<PrefNotifierImpl> pref_notifier,std::unique_ptr<PrefValueStore> pref_value_store,scoped_refptr<PersistentPrefStore> user_prefs,scoped_refptr<PersistentPrefStore> standalone_browser_prefs,scoped_refptr<PrefRegistry> pref_registry,base::RepeatingCallback<void (PersistentPrefStore::PrefReadError)> read_error_callback,bool async)57 PrefService::PrefService(
58     std::unique_ptr<PrefNotifierImpl> pref_notifier,
59     std::unique_ptr<PrefValueStore> pref_value_store,
60     scoped_refptr<PersistentPrefStore> user_prefs,
61     scoped_refptr<PersistentPrefStore> standalone_browser_prefs,
62     scoped_refptr<PrefRegistry> pref_registry,
63     base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
64         read_error_callback,
65     bool async)
66     : pref_notifier_(std::move(pref_notifier)),
67       pref_value_store_(std::move(pref_value_store)),
68       user_pref_store_(std::move(user_prefs)),
69       standalone_browser_pref_store_(std::move(standalone_browser_prefs)),
70       read_error_callback_(std::move(read_error_callback)),
71       pref_registry_(std::move(pref_registry)),
72       pref_store_observer_(
73           std::make_unique<PrefService::PersistentPrefStoreLoadingObserver>(
74               this)) {
75   pref_notifier_->SetPrefService(this);
76 
77   DCHECK(pref_registry_);
78   DCHECK(pref_value_store_);
79 
80   InitFromStorage(async);
81 }
82 
~PrefService()83 PrefService::~PrefService() {
84   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
85 
86   // Remove observers. This could be necessary if this service is destroyed
87   // before the prefs are fully loaded.
88   user_pref_store_->RemoveObserver(pref_store_observer_.get());
89   if (standalone_browser_pref_store_) {
90     standalone_browser_pref_store_->RemoveObserver(pref_store_observer_.get());
91   }
92 
93   // TODO(crbug.com/942491, 946668, 945772) The following code collects
94   // augments stack dumps created by ~PrefNotifierImpl() with information
95   // whether the profile owning the PrefService is an incognito profile.
96   // Delete this, once the bugs are closed.
97   const bool is_incognito_profile = user_pref_store_->IsInMemoryPrefStore();
98   base::debug::Alias(&is_incognito_profile);
99   // Export value of is_incognito_profile to a string so that `grep`
100   // is a sufficient tool to analyze crashdumps.
101   char is_incognito_profile_string[32];
102   strncpy(is_incognito_profile_string,
103           is_incognito_profile ? "is_incognito: yes" : "is_incognito: no",
104           sizeof(is_incognito_profile_string));
105   base::debug::Alias(&is_incognito_profile_string);
106 }
107 
InitFromStorage(bool async)108 void PrefService::InitFromStorage(bool async) {
109   if (!async) {
110     if (!user_pref_store_->IsInitializationComplete()) {
111       user_pref_store_->ReadPrefs();
112     }
113     if (standalone_browser_pref_store_ &&
114         !standalone_browser_pref_store_->IsInitializationComplete()) {
115       standalone_browser_pref_store_->ReadPrefs();
116     }
117     CheckPrefsLoaded();
118     return;
119   }
120 
121   CheckPrefsLoaded();
122 
123   if (!user_pref_store_->IsInitializationComplete()) {
124     user_pref_store_->AddObserver(pref_store_observer_.get());
125     user_pref_store_->ReadPrefsAsync(nullptr);
126   }
127 
128   if (standalone_browser_pref_store_ &&
129       !standalone_browser_pref_store_->IsInitializationComplete()) {
130     standalone_browser_pref_store_->AddObserver(pref_store_observer_.get());
131     standalone_browser_pref_store_->ReadPrefsAsync(nullptr);
132   }
133 }
134 
CheckPrefsLoaded()135 void PrefService::CheckPrefsLoaded() {
136   if (!(user_pref_store_->IsInitializationComplete() &&
137         (!standalone_browser_pref_store_ ||
138          standalone_browser_pref_store_->IsInitializationComplete()))) {
139     // Not done initializing both prefstores.
140     return;
141   }
142 
143   user_pref_store_->RemoveObserver(pref_store_observer_.get());
144   if (standalone_browser_pref_store_) {
145     standalone_browser_pref_store_->RemoveObserver(pref_store_observer_.get());
146   }
147 
148   // Both prefstores are initialized, get the read errors.
149   PersistentPrefStore::PrefReadError user_store_error =
150       user_pref_store_->GetReadError();
151   if (!standalone_browser_pref_store_) {
152     read_error_callback_.Run(user_store_error);
153     return;
154   }
155   PersistentPrefStore::PrefReadError standalone_browser_store_error =
156       standalone_browser_pref_store_->GetReadError();
157 
158   // If both stores have the same error (or no error), run the callback with
159   // either one. This avoids double-reporting (either way prefs weren't
160   // successfully fully loaded)
161   if (user_store_error == standalone_browser_store_error) {
162     read_error_callback_.Run(user_store_error);
163   } else if (user_store_error == PersistentPrefStore::PREF_READ_ERROR_NONE ||
164              user_store_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
165     // Prefer to report the standalone_browser_pref_store error if the
166     // user_pref_store error is not significant.
167     read_error_callback_.Run(standalone_browser_store_error);
168   } else {
169     // Either the user_pref_store error is significant, or
170     // both stores failed to load but for different reasons.
171     // The user_store error is more significant in essentially all cases,
172     // so prefer to report that.
173     read_error_callback_.Run(user_store_error);
174   }
175 }
176 
CommitPendingWrite(base::OnceClosure reply_callback,base::OnceClosure synchronous_done_callback)177 void PrefService::CommitPendingWrite(
178     base::OnceClosure reply_callback,
179     base::OnceClosure synchronous_done_callback) {
180   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
181   user_pref_store_->CommitPendingWrite(std::move(reply_callback),
182                                        std::move(synchronous_done_callback));
183 }
184 
SchedulePendingLossyWrites()185 void PrefService::SchedulePendingLossyWrites() {
186   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
187   user_pref_store_->SchedulePendingLossyWrites();
188 }
189 
GetBoolean(base::StringPiece path) const190 bool PrefService::GetBoolean(base::StringPiece path) const {
191   return GetValue(path).GetBool();
192 }
193 
GetInteger(base::StringPiece path) const194 int PrefService::GetInteger(base::StringPiece path) const {
195   return GetValue(path).GetInt();
196 }
197 
GetDouble(base::StringPiece path) const198 double PrefService::GetDouble(base::StringPiece path) const {
199   return GetValue(path).GetDouble();
200 }
201 
GetString(base::StringPiece path) const202 const std::string& PrefService::GetString(base::StringPiece path) const {
203   return GetValue(path).GetString();
204 }
205 
GetFilePath(base::StringPiece path) const206 base::FilePath PrefService::GetFilePath(base::StringPiece path) const {
207   const base::Value& value = GetValue(path);
208   absl::optional<base::FilePath> result = base::ValueToFilePath(value);
209   DCHECK(result);
210   return *result;
211 }
212 
HasPrefPath(const std::string & path) const213 bool PrefService::HasPrefPath(const std::string& path) const {
214   const Preference* pref = FindPreference(path);
215   return pref && !pref->IsDefaultValue();
216 }
217 
IteratePreferenceValues(base::RepeatingCallback<void (const std::string & key,const base::Value & value)> callback) const218 void PrefService::IteratePreferenceValues(
219     base::RepeatingCallback<void(const std::string& key,
220                                  const base::Value& value)> callback) const {
221   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
222   for (const auto& it : *pref_registry_)
223     callback.Run(it.first, *GetPreferenceValue(it.first));
224 }
225 
GetPreferenceValues(IncludeDefaults include_defaults) const226 base::Value::Dict PrefService::GetPreferenceValues(
227     IncludeDefaults include_defaults) const {
228   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
229 
230   base::Value::Dict out;
231   for (const auto& it : *pref_registry_) {
232     if (include_defaults == INCLUDE_DEFAULTS) {
233       out.SetByDottedPath(it.first, GetPreferenceValue(it.first)->Clone());
234     } else {
235       const Preference* pref = FindPreference(it.first);
236       if (pref->IsDefaultValue()) {
237         continue;
238       }
239       out.SetByDottedPath(it.first, pref->GetValue()->Clone());
240     }
241   }
242   return out;
243 }
244 
FindPreference(const std::string & pref_name) const245 const PrefService::Preference* PrefService::FindPreference(
246     const std::string& pref_name) const {
247   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
248   auto it = prefs_map_.find(pref_name);
249   if (it != prefs_map_.end())
250     return &(it->second);
251   const base::Value* default_value = nullptr;
252   if (!pref_registry_->defaults()->GetValue(pref_name, &default_value))
253     return nullptr;
254   it = prefs_map_
255            .insert(std::make_pair(
256                pref_name, Preference(this, pref_name, default_value->type())))
257            .first;
258   return &(it->second);
259 }
260 
ReadOnly() const261 bool PrefService::ReadOnly() const {
262   return user_pref_store_->ReadOnly();
263 }
264 
GetInitializationStatus() const265 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus()
266     const {
267   if (!user_pref_store_->IsInitializationComplete())
268     return INITIALIZATION_STATUS_WAITING;
269 
270   switch (user_pref_store_->GetReadError()) {
271     case PersistentPrefStore::PREF_READ_ERROR_NONE:
272       return INITIALIZATION_STATUS_SUCCESS;
273     case PersistentPrefStore::PREF_READ_ERROR_NO_FILE:
274       return INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE;
275     default:
276       return INITIALIZATION_STATUS_ERROR;
277   }
278 }
279 
280 PrefService::PrefInitializationStatus
GetAllPrefStoresInitializationStatus() const281 PrefService::GetAllPrefStoresInitializationStatus() const {
282   if (!pref_value_store_->IsInitializationComplete())
283     return INITIALIZATION_STATUS_WAITING;
284 
285   return GetInitializationStatus();
286 }
287 
IsManagedPreference(const std::string & pref_name) const288 bool PrefService::IsManagedPreference(const std::string& pref_name) const {
289   const Preference* pref = FindPreference(pref_name);
290   return pref && pref->IsManaged();
291 }
292 
IsPreferenceManagedByCustodian(const std::string & pref_name) const293 bool PrefService::IsPreferenceManagedByCustodian(
294     const std::string& pref_name) const {
295   const Preference* pref = FindPreference(pref_name);
296   return pref && pref->IsManagedByCustodian();
297 }
298 
IsUserModifiablePreference(const std::string & pref_name) const299 bool PrefService::IsUserModifiablePreference(
300     const std::string& pref_name) const {
301   const Preference* pref = FindPreference(pref_name);
302   return pref && pref->IsUserModifiable();
303 }
304 
GetValue(base::StringPiece path) const305 const base::Value& PrefService::GetValue(base::StringPiece path) const {
306   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
307   return *GetPreferenceValueChecked(path);
308 }
309 
GetDict(base::StringPiece path) const310 const base::Value::Dict& PrefService::GetDict(base::StringPiece path) const {
311   const base::Value& value = GetValue(path);
312   return value.GetDict();
313 }
314 
GetList(base::StringPiece path) const315 const base::Value::List& PrefService::GetList(base::StringPiece path) const {
316   const base::Value& value = GetValue(path);
317   return value.GetList();
318 }
319 
GetUserPrefValue(const std::string & path) const320 const base::Value* PrefService::GetUserPrefValue(
321     const std::string& path) const {
322   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
323 
324   const Preference* pref = FindPreference(path);
325   if (!pref) {
326     NOTREACHED() << "Trying to get an unregistered pref: " << path;
327     return nullptr;
328   }
329 
330   // Look for an existing preference in the user store. If it doesn't
331   // exist, return NULL.
332   base::Value* value = nullptr;
333   if (!user_pref_store_->GetMutableValue(path, &value))
334     return nullptr;
335 
336   if (value->type() != pref->GetType()) {
337     NOTREACHED() << "Pref value type doesn't match registered type.";
338     return nullptr;
339   }
340 
341   return value;
342 }
343 
SetDefaultPrefValue(const std::string & path,base::Value value)344 void PrefService::SetDefaultPrefValue(const std::string& path,
345                                       base::Value value) {
346   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
347   pref_registry_->SetDefaultPrefValue(path, std::move(value));
348 }
349 
GetDefaultPrefValue(const std::string & path) const350 const base::Value* PrefService::GetDefaultPrefValue(
351     const std::string& path) const {
352   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
353   // Lookup the preference in the default store.
354   const base::Value* value = nullptr;
355   bool has_value = pref_registry_->defaults()->GetValue(path, &value);
356   DCHECK(has_value) << "Default value missing for pref: " << path;
357   return value;
358 }
359 
AddPrefObserver(const std::string & path,PrefObserver * obs)360 void PrefService::AddPrefObserver(const std::string& path, PrefObserver* obs) {
361   pref_notifier_->AddPrefObserver(path, obs);
362 }
363 
RemovePrefObserver(const std::string & path,PrefObserver * obs)364 void PrefService::RemovePrefObserver(const std::string& path,
365                                      PrefObserver* obs) {
366   pref_notifier_->RemovePrefObserver(path, obs);
367 }
368 
AddPrefInitObserver(base::OnceCallback<void (bool)> obs)369 void PrefService::AddPrefInitObserver(base::OnceCallback<void(bool)> obs) {
370   pref_notifier_->AddInitObserver(std::move(obs));
371 }
372 
DeprecatedGetPrefRegistry()373 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() {
374   return pref_registry_.get();
375 }
376 
ClearPref(const std::string & path)377 void PrefService::ClearPref(const std::string& path) {
378   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
379 
380   const Preference* pref = FindPreference(path);
381   if (!pref) {
382     NOTREACHED() << "Trying to clear an unregistered pref: " << path;
383     return;
384   }
385   user_pref_store_->RemoveValue(path, GetWriteFlags(pref));
386 }
387 
ClearPrefsWithPrefixSilently(const std::string & prefix)388 void PrefService::ClearPrefsWithPrefixSilently(const std::string& prefix) {
389   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
390   user_pref_store_->RemoveValuesByPrefixSilently(prefix);
391 }
392 
OnStoreDeletionFromDisk()393 void PrefService::OnStoreDeletionFromDisk() {
394   user_pref_store_->OnStoreDeletionFromDisk();
395 }
396 
AddPrefObserverAllPrefs(PrefObserver * obs)397 void PrefService::AddPrefObserverAllPrefs(PrefObserver* obs) {
398   pref_notifier_->AddPrefObserverAllPrefs(obs);
399 }
400 
RemovePrefObserverAllPrefs(PrefObserver * obs)401 void PrefService::RemovePrefObserverAllPrefs(PrefObserver* obs) {
402   pref_notifier_->RemovePrefObserverAllPrefs(obs);
403 }
404 
405 #if BUILDFLAG(IS_ANDROID)
GetJavaObject()406 base::android::ScopedJavaLocalRef<jobject> PrefService::GetJavaObject() {
407   if (!pref_service_android_) {
408     pref_service_android_ = std::make_unique<PrefServiceAndroid>(this);
409   }
410   return pref_service_android_->GetJavaObject();
411 }
412 #endif
413 
Set(const std::string & path,const base::Value & value)414 void PrefService::Set(const std::string& path, const base::Value& value) {
415   SetUserPrefValue(path, value.Clone());
416 }
417 
SetBoolean(const std::string & path,bool value)418 void PrefService::SetBoolean(const std::string& path, bool value) {
419   SetUserPrefValue(path, base::Value(value));
420 }
421 
SetInteger(const std::string & path,int value)422 void PrefService::SetInteger(const std::string& path, int value) {
423   SetUserPrefValue(path, base::Value(value));
424 }
425 
SetDouble(const std::string & path,double value)426 void PrefService::SetDouble(const std::string& path, double value) {
427   SetUserPrefValue(path, base::Value(value));
428 }
429 
SetString(const std::string & path,const std::string & value)430 void PrefService::SetString(const std::string& path, const std::string& value) {
431   SetUserPrefValue(path, base::Value(value));
432 }
433 
SetDict(const std::string & path,base::Value::Dict dict)434 void PrefService::SetDict(const std::string& path, base::Value::Dict dict) {
435   SetUserPrefValue(path, base::Value(std::move(dict)));
436 }
437 
SetList(const std::string & path,base::Value::List list)438 void PrefService::SetList(const std::string& path, base::Value::List list) {
439   SetUserPrefValue(path, base::Value(std::move(list)));
440 }
441 
SetFilePath(const std::string & path,const base::FilePath & value)442 void PrefService::SetFilePath(const std::string& path,
443                               const base::FilePath& value) {
444   SetUserPrefValue(path, base::FilePathToValue(value));
445 }
446 
SetInt64(const std::string & path,int64_t value)447 void PrefService::SetInt64(const std::string& path, int64_t value) {
448   SetUserPrefValue(path, base::Int64ToValue(value));
449 }
450 
GetInt64(const std::string & path) const451 int64_t PrefService::GetInt64(const std::string& path) const {
452   const base::Value& value = GetValue(path);
453   absl::optional<int64_t> integer = base::ValueToInt64(value);
454   DCHECK(integer);
455   return integer.value_or(0);
456 }
457 
SetUint64(const std::string & path,uint64_t value)458 void PrefService::SetUint64(const std::string& path, uint64_t value) {
459   SetUserPrefValue(path, base::Value(base::NumberToString(value)));
460 }
461 
GetUint64(const std::string & path) const462 uint64_t PrefService::GetUint64(const std::string& path) const {
463   const base::Value& value = GetValue(path);
464   if (!value.is_string())
465     return 0;
466 
467   uint64_t result;
468   base::StringToUint64(value.GetString(), &result);
469   return result;
470 }
471 
SetTime(const std::string & path,base::Time value)472 void PrefService::SetTime(const std::string& path, base::Time value) {
473   SetUserPrefValue(path, base::TimeToValue(value));
474 }
475 
GetTime(const std::string & path) const476 base::Time PrefService::GetTime(const std::string& path) const {
477   const base::Value& value = GetValue(path);
478   absl::optional<base::Time> time = base::ValueToTime(value);
479   DCHECK(time);
480   return time.value_or(base::Time());
481 }
482 
SetTimeDelta(const std::string & path,base::TimeDelta value)483 void PrefService::SetTimeDelta(const std::string& path, base::TimeDelta value) {
484   SetUserPrefValue(path, base::TimeDeltaToValue(value));
485 }
486 
GetTimeDelta(const std::string & path) const487 base::TimeDelta PrefService::GetTimeDelta(const std::string& path) const {
488   const base::Value& value = GetValue(path);
489   absl::optional<base::TimeDelta> time_delta = base::ValueToTimeDelta(value);
490   DCHECK(time_delta);
491   return time_delta.value_or(base::TimeDelta());
492 }
493 
GetMutableUserPref(const std::string & path,base::Value::Type type)494 base::Value* PrefService::GetMutableUserPref(const std::string& path,
495                                              base::Value::Type type) {
496   CHECK(type == base::Value::Type::DICT || type == base::Value::Type::LIST);
497   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
498 
499   const Preference* pref = FindPreference(path);
500   if (!pref) {
501     NOTREACHED() << "Trying to get an unregistered pref: " << path;
502     return nullptr;
503   }
504   if (pref->GetType() != type) {
505     NOTREACHED() << "Wrong type for GetMutableValue: " << path;
506     return nullptr;
507   }
508 
509   // Look for an existing preference in the user store. Return it in case it
510   // exists and has the correct type.
511   base::Value* value = nullptr;
512   if (user_pref_store_->GetMutableValue(path, &value) &&
513       value->type() == type) {
514     return value;
515   }
516 
517   // If no user preference of the correct type exists, clone default value.
518   const base::Value* default_value = nullptr;
519   pref_registry_->defaults()->GetValue(path, &default_value);
520   DCHECK_EQ(default_value->type(), type);
521   user_pref_store_->SetValueSilently(path, default_value->Clone(),
522                                      GetWriteFlags(pref));
523   user_pref_store_->GetMutableValue(path, &value);
524   return value;
525 }
526 
ReportUserPrefChanged(const std::string & key)527 void PrefService::ReportUserPrefChanged(const std::string& key) {
528   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
529   user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
530 }
531 
ReportUserPrefChanged(const std::string & key,std::set<std::vector<std::string>> path_components)532 void PrefService::ReportUserPrefChanged(
533     const std::string& key,
534     std::set<std::vector<std::string>> path_components) {
535   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
536   user_pref_store_->ReportSubValuesChanged(key, std::move(path_components),
537                                            GetWriteFlags(FindPreference(key)));
538 }
539 
SetUserPrefValue(const std::string & path,base::Value new_value)540 void PrefService::SetUserPrefValue(const std::string& path,
541                                    base::Value new_value) {
542   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
543 
544   const Preference* pref = FindPreference(path);
545   if (!pref) {
546     NOTREACHED() << "Trying to write an unregistered pref: " << path;
547     return;
548   }
549   if (pref->GetType() != new_value.type()) {
550     NOTREACHED() << "Trying to set pref " << path << " of type "
551                  << pref->GetType() << " to value of type " << new_value.type();
552     return;
553   }
554 
555   user_pref_store_->SetValue(path, std::move(new_value), GetWriteFlags(pref));
556 }
557 
UpdateCommandLinePrefStore(PrefStore * command_line_store)558 void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) {
559   pref_value_store_->UpdateCommandLinePrefStore(command_line_store);
560 }
561 
562 ///////////////////////////////////////////////////////////////////////////////
563 // PrefService::Preference
564 
Preference(const PrefService * service,std::string name,base::Value::Type type)565 PrefService::Preference::Preference(const PrefService* service,
566                                     std::string name,
567                                     base::Value::Type type)
568     : name_(std::move(name)),
569       type_(type),
570       // Cache the registration flags at creation time to avoid multiple map
571       // lookups later.
572       registration_flags_(service->pref_registry_->GetRegistrationFlags(name_)),
573       pref_service_(service) {}
574 
GetValue() const575 const base::Value* PrefService::Preference::GetValue() const {
576   return pref_service_->GetPreferenceValueChecked(name_);
577 }
578 
GetRecommendedValue() const579 const base::Value* PrefService::Preference::GetRecommendedValue() const {
580   DCHECK(pref_service_->FindPreference(name_))
581       << "Must register pref before getting its value";
582 
583   const base::Value* found_value = nullptr;
584   if (pref_value_store()->GetRecommendedValue(name_, type_, &found_value)) {
585     DCHECK(found_value->type() == type_);
586     return found_value;
587   }
588 
589   // The pref has no recommended value.
590   return nullptr;
591 }
592 
IsManaged() const593 bool PrefService::Preference::IsManaged() const {
594   return pref_value_store()->PrefValueInManagedStore(name_);
595 }
596 
IsManagedByCustodian() const597 bool PrefService::Preference::IsManagedByCustodian() const {
598   return pref_value_store()->PrefValueInSupervisedStore(name_);
599 }
600 
IsRecommended() const601 bool PrefService::Preference::IsRecommended() const {
602   return pref_value_store()->PrefValueFromRecommendedStore(name_);
603 }
604 
HasExtensionSetting() const605 bool PrefService::Preference::HasExtensionSetting() const {
606   return pref_value_store()->PrefValueInExtensionStore(name_);
607 }
608 
HasUserSetting() const609 bool PrefService::Preference::HasUserSetting() const {
610   return pref_value_store()->PrefValueInUserStore(name_);
611 }
612 
IsExtensionControlled() const613 bool PrefService::Preference::IsExtensionControlled() const {
614   return pref_value_store()->PrefValueFromExtensionStore(name_);
615 }
616 
IsUserControlled() const617 bool PrefService::Preference::IsUserControlled() const {
618   return pref_value_store()->PrefValueFromUserStore(name_);
619 }
620 
IsDefaultValue() const621 bool PrefService::Preference::IsDefaultValue() const {
622   return pref_value_store()->PrefValueFromDefaultStore(name_);
623 }
624 
IsUserModifiable() const625 bool PrefService::Preference::IsUserModifiable() const {
626   return pref_value_store()->PrefValueUserModifiable(name_);
627 }
628 
IsExtensionModifiable() const629 bool PrefService::Preference::IsExtensionModifiable() const {
630   return pref_value_store()->PrefValueExtensionModifiable(name_);
631 }
632 
633 #if BUILDFLAG(IS_CHROMEOS_ASH)
IsStandaloneBrowserControlled() const634 bool PrefService::Preference::IsStandaloneBrowserControlled() const {
635   return pref_value_store()->PrefValueFromStandaloneBrowserStore(name_);
636 }
637 
IsStandaloneBrowserModifiable() const638 bool PrefService::Preference::IsStandaloneBrowserModifiable() const {
639   return pref_value_store()->PrefValueStandaloneBrowserModifiable(name_);
640 }
641 #endif
642 
GetPreferenceValue(base::StringPiece path) const643 const base::Value* PrefService::GetPreferenceValue(
644     base::StringPiece path) const {
645   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
646 
647   // TODO(battre): This is a check for crbug.com/435208. After analyzing some
648   // crash dumps it looks like the PrefService is accessed even though it has
649   // been cleared already.
650   CHECK(pref_registry_);
651   CHECK(pref_registry_->defaults());
652   CHECK(pref_value_store_);
653 
654   const base::Value* default_value = nullptr;
655   if (!pref_registry_->defaults()->GetValue(path, &default_value))
656     return nullptr;
657 
658   const base::Value* found_value = nullptr;
659   base::Value::Type default_type = default_value->type();
660   if (!pref_value_store_->GetValue(path, default_type, &found_value)) {
661     // Every registered preference has at least a default value.
662     NOTREACHED() << "no valid value found for registered pref " << path;
663     return default_value;
664   }
665 
666   DCHECK_EQ(found_value->type(), default_type);
667   return found_value;
668 }
669 
GetPreferenceValueChecked(base::StringPiece path) const670 const base::Value* PrefService::GetPreferenceValueChecked(
671     base::StringPiece path) const {
672   const base::Value* value = GetPreferenceValue(path);
673   DCHECK(value) << "Trying to read an unregistered pref: " << path;
674   return value;
675 }
676 
677 #if BUILDFLAG(IS_CHROMEOS_ASH)
SetStandaloneBrowserPref(const std::string & path,const base::Value & value)678 void PrefService::SetStandaloneBrowserPref(const std::string& path,
679                                            const base::Value& value) {
680   standalone_browser_pref_store_->SetValue(
681       path, value.Clone(), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
682 }
683 
RemoveStandaloneBrowserPref(const std::string & path)684 void PrefService::RemoveStandaloneBrowserPref(const std::string& path) {
685   standalone_browser_pref_store_->RemoveValue(
686       path, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
687 }
688 #endif
689 
690 // static
GetWriteFlags(const PrefService::Preference * pref)691 uint32_t PrefService::GetWriteFlags(const PrefService::Preference* pref) {
692   uint32_t write_flags = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
693 
694   if (!pref) {
695     return write_flags;
696   }
697 
698   if (pref->registration_flags() & PrefRegistry::LOSSY_PREF) {
699     write_flags |= WriteablePrefStore::LOSSY_PREF_WRITE_FLAG;
700   }
701   return write_flags;
702 }
703