Bug 1842773 - Part 5: Add ArrayBuffer.prototype.{maxByteLength,resizable} getters...
[gecko.git] / modules / libpref / Preferences.h
blob81c99590da4385420e44dcc4aa436bd4a412a59c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // Documentation for libpref is in modules/libpref/docs/index.rst.
9 #ifndef mozilla_Preferences_h
10 #define mozilla_Preferences_h
12 #ifndef MOZILLA_INTERNAL_API
13 # error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)."
14 #endif
16 #include "mozilla/Atomics.h"
17 #include "mozilla/MemoryReporting.h"
18 #include "mozilla/StaticPtr.h"
19 #include "nsCOMPtr.h"
20 #include "nsIObserver.h"
21 #include "nsIPrefBranch.h"
22 #include "nsIPrefService.h"
23 #include "nsString.h"
24 #include "nsTArray.h"
25 #include "nsWeakReference.h"
26 #include "nsXULAppAPI.h"
27 #include <atomic>
28 #include <functional>
30 class nsIFile;
32 // The callback function will get passed the pref name which triggered the call
33 // and the void* data which was passed to the registered callback function.
34 typedef void (*PrefChangedFunc)(const char* aPref, void* aData);
36 class nsPrefBranch;
38 namespace mozilla {
40 struct RegisterCallbacksInternal;
42 void UnloadPrefsModule();
44 class PreferenceServiceReporter;
46 namespace dom {
47 class Pref;
48 class PrefValue;
49 } // namespace dom
51 namespace ipc {
52 class FileDescriptor;
53 } // namespace ipc
55 struct PrefsSizes;
57 // Xlib.h defines Bool as a macro constant. Don't try to define this enum if
58 // it's already been included.
59 #ifndef Bool
61 // Keep this in sync with PrefType in parser/src/lib.rs.
62 enum class PrefType : uint8_t {
63 None = 0, // only used when neither the default nor user value is set
64 String = 1,
65 Int = 2,
66 Bool = 3,
69 #endif
71 #ifdef XP_UNIX
72 // We need to send two shared memory descriptors to every child process:
74 // 1) A read-only/write-protected snapshot of the initial state of the
75 // preference database. This memory is shared between all processes, and
76 // therefore cannot be modified once it has been created.
78 // 2) A set of changes on top of the snapshot, containing the current values of
79 // all preferences which have changed since it was created.
81 // Since the second set will be different for every process, and the first set
82 // cannot be modified, it is unfortunately not possible to combine them into a
83 // single file descriptor.
85 // XXX: bug 1440207 is about improving how fixed fds such as this are used.
86 static const int kPrefsFileDescriptor = 8;
87 static const int kPrefMapFileDescriptor = 9;
88 #endif
90 // Keep this in sync with PrefType in parser/src/lib.rs.
91 enum class PrefValueKind : uint8_t { Default, User };
93 class Preferences final : public nsIPrefService,
94 public nsIObserver,
95 public nsIPrefBranch,
96 public nsSupportsWeakReference {
97 friend class ::nsPrefBranch;
99 public:
100 NS_DECL_THREADSAFE_ISUPPORTS
101 NS_DECL_NSIPREFSERVICE
102 NS_FORWARD_NSIPREFBRANCH(mRootBranch->)
103 NS_DECL_NSIOBSERVER
105 Preferences();
107 // Returns true if the Preferences service is available, false otherwise.
108 static bool IsServiceAvailable();
110 // Initialize user prefs from prefs.js/user.js
111 static void InitializeUserPrefs();
112 static void FinishInitializingUserPrefs();
114 // Returns the singleton instance which is addreffed.
115 static already_AddRefed<Preferences> GetInstanceForService();
117 // Finallizes global members.
118 static void Shutdown();
120 // Returns shared pref service instance NOTE: not addreffed.
121 static nsIPrefService* GetService() {
122 NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
123 return sPreferences;
126 // Returns shared pref branch instance. NOTE: not addreffed.
127 static nsIPrefBranch* GetRootBranch(
128 PrefValueKind aKind = PrefValueKind::User) {
129 NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
130 return (aKind == PrefValueKind::Default) ? sPreferences->mDefaultRootBranch
131 : sPreferences->mRootBranch;
134 // Gets the type of the pref.
135 static int32_t GetType(const char* aPrefName);
137 // Fallible value getters. When `aKind` is `User` they will get the user
138 // value if possible, and fall back to the default value otherwise.
139 static nsresult GetBool(const char* aPrefName, bool* aResult,
140 PrefValueKind aKind = PrefValueKind::User);
141 static nsresult GetInt(const char* aPrefName, int32_t* aResult,
142 PrefValueKind aKind = PrefValueKind::User);
143 static nsresult GetUint(const char* aPrefName, uint32_t* aResult,
144 PrefValueKind aKind = PrefValueKind::User) {
145 return GetInt(aPrefName, reinterpret_cast<int32_t*>(aResult), aKind);
147 static nsresult GetFloat(const char* aPrefName, float* aResult,
148 PrefValueKind aKind = PrefValueKind::User);
149 static nsresult GetCString(const char* aPrefName, nsACString& aResult,
150 PrefValueKind aKind = PrefValueKind::User);
151 static nsresult GetString(const char* aPrefName, nsAString& aResult,
152 PrefValueKind aKind = PrefValueKind::User);
153 static nsresult GetLocalizedCString(
154 const char* aPrefName, nsACString& aResult,
155 PrefValueKind aKind = PrefValueKind::User);
156 static nsresult GetLocalizedString(const char* aPrefName, nsAString& aResult,
157 PrefValueKind aKind = PrefValueKind::User);
158 static nsresult GetComplex(const char* aPrefName, const nsIID& aType,
159 void** aResult,
160 PrefValueKind aKind = PrefValueKind::User);
162 // Infallible getters of user or default values, with fallback results on
163 // failure. When `aKind` is `User` they will get the user value if possible,
164 // and fall back to the default value otherwise.
165 static bool GetBool(const char* aPrefName, bool aFallback = false,
166 PrefValueKind aKind = PrefValueKind::User);
167 static int32_t GetInt(const char* aPrefName, int32_t aFallback = 0,
168 PrefValueKind aKind = PrefValueKind::User);
169 static uint32_t GetUint(const char* aPrefName, uint32_t aFallback = 0,
170 PrefValueKind aKind = PrefValueKind::User);
171 static float GetFloat(const char* aPrefName, float aFallback = 0.0f,
172 PrefValueKind aKind = PrefValueKind::User);
174 // Value setters. These fail if run outside the parent process.
176 static nsresult SetBool(const char* aPrefName, bool aValue,
177 PrefValueKind aKind = PrefValueKind::User);
178 static nsresult SetInt(const char* aPrefName, int32_t aValue,
179 PrefValueKind aKind = PrefValueKind::User);
180 static nsresult SetCString(const char* aPrefName, const nsACString& aValue,
181 PrefValueKind aKind = PrefValueKind::User);
183 static nsresult SetUint(const char* aPrefName, uint32_t aValue,
184 PrefValueKind aKind = PrefValueKind::User) {
185 return SetInt(aPrefName, static_cast<int32_t>(aValue), aKind);
188 static nsresult SetFloat(const char* aPrefName, float aValue,
189 PrefValueKind aKind = PrefValueKind::User) {
190 nsAutoCString value;
191 value.AppendFloat(aValue);
192 return SetCString(aPrefName, value, aKind);
195 static nsresult SetCString(const char* aPrefName, const char* aValue,
196 PrefValueKind aKind = PrefValueKind::User) {
197 return Preferences::SetCString(aPrefName, nsDependentCString(aValue),
198 aKind);
201 static nsresult SetString(const char* aPrefName, const char16ptr_t aValue,
202 PrefValueKind aKind = PrefValueKind::User) {
203 return Preferences::SetCString(aPrefName, NS_ConvertUTF16toUTF8(aValue),
204 aKind);
207 static nsresult SetString(const char* aPrefName, const nsAString& aValue,
208 PrefValueKind aKind = PrefValueKind::User) {
209 return Preferences::SetCString(aPrefName, NS_ConvertUTF16toUTF8(aValue),
210 aKind);
213 static nsresult SetComplex(const char* aPrefName, const nsIID& aType,
214 nsISupports* aValue,
215 PrefValueKind aKind = PrefValueKind::User);
217 static nsresult Lock(const char* aPrefName);
218 static nsresult Unlock(const char* aPrefName);
219 static bool IsLocked(const char* aPrefName);
220 static bool IsSanitized(const char* aPrefName);
222 // Clears user set pref. Fails if run outside the parent process.
223 static nsresult ClearUser(const char* aPrefName);
225 // Whether the pref has a user value or not.
226 static bool HasUserValue(const char* aPref);
228 // Whether the pref has a user value or not.
229 static bool HasDefaultValue(const char* aPref);
231 // Adds/Removes the observer for the root pref branch. See nsIPrefBranch.idl
232 // for details.
233 static nsresult AddStrongObserver(nsIObserver* aObserver,
234 const nsACString& aPref);
235 static nsresult AddWeakObserver(nsIObserver* aObserver,
236 const nsACString& aPref);
237 static nsresult RemoveObserver(nsIObserver* aObserver,
238 const nsACString& aPref);
240 template <int N>
241 static nsresult AddStrongObserver(nsIObserver* aObserver,
242 const char (&aPref)[N]) {
243 return AddStrongObserver(aObserver, nsLiteralCString(aPref));
245 template <int N>
246 static nsresult AddWeakObserver(nsIObserver* aObserver,
247 const char (&aPref)[N]) {
248 return AddWeakObserver(aObserver, nsLiteralCString(aPref));
250 template <int N>
251 static nsresult RemoveObserver(nsIObserver* aObserver,
252 const char (&aPref)[N]) {
253 return RemoveObserver(aObserver, nsLiteralCString(aPref));
256 // Adds/Removes two or more observers for the root pref branch. Pass to
257 // aPrefs an array of const char* whose last item is nullptr.
258 // Note: All preference strings *must* be statically-allocated string
259 // literals.
260 static nsresult AddStrongObservers(nsIObserver* aObserver,
261 const char* const* aPrefs);
262 static nsresult AddWeakObservers(nsIObserver* aObserver,
263 const char* const* aPrefs);
264 static nsresult RemoveObservers(nsIObserver* aObserver,
265 const char* const* aPrefs);
267 // Registers/Unregisters the callback function for the aPref.
268 template <typename T = void>
269 static nsresult RegisterCallback(PrefChangedFunc aCallback,
270 const nsACString& aPref,
271 T* aClosure = nullptr) {
272 return RegisterCallback(aCallback, aPref, aClosure, ExactMatch);
275 template <typename T = void>
276 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
277 const nsACString& aPref,
278 T* aClosure = nullptr) {
279 return UnregisterCallback(aCallback, aPref, aClosure, ExactMatch);
282 // Like RegisterCallback, but also calls the callback immediately for
283 // initialization.
284 template <typename T = void>
285 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
286 const nsACString& aPref,
287 T* aClosure = nullptr) {
288 return RegisterCallbackAndCall(aCallback, aPref, aClosure, ExactMatch);
291 // Like RegisterCallback, but registers a callback for a prefix of multiple
292 // pref names, not a single pref name.
293 template <typename T = void>
294 static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
295 const nsACString& aPref,
296 T* aClosure = nullptr) {
297 return RegisterCallback(aCallback, aPref, aClosure, PrefixMatch);
300 // Like RegisterPrefixCallback, but also calls the callback immediately for
301 // initialization.
302 template <typename T = void>
303 static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
304 const nsACString& aPref,
305 T* aClosure = nullptr) {
306 return RegisterCallbackAndCall(aCallback, aPref, aClosure, PrefixMatch);
309 // Unregister a callback registered with RegisterPrefixCallback or
310 // RegisterPrefixCallbackAndCall.
311 template <typename T = void>
312 static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
313 const nsACString& aPref,
314 T* aClosure = nullptr) {
315 return UnregisterCallback(aCallback, aPref, aClosure, PrefixMatch);
318 // Variants of the above which register a single callback to handle multiple
319 // preferences.
321 // The array of preference names must be null terminated. It may be
322 // dynamically allocated, but the caller is responsible for keeping it alive
323 // until the callback is unregistered.
325 // Also note that the exact same aPrefs pointer must be passed to the
326 // Unregister call as was passed to the Register call.
327 template <typename T = void>
328 static nsresult RegisterCallbacks(PrefChangedFunc aCallback,
329 const char* const* aPrefs,
330 T* aClosure = nullptr) {
331 return RegisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch);
333 static nsresult RegisterCallbacksAndCall(PrefChangedFunc aCallback,
334 const char* const* aPrefs,
335 void* aClosure = nullptr);
336 template <typename T = void>
337 static nsresult UnregisterCallbacks(PrefChangedFunc aCallback,
338 const char* const* aPrefs,
339 T* aClosure = nullptr) {
340 return UnregisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch);
342 template <typename T = void>
343 static nsresult RegisterPrefixCallbacks(PrefChangedFunc aCallback,
344 const char* const* aPrefs,
345 T* aClosure = nullptr) {
346 return RegisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch);
348 template <typename T = void>
349 static nsresult UnregisterPrefixCallbacks(PrefChangedFunc aCallback,
350 const char* const* aPrefs,
351 T* aClosure = nullptr) {
352 return UnregisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch);
355 template <int N, typename T = void>
356 static nsresult RegisterCallback(PrefChangedFunc aCallback,
357 const char (&aPref)[N],
358 T* aClosure = nullptr) {
359 return RegisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
360 ExactMatch);
363 template <int N, typename T = void>
364 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
365 const char (&aPref)[N],
366 T* aClosure = nullptr) {
367 return UnregisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
368 ExactMatch);
371 template <int N, typename T = void>
372 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
373 const char (&aPref)[N],
374 T* aClosure = nullptr) {
375 return RegisterCallbackAndCall(aCallback, nsLiteralCString(aPref), aClosure,
376 ExactMatch);
379 template <int N, typename T = void>
380 static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
381 const char (&aPref)[N],
382 T* aClosure = nullptr) {
383 return RegisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
384 PrefixMatch);
387 template <int N, typename T = void>
388 static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
389 const char (&aPref)[N],
390 T* aClosure = nullptr) {
391 return RegisterCallbackAndCall(aCallback, nsLiteralCString(aPref), aClosure,
392 PrefixMatch);
395 template <int N, typename T = void>
396 static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
397 const char (&aPref)[N],
398 T* aClosure = nullptr) {
399 return UnregisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
400 PrefixMatch);
403 // When a content process is created these methods are used to pass changed
404 // prefs in bulk from the parent process, via shared memory.
405 static void SerializePreferences(nsCString& aStr,
406 bool aIsDestinationWebContentProcess);
407 static void DeserializePreferences(char* aStr, size_t aPrefsLen);
409 static mozilla::ipc::FileDescriptor EnsureSnapshot(size_t* aSize);
410 static void InitSnapshot(const mozilla::ipc::FileDescriptor&, size_t aSize);
412 // When a single pref is changed in the parent process, these methods are
413 // used to pass the update to content processes.
414 static void GetPreference(dom::Pref* aPref,
415 const GeckoProcessType aDestinationProcessType,
416 const nsACString& aDestinationRemoteType);
417 static void SetPreference(const dom::Pref& aPref);
419 #ifdef DEBUG
420 static bool ArePrefsInitedInContentProcess();
421 #endif
423 static void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
424 PrefsSizes& aSizes);
426 static void HandleDirty();
428 // Explicitly choosing synchronous or asynchronous (if allowed) preferences
429 // file write. Only for the default file. The guarantee for the "blocking"
430 // is that when it returns, the file on disk reflect the current state of
431 // preferences.
432 nsresult SavePrefFileBlocking();
433 nsresult SavePrefFileAsynchronous();
435 // If this is false, only blocking writes, on main thread are allowed.
436 bool AllowOffMainThreadSave();
438 private:
439 virtual ~Preferences();
441 nsresult NotifyServiceObservers(const char* aSubject);
443 // Loads the prefs.js file from the profile, or creates a new one. Returns
444 // the prefs file if successful, or nullptr on failure.
445 already_AddRefed<nsIFile> ReadSavedPrefs();
447 // Loads the user.js file from the profile if present.
448 void ReadUserOverridePrefs();
450 nsresult MakeBackupPrefFile(nsIFile* aFile);
452 // Default pref file save can be blocking or not.
453 enum class SaveMethod { Blocking, Asynchronous };
455 // Off main thread is only respected for the default aFile value (nullptr).
456 nsresult SavePrefFileInternal(nsIFile* aFile, SaveMethod aSaveMethod);
457 nsresult WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod);
459 nsresult ResetUserPrefs();
461 // Helpers for implementing
462 // Register(Prefix)Callback/Unregister(Prefix)Callback.
463 public:
464 // Public so the ValueObserver classes can use it.
465 enum MatchKind {
466 PrefixMatch,
467 ExactMatch,
470 private:
471 static void SetupTelemetryPref();
472 static nsresult InitInitialObjects(bool aIsStartup);
474 friend struct Internals;
476 static nsresult RegisterCallback(PrefChangedFunc aCallback,
477 const nsACString& aPref, void* aClosure,
478 MatchKind aMatchKind,
479 bool aIsPriority = false);
480 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
481 const nsACString& aPref, void* aClosure,
482 MatchKind aMatchKind);
483 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
484 const nsACString& aPref,
485 void* aClosure, MatchKind aMatchKind);
487 static nsresult RegisterCallbacks(PrefChangedFunc aCallback,
488 const char* const* aPrefs, void* aClosure,
489 MatchKind aMatchKind);
490 static nsresult UnregisterCallbacks(PrefChangedFunc aCallback,
491 const char* const* aPrefs, void* aClosure,
492 MatchKind aMatchKind);
494 template <typename T>
495 static nsresult RegisterCallbackImpl(PrefChangedFunc aCallback, T& aPref,
496 void* aClosure, MatchKind aMatchKind,
497 bool aIsPriority = false);
498 template <typename T>
499 static nsresult UnregisterCallbackImpl(PrefChangedFunc aCallback, T& aPref,
500 void* aClosure, MatchKind aMatchKind);
502 static nsresult RegisterCallback(PrefChangedFunc aCallback, const char* aPref,
503 void* aClosure, MatchKind aMatchKind,
504 bool aIsPriority = false) {
505 return RegisterCallback(aCallback, nsDependentCString(aPref), aClosure,
506 aMatchKind, aIsPriority);
508 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
509 const char* aPref, void* aClosure,
510 MatchKind aMatchKind) {
511 return UnregisterCallback(aCallback, nsDependentCString(aPref), aClosure,
512 aMatchKind);
514 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
515 const char* aPref, void* aClosure,
516 MatchKind aMatchKind) {
517 return RegisterCallbackAndCall(aCallback, nsDependentCString(aPref),
518 aClosure, aMatchKind);
521 private:
522 nsCOMPtr<nsIFile> mCurrentFile;
523 bool mDirty = false;
524 bool mProfileShutdown = false;
525 // We wait a bit after prefs are dirty before writing them. In this period,
526 // mDirty and mSavePending will both be true.
527 bool mSavePending = false;
529 nsCOMPtr<nsIPrefBranch> mRootBranch;
530 nsCOMPtr<nsIPrefBranch> mDefaultRootBranch;
532 static StaticRefPtr<Preferences> sPreferences;
533 static bool sShutdown;
535 // Init static members. Returns true on success.
536 static bool InitStaticMembers();
539 extern Atomic<bool, Relaxed> sOmitBlocklistedPrefValues;
540 extern Atomic<bool, Relaxed> sCrashOnBlocklistedPref;
542 bool IsPreferenceSanitized(const char* aPref);
544 const char kFissionEnforceBlockList[] =
545 "fission.enforceBlocklistedPrefsInSubprocesses";
546 const char kFissionOmitBlockListValues[] =
547 "fission.omitBlocklistedPrefsInSubprocesses";
549 void OnFissionBlocklistPrefChange(const char* aPref, void* aData);
551 } // namespace mozilla
553 #endif // mozilla_Preferences_h