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