• 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 #ifndef COMPONENTS_PREFS_PREF_VALUE_STORE_H_
6 #define COMPONENTS_PREFS_PREF_VALUE_STORE_H_
7 
8 #include <array>
9 #include <functional>
10 #include <map>
11 #include <memory>
12 #include <string>
13 #include <string_view>
14 #include <type_traits>
15 #include <vector>
16 
17 #include "base/functional/callback.h"
18 #include "base/memory/raw_ptr.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/values.h"
21 #include "components/prefs/pref_store.h"
22 #include "components/prefs/prefs_export.h"
23 
24 class PrefNotifier;
25 class PrefStore;
26 
27 // The PrefValueStore manages various sources of values for Preferences
28 // (e.g., configuration policies, extensions, and user settings). It returns
29 // the value of a Preference from the source with the highest priority, and
30 // allows setting user-defined values for preferences that are not managed.
31 //
32 // Unless otherwise explicitly noted, all of the methods of this class must
33 // be called on the UI thread.
34 class COMPONENTS_PREFS_EXPORT PrefValueStore {
35  public:
36   using PrefChangedCallback = base::RepeatingCallback<void(const std::string&)>;
37 
38   // PrefStores must be listed here in order from highest to lowest priority.
39   //   MANAGED contains all managed preferences that are provided by
40   //      mandatory policies (e.g. Windows Group Policy or cloud policy).
41   //   SUPERVISED_USER contains preferences that are valid for supervised users.
42   //   EXTENSION contains preferences set by extensions.
43   //   STANDALONE_BROWSER contains system preferences inherited from a separate
44   //      Chrome instance. One relevant source is extension prefs in lacros
45   //      passed to ash, so these prefs have similar precedence to extension
46   //      prefs.
47   //   COMMAND_LINE contains preferences set by command-line switches.
48   //   USER contains all user-set preferences.
49   //   RECOMMENDED contains all preferences that are provided by recommended
50   //      policies.
51   //   DEFAULT contains all application default preferences.
52   enum PrefStoreType {
53     // INVALID_STORE is not associated with an actual PrefStore but used as
54     // an invalid marker, e.g. as a return value.
55     INVALID_STORE = -1,
56     MANAGED_STORE = 0,
57     SUPERVISED_USER_STORE,
58     EXTENSION_STORE,
59     STANDALONE_BROWSER_STORE,
60     COMMAND_LINE_STORE,
61     USER_STORE,
62     RECOMMENDED_STORE,
63     DEFAULT_STORE,
64     PREF_STORE_TYPE_MAX = DEFAULT_STORE
65   };
66 
67   // In decreasing order of precedence:
68   //   |managed_prefs| contains all preferences from mandatory policies.
69   //   |supervised_user_prefs| contains all preferences from supervised user
70   //        settings, i.e. settings configured for a supervised user by their
71   //        custodian.
72   //   |extension_prefs| contains preference values set by extensions.
73   //   |command_line_prefs| contains preference values set by command-line
74   //        switches.
75   //   |user_prefs| contains all user-set preference values.
76   //   |recommended_prefs| contains all preferences from recommended policies.
77   //   |default_prefs| contains application-default preference values. It must
78   //        be non-null if any preferences are to be registered.
79   //
80   // |pref_notifier| facilitates broadcasting preference change notifications
81   // to the world.
82   PrefValueStore(PrefStore* managed_prefs,
83                  PrefStore* supervised_user_prefs,
84                  PrefStore* extension_prefs,
85                  PrefStore* standalone_browser_prefs,
86                  PrefStore* command_line_prefs,
87                  PrefStore* user_prefs,
88                  PrefStore* recommended_prefs,
89                  PrefStore* default_prefs,
90                  PrefNotifier* pref_notifier);
91 
92   PrefValueStore(const PrefValueStore&) = delete;
93   PrefValueStore& operator=(const PrefValueStore&) = delete;
94 
95   virtual ~PrefValueStore();
96 
97   // Creates a clone of this PrefValueStore with PrefStores overwritten
98   // by the parameters passed, if unequal NULL.
99   //
100   // The new PrefValueStore is passed the |delegate| in its constructor.
101   std::unique_ptr<PrefValueStore> CloneAndSpecialize(
102       PrefStore* managed_prefs,
103       PrefStore* supervised_user_prefs,
104       PrefStore* extension_prefs,
105       PrefStore* standalone_browser_prefs,
106       PrefStore* command_line_prefs,
107       PrefStore* user_prefs,
108       PrefStore* recommended_prefs,
109       PrefStore* default_prefs,
110       PrefNotifier* pref_notifier);
111 
112   // Returns the pref store type identifying the source that controls the
113   // Preference identified by |name|. If none of the sources has a value,
114   // INVALID_STORE is returned. In practice, the default PrefStore
115   // should always have a value for any registered preferencem, so INVALID_STORE
116   // indicates an error.
117   PrefStoreType ControllingPrefStoreForPref(const std::string& name) const;
118 
119   // Gets the value for the given preference name that has the specified value
120   // type. Values stored in a PrefStore that have the matching |name| but
121   // a non-matching |type| are silently skipped. Returns true if a valid value
122   // was found in any of the available PrefStores. Most callers should use
123   // Preference::GetValue() instead of calling this method directly.
124   bool GetValue(std::string_view name,
125                 base::Value::Type type,
126                 const base::Value** out_value) const;
127 
128   // Gets the recommended value for the given preference name that has the
129   // specified value type. A value stored in the recommended PrefStore that has
130   // the matching |name| but a non-matching |type| is silently ignored. Returns
131   // true if a valid value was found. Most callers should use
132   // Preference::GetRecommendedValue() instead of calling this method directly.
133   bool GetRecommendedValue(const std::string& name,
134                            base::Value::Type type,
135                            const base::Value** out_value) const;
136 
137   // These methods return true if a preference with the given name is in the
138   // indicated pref store, even if that value is currently being overridden by
139   // a higher-priority source.
140   bool PrefValueInManagedStore(const std::string& name) const;
141   bool PrefValueInSupervisedStore(const std::string& name) const;
142   bool PrefValueInExtensionStore(const std::string& name) const;
143   bool PrefValueInUserStore(const std::string& name) const;
144   bool PrefValueInStandaloneBrowserStore(const std::string& name) const;
145 
146   // These methods return true if a preference with the given name is actually
147   // being controlled by the indicated pref store and not being overridden by
148   // a higher-priority source.
149   bool PrefValueFromExtensionStore(const std::string& name) const;
150   bool PrefValueFromUserStore(const std::string& name) const;
151   bool PrefValueFromRecommendedStore(const std::string& name) const;
152   bool PrefValueFromDefaultStore(const std::string& name) const;
153   bool PrefValueFromStandaloneBrowserStore(const std::string& name) const;
154 
155   // Check whether a Preference value is modifiable by the user, i.e. whether
156   // there is no higher-priority source controlling it.
157   bool PrefValueUserModifiable(const std::string& name) const;
158 
159   // Check whether a Preference value is modifiable by an extension, i.e.
160   // whether there is no higher-priority source controlling it.
161   bool PrefValueExtensionModifiable(const std::string& name) const;
162 
163   // Check whether a Preference value is modifiable by a standalone browser
164   // (lacros), i.e. whether there is no higher-priority source controlling it.
165   bool PrefValueStandaloneBrowserModifiable(const std::string& name) const;
166 
167   // Update the command line PrefStore with |command_line_prefs|.
168   void UpdateCommandLinePrefStore(PrefStore* command_line_prefs);
169 
170   bool IsInitializationComplete() const;
171 
172  private:
173   // Keeps a PrefStore reference on behalf of the PrefValueStore and monitors
174   // the PrefStore for changes, forwarding notifications to PrefValueStore. This
175   // indirection is here for the sake of disambiguating notifications from the
176   // individual PrefStores.
177   class PrefStoreKeeper : public PrefStore::Observer {
178    public:
179     PrefStoreKeeper();
180 
181     PrefStoreKeeper(const PrefStoreKeeper&) = delete;
182     PrefStoreKeeper& operator=(const PrefStoreKeeper&) = delete;
183 
184     ~PrefStoreKeeper() override;
185 
186     // Takes ownership of |pref_store|.
187     void Initialize(PrefValueStore* store,
188                     PrefStore* pref_store,
189                     PrefStoreType type);
190 
store()191     PrefStore* store() { return pref_store_.get(); }
store()192     const PrefStore* store() const { return pref_store_.get(); }
193 
194    private:
195     // PrefStore::Observer implementation.
196     void OnPrefValueChanged(std::string_view key) override;
197     void OnInitializationCompleted(bool succeeded) override;
198 
199     // PrefValueStore this keeper is part of.
200     raw_ptr<PrefValueStore> pref_value_store_;
201 
202     // The PrefStore managed by this keeper.
203     scoped_refptr<PrefStore> pref_store_;
204 
205     // Type of the pref store.
206     PrefStoreType type_;
207   };
208 
209   typedef std::map<std::string, base::Value::Type> PrefTypeMap;
210 
211   // Returns true if the preference with the given name has a value in the
212   // given PrefStoreType, of the same value type as the preference was
213   // registered with.
214   bool PrefValueInStore(const std::string& name, PrefStoreType store) const;
215 
216   // Returns true if a preference has an explicit value in any of the
217   // stores in the range specified by |first_checked_store| and
218   // |last_checked_store|, even if that value is currently being
219   // overridden by a higher-priority store.
220   bool PrefValueInStoreRange(const std::string& name,
221                              PrefStoreType first_checked_store,
222                              PrefStoreType last_checked_store) const;
223 
224   // Get a value from the specified |store|.
225   bool GetValueFromStore(std::string_view name,
226                          PrefStoreType store,
227                          const base::Value** out_value) const;
228 
229   // Get a value from the specified |store| if its |type| matches.
230   bool GetValueFromStoreWithType(std::string_view name,
231                                  base::Value::Type type,
232                                  PrefStoreType store,
233                                  const base::Value** out_value) const;
234 
235   // Called upon changes in individual pref stores in order to determine whether
236   // the user-visible pref value has changed. Triggers the change notification
237   // if the effective value of the preference has changed, or if the store
238   // controlling the pref has changed.
239   void NotifyPrefChanged(std::string_view, PrefStoreType new_store);
240 
241   // Called from the PrefStoreKeeper implementation when a pref value for |key|
242   // changed in the pref store for |type|.
243   void OnPrefValueChanged(PrefStoreType type, std::string_view key);
244 
245   // Handle the event that the store for |type| has completed initialization.
246   void OnInitializationCompleted(PrefStoreType type, bool succeeded);
247 
248   // Initializes a pref store keeper. Sets up a PrefStoreKeeper that will take
249   // ownership of the passed |pref_store|.
250   void InitPrefStore(PrefStoreType type, PrefStore* pref_store);
251 
252   // Checks whether initialization is completed and tells the notifier if that
253   // is the case.
254   void CheckInitializationCompleted();
255 
256   // Get the PrefStore pointer for the given type. May return NULL if there is
257   // no PrefStore for that type.
GetPrefStore(PrefStoreType type)258   PrefStore* GetPrefStore(PrefStoreType type) {
259     return pref_stores_[type].store();
260   }
GetPrefStore(PrefStoreType type)261   const PrefStore* GetPrefStore(PrefStoreType type) const {
262     return pref_stores_[type].store();
263   }
264 
265   // Keeps the PrefStore references in order of precedence.
266   std::array<PrefStoreKeeper, PREF_STORE_TYPE_MAX + 1> pref_stores_;
267 
268   // Used for generating notifications. This is a weak reference,
269   // since the notifier is owned by the corresponding PrefService.
270   raw_ptr<PrefNotifier> pref_notifier_;
271 
272   // A mapping of preference names to their registered types.
273   PrefTypeMap pref_types_;
274 
275   // True if not all of the PrefStores were initialized successfully.
276   bool initialization_failed_;
277 };
278 
279 namespace std {
280 
281 template <>
282 struct hash<PrefValueStore::PrefStoreType> {
283   size_t operator()(PrefValueStore::PrefStoreType type) const {
284     return std::hash<
285         std::underlying_type<PrefValueStore::PrefStoreType>::type>()(type);
286   }
287 };
288 
289 }  // namespace std
290 
291 #endif  // COMPONENTS_PREFS_PREF_VALUE_STORE_H_
292