• 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 <string_view>
11 #include <utility>
12 
13 #include "base/check_deref.h"
14 #include "base/check_op.h"
15 #include "base/debug/alias.h"
16 #include "base/debug/dump_without_crashing.h"
17 #include "base/files/file_path.h"
18 #include "base/functional/bind.h"
19 #include "base/json/values_util.h"
20 #include "base/location.h"
21 #include "base/logging.h"
22 #include "base/memory/ptr_util.h"
23 #include "base/metrics/histogram.h"
24 #include "base/notreached.h"
25 #include "base/strings/strcat.h"
26 #include "base/strings/string_number_conversions.h"
27 #include "base/strings/string_util.h"
28 #include "base/task/sequenced_task_runner.h"
29 #include "base/values.h"
30 #include "build/chromeos_buildflags.h"
31 #include "components/prefs/default_pref_store.h"
32 #include "components/prefs/json_pref_store.h"
33 #include "components/prefs/pref_notifier_impl.h"
34 #include "components/prefs/pref_registry.h"
35 
36 #if BUILDFLAG(IS_CHROMEOS_ASH)
37 #include "components/prefs/value_map_pref_store.h"
38 #endif
39 
40 #if BUILDFLAG(IS_ANDROID)
41 #include "components/prefs/android/pref_service_android.h"
42 #endif
43 
44 #if BUILDFLAG(IS_CHROMEOS_ASH)
45 namespace pref_service_util {
GetAllDottedPaths(std::string_view prefix,const base::Value::Dict & dict,std::vector<std::string> & paths)46 void GetAllDottedPaths(std::string_view prefix,
47                        const base::Value::Dict& dict,
48                        std::vector<std::string>& paths) {
49   for (const auto pair : dict) {
50     std::string path;
51     if (prefix.empty()) {
52       path = pair.first;
53     } else {
54       path = base::StrCat({prefix, ".", pair.first});
55     }
56 
57     if (pair.second.is_dict()) {
58       GetAllDottedPaths(path, pair.second.GetDict(), paths);
59     } else {
60       paths.push_back(path);
61     }
62   }
63 }
64 
GetAllDottedPaths(const base::Value::Dict & dict,std::vector<std::string> & paths)65 void GetAllDottedPaths(const base::Value::Dict& dict,
66                        std::vector<std::string>& paths) {
67   GetAllDottedPaths("", dict, paths);
68 }
69 }  // namespace pref_service_util
70 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
71 
72 PrefService::PersistentPrefStoreLoadingObserver::
PersistentPrefStoreLoadingObserver(PrefService * pref_service)73     PersistentPrefStoreLoadingObserver(PrefService* pref_service)
74     : pref_service_(pref_service) {
75   DCHECK(pref_service_);
76 }
77 
OnInitializationCompleted(bool succeeded)78 void PrefService::PersistentPrefStoreLoadingObserver::OnInitializationCompleted(
79     bool succeeded) {
80   pref_service_->CheckPrefsLoaded();
81 }
82 
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)83 PrefService::PrefService(
84     std::unique_ptr<PrefNotifierImpl> pref_notifier,
85     std::unique_ptr<PrefValueStore> pref_value_store,
86     scoped_refptr<PersistentPrefStore> user_prefs,
87     scoped_refptr<PersistentPrefStore> standalone_browser_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       standalone_browser_pref_store_(std::move(standalone_browser_prefs)),
96       read_error_callback_(std::move(read_error_callback)),
97       pref_registry_(std::move(pref_registry)),
98       pref_store_observer_(
99           std::make_unique<PrefService::PersistentPrefStoreLoadingObserver>(
100               this)) {
101   pref_notifier_->SetPrefService(this);
102 
103   DCHECK(pref_registry_);
104   DCHECK(pref_value_store_);
105 
106   InitFromStorage(async);
107 }
108 
~PrefService()109 PrefService::~PrefService() {
110   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
111 
112   // Remove observers. This could be necessary if this service is destroyed
113   // before the prefs are fully loaded.
114   user_pref_store_->RemoveObserver(pref_store_observer_.get());
115   if (standalone_browser_pref_store_) {
116     standalone_browser_pref_store_->RemoveObserver(pref_store_observer_.get());
117   }
118 
119   // TODO(crbug.com/942491, 946668, 945772) The following code collects
120   // augments stack dumps created by ~PrefNotifierImpl() with information
121   // whether the profile owning the PrefService is an incognito profile.
122   // Delete this, once the bugs are closed.
123   const bool is_incognito_profile = user_pref_store_->IsInMemoryPrefStore();
124   base::debug::Alias(&is_incognito_profile);
125   // Export value of is_incognito_profile to a string so that `grep`
126   // is a sufficient tool to analyze crashdumps.
127   char is_incognito_profile_string[32];
128   strncpy(is_incognito_profile_string,
129           is_incognito_profile ? "is_incognito: yes" : "is_incognito: no",
130           sizeof(is_incognito_profile_string));
131   base::debug::Alias(&is_incognito_profile_string);
132 }
133 
InitFromStorage(bool async)134 void PrefService::InitFromStorage(bool async) {
135   if (!async) {
136     if (!user_pref_store_->IsInitializationComplete()) {
137       user_pref_store_->ReadPrefs();
138     }
139     if (standalone_browser_pref_store_ &&
140         !standalone_browser_pref_store_->IsInitializationComplete()) {
141       standalone_browser_pref_store_->ReadPrefs();
142     }
143     CheckPrefsLoaded();
144     return;
145   }
146 
147   CheckPrefsLoaded();
148 
149   if (!user_pref_store_->IsInitializationComplete()) {
150     user_pref_store_->AddObserver(pref_store_observer_.get());
151     user_pref_store_->ReadPrefsAsync(nullptr);
152   }
153 
154   if (standalone_browser_pref_store_ &&
155       !standalone_browser_pref_store_->IsInitializationComplete()) {
156     standalone_browser_pref_store_->AddObserver(pref_store_observer_.get());
157     standalone_browser_pref_store_->ReadPrefsAsync(nullptr);
158   }
159 }
160 
CheckPrefsLoaded()161 void PrefService::CheckPrefsLoaded() {
162   if (!(user_pref_store_->IsInitializationComplete() &&
163         (!standalone_browser_pref_store_ ||
164          standalone_browser_pref_store_->IsInitializationComplete()))) {
165     // Not done initializing both prefstores.
166     return;
167   }
168 
169   user_pref_store_->RemoveObserver(pref_store_observer_.get());
170   if (standalone_browser_pref_store_) {
171     standalone_browser_pref_store_->RemoveObserver(pref_store_observer_.get());
172   }
173 
174   // Both prefstores are initialized, get the read errors.
175   PersistentPrefStore::PrefReadError user_store_error =
176       user_pref_store_->GetReadError();
177   if (!standalone_browser_pref_store_) {
178     read_error_callback_.Run(user_store_error);
179     return;
180   }
181   PersistentPrefStore::PrefReadError standalone_browser_store_error =
182       standalone_browser_pref_store_->GetReadError();
183 
184   // If both stores have the same error (or no error), run the callback with
185   // either one. This avoids double-reporting (either way prefs weren't
186   // successfully fully loaded)
187   if (user_store_error == standalone_browser_store_error) {
188     read_error_callback_.Run(user_store_error);
189   } else if (user_store_error == PersistentPrefStore::PREF_READ_ERROR_NONE ||
190              user_store_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
191     // Prefer to report the standalone_browser_pref_store error if the
192     // user_pref_store error is not significant.
193     read_error_callback_.Run(standalone_browser_store_error);
194   } else {
195     // Either the user_pref_store error is significant, or
196     // both stores failed to load but for different reasons.
197     // The user_store error is more significant in essentially all cases,
198     // so prefer to report that.
199     read_error_callback_.Run(user_store_error);
200   }
201 }
202 
CommitPendingWrite(base::OnceClosure reply_callback,base::OnceClosure synchronous_done_callback)203 void PrefService::CommitPendingWrite(
204     base::OnceClosure reply_callback,
205     base::OnceClosure synchronous_done_callback) {
206   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
207   user_pref_store_->CommitPendingWrite(std::move(reply_callback),
208                                        std::move(synchronous_done_callback));
209 }
210 
SchedulePendingLossyWrites()211 void PrefService::SchedulePendingLossyWrites() {
212   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
213   user_pref_store_->SchedulePendingLossyWrites();
214 }
215 
GetBoolean(std::string_view path) const216 bool PrefService::GetBoolean(std::string_view path) const {
217   return GetValue(path).GetBool();
218 }
219 
GetInteger(std::string_view path) const220 int PrefService::GetInteger(std::string_view path) const {
221   return GetValue(path).GetInt();
222 }
223 
GetDouble(std::string_view path) const224 double PrefService::GetDouble(std::string_view path) const {
225   return GetValue(path).GetDouble();
226 }
227 
GetString(std::string_view path) const228 const std::string& PrefService::GetString(std::string_view path) const {
229   return GetValue(path).GetString();
230 }
231 
GetFilePath(std::string_view path) const232 base::FilePath PrefService::GetFilePath(std::string_view path) const {
233   const base::Value& value = GetValue(path);
234   std::optional<base::FilePath> result = base::ValueToFilePath(value);
235   DCHECK(result);
236   return *result;
237 }
238 
HasPrefPath(std::string_view path) const239 bool PrefService::HasPrefPath(std::string_view path) const {
240   const Preference* pref = FindPreference(path);
241   return pref && !pref->IsDefaultValue();
242 }
243 
IteratePreferenceValues(base::RepeatingCallback<void (const std::string & key,const base::Value & value)> callback) const244 void PrefService::IteratePreferenceValues(
245     base::RepeatingCallback<void(const std::string& key,
246                                  const base::Value& value)> callback) const {
247   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
248   for (const auto& it : *pref_registry_)
249     callback.Run(it.first, *GetPreferenceValue(it.first));
250 }
251 
GetPreferenceValues(IncludeDefaults include_defaults) const252 base::Value::Dict PrefService::GetPreferenceValues(
253     IncludeDefaults include_defaults) const {
254   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
255 
256   base::Value::Dict out;
257   for (const auto& it : *pref_registry_) {
258     if (include_defaults == INCLUDE_DEFAULTS) {
259       out.SetByDottedPath(it.first, GetPreferenceValue(it.first)->Clone());
260     } else {
261       const Preference* pref = FindPreference(it.first);
262       if (pref->IsDefaultValue()) {
263         continue;
264       }
265       out.SetByDottedPath(it.first, pref->GetValue()->Clone());
266     }
267   }
268   return out;
269 }
270 
271 std::vector<PrefService::PreferenceValueAndStore>
GetPreferencesValueAndStore() const272 PrefService::GetPreferencesValueAndStore() const {
273   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
274 
275   std::vector<PreferenceValueAndStore> result;
276   for (const auto& it : *pref_registry_) {
277     auto* preference = FindPreference(it.first);
278     CHECK(preference);
279     PreferenceValueAndStore pref_data{
280         it.first, preference->GetValue()->Clone(),
281         pref_value_store_->ControllingPrefStoreForPref(it.first)};
282     result.emplace_back(std::move(pref_data));
283   }
284   return result;
285 }
286 
FindPreference(std::string_view path) const287 const PrefService::Preference* PrefService::FindPreference(
288     std::string_view path) const {
289   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
290   auto it = prefs_map_.find(path);
291   if (it != prefs_map_.end())
292     return &(it->second);
293   const base::Value* default_value = nullptr;
294   if (!pref_registry_->defaults()->GetValue(path, &default_value)) {
295     return nullptr;
296   }
297   it = prefs_map_
298            .insert(std::make_pair(
299                std::string(path),
300                Preference(this, std::string(path), default_value->type())))
301            .first;
302   return &(it->second);
303 }
304 
ReadOnly() const305 bool PrefService::ReadOnly() const {
306   return user_pref_store_->ReadOnly();
307 }
308 
GetInitializationStatus() const309 PrefService::PrefInitializationStatus PrefService::GetInitializationStatus()
310     const {
311   if (!user_pref_store_->IsInitializationComplete())
312     return INITIALIZATION_STATUS_WAITING;
313 
314   switch (user_pref_store_->GetReadError()) {
315     case PersistentPrefStore::PREF_READ_ERROR_NONE:
316       return INITIALIZATION_STATUS_SUCCESS;
317     case PersistentPrefStore::PREF_READ_ERROR_NO_FILE:
318       return INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE;
319     default:
320       return INITIALIZATION_STATUS_ERROR;
321   }
322 }
323 
324 PrefService::PrefInitializationStatus
GetAllPrefStoresInitializationStatus() const325 PrefService::GetAllPrefStoresInitializationStatus() const {
326   if (!pref_value_store_->IsInitializationComplete())
327     return INITIALIZATION_STATUS_WAITING;
328 
329   return GetInitializationStatus();
330 }
331 
IsManagedPreference(std::string_view path) const332 bool PrefService::IsManagedPreference(std::string_view path) const {
333   const Preference* pref = FindPreference(path);
334   return pref && pref->IsManaged();
335 }
336 
IsPreferenceManagedByCustodian(std::string_view path) const337 bool PrefService::IsPreferenceManagedByCustodian(std::string_view path) const {
338   const Preference* pref = FindPreference(path);
339   return pref && pref->IsManagedByCustodian();
340 }
341 
IsUserModifiablePreference(std::string_view path) const342 bool PrefService::IsUserModifiablePreference(std::string_view path) const {
343   const Preference* pref = FindPreference(path);
344   return pref && pref->IsUserModifiable();
345 }
346 
GetValue(std::string_view path) const347 const base::Value& PrefService::GetValue(std::string_view path) const {
348   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
349   return *GetPreferenceValue(path);
350 }
351 
GetDict(std::string_view path) const352 const base::Value::Dict& PrefService::GetDict(std::string_view path) const {
353   const base::Value& value = GetValue(path);
354   return value.GetDict();
355 }
356 
GetList(std::string_view path) const357 const base::Value::List& PrefService::GetList(std::string_view path) const {
358   const base::Value& value = GetValue(path);
359   return value.GetList();
360 }
361 
GetUserPrefValue(std::string_view path) const362 const base::Value* PrefService::GetUserPrefValue(std::string_view path) const {
363   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
364 
365   const Preference* pref = FindPreference(path);
366   if (!pref) {
367     NOTREACHED() << "Trying to get an unregistered pref: " << path;
368   }
369 
370   // Look for an existing preference in the user store. If it doesn't
371   // exist, return NULL.
372   base::Value* value = nullptr;
373   if (!user_pref_store_->GetMutableValue(path, &value))
374     return nullptr;
375 
376   if (value->type() != pref->GetType()) {
377     DUMP_WILL_BE_NOTREACHED()
378         << "Pref value type doesn't match registered type.";
379     return nullptr;
380   }
381 
382   return value;
383 }
384 
SetDefaultPrefValue(std::string_view path,base::Value value)385 void PrefService::SetDefaultPrefValue(std::string_view path,
386                                       base::Value value) {
387   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
388   pref_registry_->SetDefaultPrefValue(path, std::move(value));
389 }
390 
GetDefaultPrefValue(std::string_view path) const391 const base::Value* PrefService::GetDefaultPrefValue(
392     std::string_view path) const {
393   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
394   // Lookup the preference in the default store.
395   const base::Value* value = nullptr;
396   bool has_value = pref_registry_->defaults()->GetValue(path, &value);
397   DCHECK(has_value) << "Default value missing for pref: " << path;
398   return value;
399 }
400 
AddPrefObserver(std::string_view path,PrefObserver * obs)401 void PrefService::AddPrefObserver(std::string_view path, PrefObserver* obs) {
402   pref_notifier_->AddPrefObserver(path, obs);
403 }
404 
RemovePrefObserver(std::string_view path,PrefObserver * obs)405 void PrefService::RemovePrefObserver(std::string_view path, PrefObserver* obs) {
406   pref_notifier_->RemovePrefObserver(path, obs);
407 }
408 
AddPrefInitObserver(base::OnceCallback<void (bool)> obs)409 void PrefService::AddPrefInitObserver(base::OnceCallback<void(bool)> obs) {
410   pref_notifier_->AddInitObserver(std::move(obs));
411 }
412 
DeprecatedGetPrefRegistry()413 PrefRegistry* PrefService::DeprecatedGetPrefRegistry() {
414   return pref_registry_.get();
415 }
416 
ClearPref(std::string_view path)417 void PrefService::ClearPref(std::string_view path) {
418   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
419 
420   const Preference* pref = FindPreference(path);
421   if (!pref) {
422     NOTREACHED() << "Trying to clear an unregistered pref: " << path;
423   }
424   user_pref_store_->RemoveValue(path, GetWriteFlags(pref));
425 }
426 
ClearPrefsWithPrefixSilently(std::string_view prefix)427 void PrefService::ClearPrefsWithPrefixSilently(std::string_view prefix) {
428   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
429   user_pref_store_->RemoveValuesByPrefixSilently(prefix);
430 }
431 
OnStoreDeletionFromDisk()432 void PrefService::OnStoreDeletionFromDisk() {
433   user_pref_store_->OnStoreDeletionFromDisk();
434 }
435 
AddPrefObserverAllPrefs(PrefObserver * obs)436 void PrefService::AddPrefObserverAllPrefs(PrefObserver* obs) {
437   pref_notifier_->AddPrefObserverAllPrefs(obs);
438 }
439 
RemovePrefObserverAllPrefs(PrefObserver * obs)440 void PrefService::RemovePrefObserverAllPrefs(PrefObserver* obs) {
441   pref_notifier_->RemovePrefObserverAllPrefs(obs);
442 }
443 
444 #if BUILDFLAG(IS_ANDROID)
GetJavaObject()445 base::android::ScopedJavaLocalRef<jobject> PrefService::GetJavaObject() {
446   if (!pref_service_android_) {
447     pref_service_android_ = std::make_unique<PrefServiceAndroid>(this);
448   }
449   return pref_service_android_->GetJavaObject();
450 }
451 #endif
452 
Set(std::string_view path,const base::Value & value)453 void PrefService::Set(std::string_view path, const base::Value& value) {
454   SetUserPrefValue(path, value.Clone());
455 }
456 
SetBoolean(std::string_view path,bool value)457 void PrefService::SetBoolean(std::string_view path, bool value) {
458   SetUserPrefValue(path, base::Value(value));
459 }
460 
SetInteger(std::string_view path,int value)461 void PrefService::SetInteger(std::string_view path, int value) {
462   SetUserPrefValue(path, base::Value(value));
463 }
464 
SetDouble(std::string_view path,double value)465 void PrefService::SetDouble(std::string_view path, double value) {
466   SetUserPrefValue(path, base::Value(value));
467 }
468 
SetString(std::string_view path,std::string_view value)469 void PrefService::SetString(std::string_view path, std::string_view value) {
470   SetUserPrefValue(path, base::Value(value));
471 }
472 
SetDict(std::string_view path,base::Value::Dict dict)473 void PrefService::SetDict(std::string_view path, base::Value::Dict dict) {
474   SetUserPrefValue(path, base::Value(std::move(dict)));
475 }
476 
SetList(std::string_view path,base::Value::List list)477 void PrefService::SetList(std::string_view path, base::Value::List list) {
478   SetUserPrefValue(path, base::Value(std::move(list)));
479 }
480 
SetFilePath(std::string_view path,const base::FilePath & value)481 void PrefService::SetFilePath(std::string_view path,
482                               const base::FilePath& value) {
483   SetUserPrefValue(path, base::FilePathToValue(value));
484 }
485 
SetInt64(std::string_view path,int64_t value)486 void PrefService::SetInt64(std::string_view path, int64_t value) {
487   SetUserPrefValue(path, base::Int64ToValue(value));
488 }
489 
GetInt64(std::string_view path) const490 int64_t PrefService::GetInt64(std::string_view path) const {
491   const base::Value& value = GetValue(path);
492   std::optional<int64_t> integer = base::ValueToInt64(value);
493   DCHECK(integer);
494   return integer.value_or(0);
495 }
496 
SetUint64(std::string_view path,uint64_t value)497 void PrefService::SetUint64(std::string_view path, uint64_t value) {
498   SetUserPrefValue(path, base::Value(base::NumberToString(value)));
499 }
500 
GetUint64(std::string_view path) const501 uint64_t PrefService::GetUint64(std::string_view path) const {
502   const base::Value& value = GetValue(path);
503   if (!value.is_string())
504     return 0;
505 
506   uint64_t result;
507   base::StringToUint64(value.GetString(), &result);
508   return result;
509 }
510 
SetTime(std::string_view path,base::Time value)511 void PrefService::SetTime(std::string_view path, base::Time value) {
512   SetUserPrefValue(path, base::TimeToValue(value));
513 }
514 
GetTime(std::string_view path) const515 base::Time PrefService::GetTime(std::string_view path) const {
516   const base::Value& value = GetValue(path);
517   std::optional<base::Time> time = base::ValueToTime(value);
518   DCHECK(time);
519   return time.value_or(base::Time());
520 }
521 
SetTimeDelta(std::string_view path,base::TimeDelta value)522 void PrefService::SetTimeDelta(std::string_view path, base::TimeDelta value) {
523   SetUserPrefValue(path, base::TimeDeltaToValue(value));
524 }
525 
GetTimeDelta(std::string_view path) const526 base::TimeDelta PrefService::GetTimeDelta(std::string_view path) const {
527   const base::Value& value = GetValue(path);
528   std::optional<base::TimeDelta> time_delta = base::ValueToTimeDelta(value);
529   DCHECK(time_delta);
530   return time_delta.value_or(base::TimeDelta());
531 }
532 
GetMutableUserPref(std::string_view path,base::Value::Type type)533 base::Value* PrefService::GetMutableUserPref(std::string_view path,
534                                              base::Value::Type type) {
535   CHECK(type == base::Value::Type::DICT || type == base::Value::Type::LIST);
536   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
537 
538   const Preference* pref = FindPreference(path);
539   if (!pref) {
540     DUMP_WILL_BE_NOTREACHED() << "Trying to get an unregistered pref: " << path;
541     return nullptr;
542   }
543   if (pref->GetType() != type) {
544     NOTREACHED() << "Wrong type for GetMutableValue: " << path;
545   }
546 
547   // Look for an existing preference in the user store. Return it in case it
548   // exists and has the correct type.
549   base::Value* value = nullptr;
550   if (user_pref_store_->GetMutableValue(path, &value) &&
551       value->type() == type) {
552     return value;
553   }
554 
555   // If no user preference of the correct type exists, clone default value.
556   const base::Value* default_value = nullptr;
557   pref_registry_->defaults()->GetValue(path, &default_value);
558   DCHECK_EQ(default_value->type(), type);
559   user_pref_store_->SetValueSilently(path, default_value->Clone(),
560                                      GetWriteFlags(pref));
561   user_pref_store_->GetMutableValue(path, &value);
562   return value;
563 }
564 
ReportUserPrefChanged(const std::string & key)565 void PrefService::ReportUserPrefChanged(const std::string& key) {
566   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
567   user_pref_store_->ReportValueChanged(key, GetWriteFlags(FindPreference(key)));
568 }
569 
ReportUserPrefChanged(const std::string & key,std::set<std::vector<std::string>> path_components)570 void PrefService::ReportUserPrefChanged(
571     const std::string& key,
572     std::set<std::vector<std::string>> path_components) {
573   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
574   user_pref_store_->ReportSubValuesChanged(key, std::move(path_components),
575                                            GetWriteFlags(FindPreference(key)));
576 }
577 
SetUserPrefValue(std::string_view path,base::Value new_value)578 void PrefService::SetUserPrefValue(std::string_view path,
579                                    base::Value new_value) {
580   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
581 
582   const Preference* pref = FindPreference(path);
583   if (!pref) {
584     DUMP_WILL_BE_NOTREACHED()
585         << "Trying to write an unregistered pref: " << path;
586     return;
587   }
588   if (pref->GetType() != new_value.type()) {
589     NOTREACHED() << "Trying to set pref " << path << " of type "
590                  << pref->GetType() << " to value of type " << new_value.type();
591   }
592 
593   user_pref_store_->SetValue(path, std::move(new_value), GetWriteFlags(pref));
594 }
595 
UpdateCommandLinePrefStore(PrefStore * command_line_store)596 void PrefService::UpdateCommandLinePrefStore(PrefStore* command_line_store) {
597   pref_value_store_->UpdateCommandLinePrefStore(command_line_store);
598 }
599 
600 ///////////////////////////////////////////////////////////////////////////////
601 // PrefService::Preference
602 
Preference(const PrefService * service,std::string name,base::Value::Type type)603 PrefService::Preference::Preference(const PrefService* service,
604                                     std::string name,
605                                     base::Value::Type type)
606     : name_(std::move(name)),
607       type_(type),
608       // Cache the registration flags at creation time to avoid multiple map
609       // lookups later.
610       registration_flags_(service->pref_registry_->GetRegistrationFlags(name_)),
611       pref_service_(CHECK_DEREF(service)) {}
612 
GetValue() const613 const base::Value* PrefService::Preference::GetValue() const {
614   return pref_service_->GetPreferenceValue(name_);
615 }
616 
GetRecommendedValue() const617 const base::Value* PrefService::Preference::GetRecommendedValue() const {
618   DCHECK(pref_service_->FindPreference(name_))
619       << "Must register pref before getting its value";
620 
621   const base::Value* found_value = nullptr;
622   if (pref_value_store()->GetRecommendedValue(name_, type_, &found_value)) {
623     DCHECK(found_value->type() == type_);
624     return found_value;
625   }
626 
627   // The pref has no recommended value.
628   return nullptr;
629 }
630 
IsManaged() const631 bool PrefService::Preference::IsManaged() const {
632   return pref_value_store()->PrefValueInManagedStore(name_);
633 }
634 
IsManagedByCustodian() const635 bool PrefService::Preference::IsManagedByCustodian() const {
636   return pref_value_store()->PrefValueInSupervisedStore(name_);
637 }
638 
IsRecommended() const639 bool PrefService::Preference::IsRecommended() const {
640   return pref_value_store()->PrefValueFromRecommendedStore(name_);
641 }
642 
HasExtensionSetting() const643 bool PrefService::Preference::HasExtensionSetting() const {
644   return pref_value_store()->PrefValueInExtensionStore(name_);
645 }
646 
HasUserSetting() const647 bool PrefService::Preference::HasUserSetting() const {
648   return pref_value_store()->PrefValueInUserStore(name_);
649 }
650 
IsExtensionControlled() const651 bool PrefService::Preference::IsExtensionControlled() const {
652   return pref_value_store()->PrefValueFromExtensionStore(name_);
653 }
654 
IsUserControlled() const655 bool PrefService::Preference::IsUserControlled() const {
656   return pref_value_store()->PrefValueFromUserStore(name_);
657 }
658 
IsDefaultValue() const659 bool PrefService::Preference::IsDefaultValue() const {
660   return pref_value_store()->PrefValueFromDefaultStore(name_);
661 }
662 
IsUserModifiable() const663 bool PrefService::Preference::IsUserModifiable() const {
664   return pref_value_store()->PrefValueUserModifiable(name_);
665 }
666 
IsExtensionModifiable() const667 bool PrefService::Preference::IsExtensionModifiable() const {
668   return pref_value_store()->PrefValueExtensionModifiable(name_);
669 }
670 
671 #if BUILDFLAG(IS_CHROMEOS_ASH)
IsStandaloneBrowserControlled() const672 bool PrefService::Preference::IsStandaloneBrowserControlled() const {
673   return pref_value_store()->PrefValueFromStandaloneBrowserStore(name_);
674 }
675 
IsStandaloneBrowserModifiable() const676 bool PrefService::Preference::IsStandaloneBrowserModifiable() const {
677   return pref_value_store()->PrefValueStandaloneBrowserModifiable(name_);
678 }
679 #endif
680 
GetPreferenceValue(std::string_view path) const681 const base::Value* PrefService::GetPreferenceValue(
682     std::string_view path) const {
683   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
684 
685   const base::Value* default_value = nullptr;
686   CHECK(pref_registry_->defaults()->GetValue(path, &default_value))
687       << "Trying to access an unregistered pref: " << path;
688   CHECK(default_value);
689   const base::Value::Type default_type = default_value->type();
690 
691   const base::Value* found_value = nullptr;
692   // GetValue shouldn't fail because every registered preference has at least a
693   // default value.
694   CHECK(pref_value_store_->GetValue(path, default_type, &found_value));
695   CHECK(found_value);
696   // The type is expected to match here thanks to a verification in
697   // PrefValueStore::GetValueFromStoreWithType which discards polluted values
698   // (and we should at least get a matching type from the default store if no
699   // other store has a valid value+type).
700   CHECK_EQ(found_value->type(), default_type);
701   return found_value;
702 }
703 
704 #if BUILDFLAG(IS_CHROMEOS_ASH)
SetStandaloneBrowserPref(std::string_view path,const base::Value & value)705 void PrefService::SetStandaloneBrowserPref(std::string_view path,
706                                            const base::Value& value) {
707   if (!standalone_browser_pref_store_) {
708     LOG(WARNING) << "Failure to set value of " << path
709                  << " in standalone browser store";
710     return;
711   }
712   standalone_browser_pref_store_->SetValue(
713       path, value.Clone(), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
714 }
715 
RemoveAllStandaloneBrowserPrefs()716 void PrefService::RemoveAllStandaloneBrowserPrefs() {
717   if (!standalone_browser_pref_store_) {
718     LOG(WARNING) << "standalone_browser_pref_store_ is null";
719     return;
720   }
721 
722   std::vector<std::string> paths;
723   pref_service_util::GetAllDottedPaths(
724       standalone_browser_pref_store_->GetValues(), paths);
725 
726   for (const std::string& path : paths) {
727     standalone_browser_pref_store_->RemoveValue(
728         path, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
729   }
730 }
731 #endif
732 
733 // static
GetWriteFlags(const PrefService::Preference * pref)734 uint32_t PrefService::GetWriteFlags(const PrefService::Preference* pref) {
735   uint32_t write_flags = WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS;
736 
737   if (!pref) {
738     return write_flags;
739   }
740 
741   if (pref->registration_flags() & PrefRegistry::LOSSY_PREF) {
742     write_flags |= WriteablePrefStore::LOSSY_PREF_WRITE_FLAG;
743   }
744   return write_flags;
745 }
746