• 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 // This provides a way to access the application's current preferences.
6 
7 // Chromium settings and storage represent user-selected preferences and
8 // information and MUST not be extracted, overwritten or modified except
9 // through Chromium defined APIs.
10 
11 #ifndef COMPONENTS_PREFS_PREF_SERVICE_H_
12 #define COMPONENTS_PREFS_PREF_SERVICE_H_
13 
14 #include <stdint.h>
15 
16 #include <memory>
17 #include <set>
18 #include <string>
19 #include <unordered_map>
20 #include <vector>
21 
22 #include "base/compiler_specific.h"
23 #include "base/functional/callback.h"
24 #include "base/memory/raw_ptr.h"
25 #include "base/memory/ref_counted.h"
26 #include "base/sequence_checker.h"
27 #include "base/strings/string_piece.h"
28 #include "base/time/time.h"
29 #include "base/values.h"
30 #include "build/build_config.h"
31 #include "build/chromeos_buildflags.h"
32 #include "components/prefs/persistent_pref_store.h"
33 #include "components/prefs/pref_value_store.h"
34 #include "components/prefs/prefs_export.h"
35 
36 #if BUILDFLAG(IS_ANDROID)
37 #include "base/android/scoped_java_ref.h"
38 #endif
39 
40 class PrefNotifier;
41 class PrefNotifierImpl;
42 class PrefObserver;
43 class PrefRegistry;
44 class PrefStore;
45 #if BUILDFLAG(IS_ANDROID)
46 class PrefServiceAndroid;
47 #endif
48 
49 namespace base {
50 class FilePath;
51 }
52 
53 namespace prefs {
54 class ScopedDictionaryPrefUpdate;
55 }
56 
57 namespace subtle {
58 class PrefMemberBase;
59 class ScopedUserPrefUpdateBase;
60 }
61 
62 // Base class for PrefServices. You can use the base class to read and
63 // interact with preferences, but not to register new preferences; for
64 // that see e.g. PrefRegistrySimple.
65 //
66 // Settings and storage accessed through this class represent
67 // user-selected preferences and information and MUST not be
68 // extracted, overwritten or modified except through the defined APIs.
69 class COMPONENTS_PREFS_EXPORT PrefService {
70  public:
71   enum PrefInitializationStatus {
72     INITIALIZATION_STATUS_WAITING,
73     INITIALIZATION_STATUS_SUCCESS,
74     INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE,
75     INITIALIZATION_STATUS_ERROR
76   };
77 
78   enum IncludeDefaults {
79     INCLUDE_DEFAULTS,
80     EXCLUDE_DEFAULTS,
81   };
82 
83   // A helper class to store all the information associated with a preference.
84   class COMPONENTS_PREFS_EXPORT Preference {
85    public:
86     // The type of the preference is determined by the type with which it is
87     // registered. This type needs to be a boolean, integer, double, string,
88     // dictionary (a branch), or list.  You shouldn't need to construct this on
89     // your own; use the PrefService::Register*Pref methods instead.
90     Preference(const PrefService* service,
91                std::string name,
92                base::Value::Type type);
~Preference()93     ~Preference() {}
94 
95     // Returns the name of the Preference (i.e., the key, e.g.,
96     // browser.window_placement).
name()97     std::string name() const { return name_; }
98 
99     // Returns the registered type of the preference.
GetType()100     base::Value::Type GetType() const { return type_; }
101 
102     // Returns the value of the Preference, falling back to the registered
103     // default value if no other has been set.
104     const base::Value* GetValue() const;
105 
106     // Returns the value recommended by the admin, if any.
107     const base::Value* GetRecommendedValue() const;
108 
109     // Returns true if the Preference is managed, i.e. set by an admin policy.
110     // Since managed prefs have the highest priority, this also indicates
111     // whether the pref is actually being controlled by the policy setting.
112     bool IsManaged() const;
113 
114     // Returns true if the Preference is controlled by the custodian of the
115     // supervised user. Since a supervised user is not expected to have an admin
116     // policy, this is the controlling pref if set.
117     bool IsManagedByCustodian() const;
118 
119     // Returns true if the Preference's current value is one recommended by
120     // admin policy. Note that this will be false if any other higher-priority
121     // source overrides the value (e.g., the user has set a value).
122     bool IsRecommended() const;
123 
124     // Returns true if the Preference has a value set by an extension, even if
125     // that value is being overridden by a higher-priority source.
126     bool HasExtensionSetting() const;
127 
128     // Returns true if the Preference has a user setting, even if that value is
129     // being overridden by a higher-priority source.
130     bool HasUserSetting() const;
131 
132     // Returns true if the Preference value is currently being controlled by an
133     // extension, and not by any higher-priority source.
134     bool IsExtensionControlled() const;
135 
136     // Returns true if the Preference value is currently being controlled by a
137     // user setting, and not by any higher-priority source.
138     bool IsUserControlled() const;
139 
140     // Returns true if the Preference is currently using its default value,
141     // and has not been set by any higher-priority source (even with the same
142     // value).
143     bool IsDefaultValue() const;
144 
145     // Returns true if the user can change the Preference value, which is the
146     // case if no higher-priority source than the user store controls the
147     // Preference.
148     bool IsUserModifiable() const;
149 
150     // Returns true if an extension can change the Preference value, which is
151     // the case if no higher-priority source than the extension store controls
152     // the Preference.
153     bool IsExtensionModifiable() const;
154 
155 #if BUILDFLAG(IS_CHROMEOS_ASH)
156     // Returns true if the Preference value is currently being controlled by a
157     // standalone browser (lacros) and not by any higher-priority source.
158     bool IsStandaloneBrowserControlled() const;
159 
160     // Returns true if a standalone browser (lacros) can change the Preference
161     // value, which is the case if no higher-priority source than the standalone
162     // browser store controls the Preference.
163     bool IsStandaloneBrowserModifiable() const;
164 #endif
165 
166     // Return the registration flags for this pref as a bitmask of
167     // PrefRegistry::PrefRegistrationFlags.
registration_flags()168     uint32_t registration_flags() const { return registration_flags_; }
169 
170    private:
171     friend class PrefService;
172 
pref_value_store()173     PrefValueStore* pref_value_store() const {
174       return pref_service_->pref_value_store_.get();
175     }
176 
177     const std::string name_;
178 
179     const base::Value::Type type_;
180 
181     const uint32_t registration_flags_;
182 
183     // Reference to the PrefService in which this pref was created.
184     const raw_ptr<const PrefService> pref_service_;
185   };
186 
187   // You may wish to use PrefServiceFactory or one of its subclasses
188   // for simplified construction.
189   PrefService(std::unique_ptr<PrefNotifierImpl> pref_notifier,
190               std::unique_ptr<PrefValueStore> pref_value_store,
191               scoped_refptr<PersistentPrefStore> user_prefs,
192               scoped_refptr<PersistentPrefStore> standalone_browser_prefs,
193               scoped_refptr<PrefRegistry> pref_registry,
194               base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
195                   read_error_callback,
196               bool async);
197 
198   PrefService(const PrefService&) = delete;
199   PrefService& operator=(const PrefService&) = delete;
200 
201   virtual ~PrefService();
202 
203   // Lands pending writes to disk. This should only be used if we need to save
204   // immediately (basically, during shutdown). |reply_callback| will be posted
205   // to the current sequence when changes have been written.
206   // |synchronous_done_callback| on the other hand will be invoked right away
207   // wherever the writes complete (could even be invoked synchronously if no
208   // writes need to occur); this is useful when the current thread cannot pump
209   // messages to observe the reply (e.g. nested loops banned on main thread
210   // during shutdown). |synchronous_done_callback| must be thread-safe.
211   void CommitPendingWrite(
212       base::OnceClosure reply_callback = base::OnceClosure(),
213       base::OnceClosure synchronous_done_callback = base::OnceClosure());
214 
215   // Schedules a write if there is any lossy data pending. Unlike
216   // CommitPendingWrite() this does not immediately sync to disk, instead it
217   // triggers an eventual write if there is lossy data pending and if there
218   // isn't one scheduled already.
219   void SchedulePendingLossyWrites();
220 
221   // Returns true if the preference for the given preference name is available
222   // and is managed.
223   bool IsManagedPreference(const std::string& pref_name) const;
224 
225   // Returns true if the preference for the given preference name is available
226   // and is controlled by the parent/guardian of the child Account.
227   bool IsPreferenceManagedByCustodian(const std::string& pref_name) const;
228 
229   // Returns |true| if a preference with the given name is available and its
230   // value can be changed by the user.
231   bool IsUserModifiablePreference(const std::string& pref_name) const;
232 
233   // Look up a preference.  Returns NULL if the preference is not
234   // registered.
235   const PrefService::Preference* FindPreference(const std::string& path) const;
236 
237   // If the path is valid and the value at the end of the path matches the type
238   // specified, it will return the specified value.  Otherwise, the default
239   // value (set when the pref was registered) will be returned.
240   bool GetBoolean(base::StringPiece path) const;
241   int GetInteger(base::StringPiece path) const;
242   double GetDouble(base::StringPiece path) const;
243   const std::string& GetString(base::StringPiece path) const;
244   base::FilePath GetFilePath(base::StringPiece path) const;
245 
246   // Returns the branch if it exists, or the registered default value otherwise.
247   // `path` must point to a registered preference (DCHECK).
248   const base::Value& GetValue(base::StringPiece path) const;
249 
250   // Returns the branch if it exists, or the registered default value otherwise.
251   // `path` must point to a registered preference whose value and registered
252   // default are of type `base::Value::Type::DICT (DCHECK).
253   const base::Value::Dict& GetDict(base::StringPiece path) const;
254 
255   // Returns the branch if it exists, or the registered default value otherwise.
256   // `path` must point to a registered preference whose value and registered
257   // default are of type `base::Value::Type::LIST (DCHECK).
258   const base::Value::List& GetList(base::StringPiece path) const;
259 
260   // Removes a user pref and restores the pref to its default value.
261   void ClearPref(const std::string& path);
262 
263   // Removes user prefs that start with |prefix|.
264   void ClearPrefsWithPrefixSilently(const std::string& prefix);
265 
266   // If the path is valid (i.e., registered), update the pref value in the user
267   // prefs.
268   //
269   // To set the value of dictionary or list values in the pref tree, use
270   // SetDict()/SetList(), but to modify the value of a dictionary or list use
271   // either ScopedDictPrefUpdate or ScopedListPrefUpdate from
272   // scoped_user_pref_update.h.
273   void Set(const std::string& path, const base::Value& value);
274   void SetBoolean(const std::string& path, bool value);
275   void SetInteger(const std::string& path, int value);
276   void SetDouble(const std::string& path, double value);
277   void SetString(const std::string& path, const std::string& value);
278   void SetDict(const std::string& path, base::Value::Dict dict);
279   void SetList(const std::string& path, base::Value::List list);
280   void SetFilePath(const std::string& path, const base::FilePath& value);
281 
282   // Int64 helper methods that actually store the given value as a string.
283   // Note that if obtaining the named value via GetDictionary or GetList, the
284   // Value type will be Type::STRING.
285   void SetInt64(const std::string& path, int64_t value);
286   int64_t GetInt64(const std::string& path) const;
287 
288   // As above, but for unsigned values.
289   void SetUint64(const std::string& path, uint64_t value);
290   uint64_t GetUint64(const std::string& path) const;
291 
292   // Time helper methods that actually store the given value as a string, which
293   // represents the number of microseconds elapsed (absolute for TimeDelta and
294   // relative to Windows epoch for Time variants). Note that if obtaining the
295   // named value via GetDictionary or GetList, the Value type will be
296   // Type::STRING.
297   void SetTime(const std::string& path, base::Time value);
298   base::Time GetTime(const std::string& path) const;
299   void SetTimeDelta(const std::string& path, base::TimeDelta value);
300   base::TimeDelta GetTimeDelta(const std::string& path) const;
301 
302   // Returns the value of the given preference, from the user pref store. If
303   // the preference is not set in the user pref store, returns NULL.
304   const base::Value* GetUserPrefValue(const std::string& path) const;
305 
306   // Changes the default value for a preference.
307   //
308   // Will cause a pref change notification to be fired if this causes
309   // the effective value to change.
310   void SetDefaultPrefValue(const std::string& path, base::Value value);
311 
312   // Returns the default value of the given preference. |path| must point to a
313   // registered preference. In that case, will never return nullptr, so callers
314   // do not need to check this.
315   const base::Value* GetDefaultPrefValue(const std::string& path) const;
316 
317   // Returns true if a value has been set for the specified path.
318   // NOTE: this is NOT the same as FindPreference. In particular
319   // FindPreference returns whether RegisterXXX has been invoked, where as
320   // this checks if a value exists for the path.
321   bool HasPrefPath(const std::string& path) const;
322 
323   // Issues a callback for every preference value. The preferences must not be
324   // mutated during iteration.
325   void IteratePreferenceValues(
326       base::RepeatingCallback<void(const std::string& key,
327                                    const base::Value& value)> callback) const;
328 
329   // Returns a dictionary with effective preference values. This is an expensive
330   // operation which does a deep copy. Use only if you really need the results
331   // in a base::Value (for example, for JSON serialization). Otherwise use
332   // IteratePreferenceValues above to avoid the copies.
333   //
334   // If INCLUDE_DEFAULTS is requested, preferences set to their default values
335   // will be included. Otherwise, these will be omitted from the returned
336   // dictionary.
337   base::Value::Dict GetPreferenceValues(IncludeDefaults include_defaults) const;
338 
339   bool ReadOnly() const;
340 
341   // Returns the initialization state, taking only user prefs into account.
342   PrefInitializationStatus GetInitializationStatus() const;
343 
344   // Returns the initialization state, taking all pref stores into account.
345   PrefInitializationStatus GetAllPrefStoresInitializationStatus() const;
346 
347   // Tell our PrefValueStore to update itself to |command_line_store|.
348   // Takes ownership of the store.
349   virtual void UpdateCommandLinePrefStore(PrefStore* command_line_store);
350 
351   // We run the callback once, when initialization completes. The bool
352   // parameter will be set to true for successful initialization,
353   // false for unsuccessful.
354   void AddPrefInitObserver(base::OnceCallback<void(bool)> callback);
355 
356   // Returns the PrefRegistry object for this service. You should not
357   // use this; the intent is for no registrations to take place after
358   // PrefService has been constructed.
359   //
360   // Instead of using this method, the recommended approach is to
361   // register all preferences for a class Xyz up front in a static
362   // Xyz::RegisterPrefs function, which gets invoked early in the
363   // application's start-up, before a PrefService is created.
364   //
365   // As an example, prefs registration in Chrome is triggered by the
366   // functions chrome::RegisterPrefs (for global preferences) and
367   // chrome::RegisterProfilePrefs (for user-specific preferences)
368   // implemented in chrome/browser/prefs/browser_prefs.cc.
369   PrefRegistry* DeprecatedGetPrefRegistry();
370 
371   // Invoked when the store is deleted from disk. Allows this PrefService
372   // to tangentially cleanup data it may have saved outside the store.
373   void OnStoreDeletionFromDisk();
374 
375   // A low level function for registering an observer for every single
376   // preference changed notification. The caller must ensure that the observer
377   // remains valid as long as it is registered. Pointer ownership is not
378   // transferred.
379   //
380   // Almost all calling code should use a PrefChangeRegistrar instead.
381   //
382   // AVOID ADDING THESE. These are low-level observer notifications that are
383   // called for every pref change. This can lead to inefficiency, and the lack
384   // of a "registrar" model makes it easy to forget to undregister. It is
385   // really designed for integrating other notification systems, not for normal
386   // observation.
387   void AddPrefObserverAllPrefs(PrefObserver* obs);
388   void RemovePrefObserverAllPrefs(PrefObserver* obs);
389 
390 #if BUILDFLAG(IS_CHROMEOS_ASH)
391   // Write extension-controlled prefs from Lacros in ash.
392   void SetStandaloneBrowserPref(const std::string& path,
393                                 const base::Value& value);
394   // Clear extension-controlled prefs from Lacros in ash.
395   void RemoveStandaloneBrowserPref(const std::string& path);
396 #endif
397 
398 #if BUILDFLAG(IS_ANDROID)
399   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
400 #endif
401 
402   // Returns the WriteablePrefStore::PrefWriteFlags for `pref`.
403   static uint32_t GetWriteFlags(const PrefService::Preference* pref);
404 
405  protected:
406   // The PrefNotifier handles registering and notifying preference observers.
407   // It is created and owned by this PrefService. Subclasses may access it for
408   // unit testing.
409   const std::unique_ptr<PrefNotifierImpl> pref_notifier_;
410 
411   // The PrefValueStore provides prioritized preference values. It is owned by
412   // this PrefService. Subclasses may access it for unit testing.
413   std::unique_ptr<PrefValueStore> pref_value_store_;
414 
415   // Pref Stores and profile that we passed to the PrefValueStore.
416   const scoped_refptr<PersistentPrefStore> user_pref_store_;
417   const scoped_refptr<PersistentPrefStore> standalone_browser_pref_store_;
418 
419   // Callback to call when a read error occurs. Always invoked on the sequence
420   // this PrefService was created own.
421   const base::RepeatingCallback<void(PersistentPrefStore::PrefReadError)>
422       read_error_callback_;
423 
424  private:
425   // Hash map expected to be fastest here since it minimises expensive
426   // string comparisons. Order is unimportant, and deletions are rare.
427   // Confirmed on Android where this speeded Chrome startup by roughly 50ms
428   // vs. std::map, and by roughly 180ms vs. std::set of Preference pointers.
429   typedef std::unordered_map<std::string, Preference> PreferenceMap;
430 
431   // Give access to ReportUserPrefChanged() and GetMutableUserPref().
432   friend class subtle::ScopedUserPrefUpdateBase;
433   friend class PrefServiceTest_WriteablePrefStoreFlags_Test;
434   friend class prefs::ScopedDictionaryPrefUpdate;
435 
436   // Registration of pref change observers must be done using the
437   // PrefChangeRegistrar, which is declared as a friend here to grant it
438   // access to the otherwise protected members Add/RemovePrefObserver.
439   // PrefMember registers for preferences changes notification directly to
440   // avoid the storage overhead of the registrar, so its base class must be
441   // declared as a friend, too.
442   friend class PrefChangeRegistrar;
443   friend class subtle::PrefMemberBase;
444 
445   // These are protected so they can only be accessed by the friend
446   // classes listed above.
447   //
448   // If the pref at the given path changes, we call the observer's
449   // OnPreferenceChanged method. Note that observers should not call
450   // these methods directly but rather use a PrefChangeRegistrar to
451   // make sure the observer gets cleaned up properly.
452   //
453   // Virtual for testing.
454   virtual void AddPrefObserver(const std::string& path, PrefObserver* obs);
455   virtual void RemovePrefObserver(const std::string& path, PrefObserver* obs);
456 
457   // A PrefStore::Observer which reports loading errors from
458   // PersistentPrefStores after they are loaded. Usually this is only user_prefs
459   // however in ash it additionally includes standalone_browser_prefs. Errors
460   // are only reported once even though multiple files may be loaded.
461   class PersistentPrefStoreLoadingObserver : public PrefStore::Observer {
462    public:
463     explicit PersistentPrefStoreLoadingObserver(PrefService* pref_service_);
464 
465     // PrefStore::Observer implementation
OnPrefValueChanged(const std::string & key)466     void OnPrefValueChanged(const std::string& key) override {}
467     void OnInitializationCompleted(bool succeeded) override;
468 
469    private:
470     raw_ptr<PrefService> pref_service_ = nullptr;
471   };
472 
473   // Sends notification of a changed preference. This needs to be called by
474   // a ScopedDictPrefUpdate or ScopedListPrefUpdate if a Value::Dict or
475   // Value::List is changed.
476   void ReportUserPrefChanged(const std::string& key);
477   void ReportUserPrefChanged(
478       const std::string& key,
479       std::set<std::vector<std::string>> path_components);
480 
481   // Sets the value for this pref path in the user pref store and informs the
482   // PrefNotifier of the change.
483   void SetUserPrefValue(const std::string& path, base::Value new_value);
484 
485   // Load preferences from storage, attempting to diagnose and handle errors.
486   // This should only be called from the constructor.
487   void InitFromStorage(bool async);
488 
489   // Verifies that prefs are fully loaded from disk, handling errors. This
490   // method may be called multiple times, but no more than once after all prefs
491   // are loaded.
492   void CheckPrefsLoaded();
493 
494   // Used to set the value of dictionary or list values in the user pref store.
495   // This will create a dictionary or list if one does not exist in the user
496   // pref store. This method returns NULL only if you're requesting an
497   // unregistered pref or a non-dict/non-list pref.
498   // |type| may only be Values::Type::DICT or Values::Type::LIST and
499   // |path| must point to a registered preference of type |type|.
500   // Ownership of the returned value remains at the user pref store.
501   base::Value* GetMutableUserPref(const std::string& path,
502                                   base::Value::Type type);
503 
504   // GetPreferenceValue is the equivalent of FindPreference(path)->GetValue(),
505   // it has been added for performance. It is faster because it does
506   // not need to find or create a Preference object to get the
507   // value (GetValue() calls back though the preference service to
508   // actually get the value.).
509   const base::Value* GetPreferenceValue(base::StringPiece path) const;
510   const base::Value* GetPreferenceValueChecked(base::StringPiece path) const;
511 
512   const scoped_refptr<PrefRegistry> pref_registry_;
513 
514   std::unique_ptr<PrefService::PersistentPrefStoreLoadingObserver>
515       pref_store_observer_;
516 
517   // Local cache of registered Preference objects. The pref_registry_
518   // is authoritative with respect to what the types and default values
519   // of registered preferences are.
520   mutable PreferenceMap prefs_map_;
521 
522 #if BUILDFLAG(IS_ANDROID)
523   // Manage and fetch the java object that wraps this PrefService on
524   // android.
525   std::unique_ptr<PrefServiceAndroid> pref_service_android_;
526 #endif
527 
528   SEQUENCE_CHECKER(sequence_checker_);
529 };
530 
531 #endif  // COMPONENTS_PREFS_PREF_SERVICE_H_
532