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