Bug 1826566 [wpt PR 39395] - Only merge table columns that have no cell edges., a...
[gecko.git] / modules / libpref / Preferences.h
blob7540755422709291ba7e1ca15be3d48986f0ed70
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** aPrefs);
262 static nsresult AddWeakObservers(nsIObserver* aObserver, const char** aPrefs);
263 static nsresult RemoveObservers(nsIObserver* aObserver, const char** aPrefs);
265 // Registers/Unregisters the callback function for the aPref.
266 template <typename T = void>
267 static nsresult RegisterCallback(PrefChangedFunc aCallback,
268 const nsACString& aPref,
269 T* aClosure = nullptr) {
270 return RegisterCallback(aCallback, aPref, aClosure, ExactMatch);
273 template <typename T = void>
274 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
275 const nsACString& aPref,
276 T* aClosure = nullptr) {
277 return UnregisterCallback(aCallback, aPref, aClosure, ExactMatch);
280 // Like RegisterCallback, but also calls the callback immediately for
281 // initialization.
282 template <typename T = void>
283 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
284 const nsACString& aPref,
285 T* aClosure = nullptr) {
286 return RegisterCallbackAndCall(aCallback, aPref, aClosure, ExactMatch);
289 // Like RegisterCallback, but registers a callback for a prefix of multiple
290 // pref names, not a single pref name.
291 template <typename T = void>
292 static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
293 const nsACString& aPref,
294 T* aClosure = nullptr) {
295 return RegisterCallback(aCallback, aPref, aClosure, PrefixMatch);
298 // Like RegisterPrefixCallback, but also calls the callback immediately for
299 // initialization.
300 template <typename T = void>
301 static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
302 const nsACString& aPref,
303 T* aClosure = nullptr) {
304 return RegisterCallbackAndCall(aCallback, aPref, aClosure, PrefixMatch);
307 // Unregister a callback registered with RegisterPrefixCallback or
308 // RegisterPrefixCallbackAndCall.
309 template <typename T = void>
310 static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
311 const nsACString& aPref,
312 T* aClosure = nullptr) {
313 return UnregisterCallback(aCallback, aPref, aClosure, PrefixMatch);
316 // Variants of the above which register a single callback to handle multiple
317 // preferences.
319 // The array of preference names must be null terminated. It may be
320 // dynamically allocated, but the caller is responsible for keeping it alive
321 // until the callback is unregistered.
323 // Also note that the exact same aPrefs pointer must be passed to the
324 // Unregister call as was passed to the Register call.
325 template <typename T = void>
326 static nsresult RegisterCallbacks(PrefChangedFunc aCallback,
327 const char** aPrefs,
328 T* aClosure = nullptr) {
329 return RegisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch);
331 static nsresult RegisterCallbacksAndCall(PrefChangedFunc aCallback,
332 const char** aPrefs,
333 void* aClosure = nullptr);
334 template <typename T = void>
335 static nsresult UnregisterCallbacks(PrefChangedFunc aCallback,
336 const char** aPrefs,
337 T* aClosure = nullptr) {
338 return UnregisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch);
340 template <typename T = void>
341 static nsresult RegisterPrefixCallbacks(PrefChangedFunc aCallback,
342 const char** aPrefs,
343 T* aClosure = nullptr) {
344 return RegisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch);
346 template <typename T = void>
347 static nsresult UnregisterPrefixCallbacks(PrefChangedFunc aCallback,
348 const char** aPrefs,
349 T* aClosure = nullptr) {
350 return UnregisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch);
353 template <int N, typename T = void>
354 static nsresult RegisterCallback(PrefChangedFunc aCallback,
355 const char (&aPref)[N],
356 T* aClosure = nullptr) {
357 return RegisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
358 ExactMatch);
361 template <int N, typename T = void>
362 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
363 const char (&aPref)[N],
364 T* aClosure = nullptr) {
365 return UnregisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
366 ExactMatch);
369 template <int N, typename T = void>
370 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
371 const char (&aPref)[N],
372 T* aClosure = nullptr) {
373 return RegisterCallbackAndCall(aCallback, nsLiteralCString(aPref), aClosure,
374 ExactMatch);
377 template <int N, typename T = void>
378 static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
379 const char (&aPref)[N],
380 T* aClosure = nullptr) {
381 return RegisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
382 PrefixMatch);
385 template <int N, typename T = void>
386 static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
387 const char (&aPref)[N],
388 T* aClosure = nullptr) {
389 return RegisterCallbackAndCall(aCallback, nsLiteralCString(aPref), aClosure,
390 PrefixMatch);
393 template <int N, typename T = void>
394 static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
395 const char (&aPref)[N],
396 T* aClosure = nullptr) {
397 return UnregisterCallback(aCallback, nsLiteralCString(aPref), aClosure,
398 PrefixMatch);
401 // When a content process is created these methods are used to pass changed
402 // prefs in bulk from the parent process, via shared memory.
403 static void SerializePreferences(nsCString& aStr,
404 bool aIsDestinationWebContentProcess);
405 static void DeserializePreferences(char* aStr, size_t aPrefsLen);
407 static mozilla::ipc::FileDescriptor EnsureSnapshot(size_t* aSize);
408 static void InitSnapshot(const mozilla::ipc::FileDescriptor&, size_t aSize);
410 // When a single pref is changed in the parent process, these methods are
411 // used to pass the update to content processes.
412 static void GetPreference(dom::Pref* aPref,
413 const GeckoProcessType aDestinationProcessType,
414 const nsACString& aDestinationRemoteType);
415 static void SetPreference(const dom::Pref& aPref);
417 #ifdef DEBUG
418 static bool ArePrefsInitedInContentProcess();
419 #endif
421 static void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
422 PrefsSizes& aSizes);
424 static void HandleDirty();
426 // Explicitly choosing synchronous or asynchronous (if allowed) preferences
427 // file write. Only for the default file. The guarantee for the "blocking"
428 // is that when it returns, the file on disk reflect the current state of
429 // preferences.
430 nsresult SavePrefFileBlocking();
431 nsresult SavePrefFileAsynchronous();
433 // If this is false, only blocking writes, on main thread are allowed.
434 bool AllowOffMainThreadSave();
436 private:
437 virtual ~Preferences();
439 nsresult NotifyServiceObservers(const char* aSubject);
441 // Loads the prefs.js file from the profile, or creates a new one. Returns
442 // the prefs file if successful, or nullptr on failure.
443 already_AddRefed<nsIFile> ReadSavedPrefs();
445 // Loads the user.js file from the profile if present.
446 void ReadUserOverridePrefs();
448 nsresult MakeBackupPrefFile(nsIFile* aFile);
450 // Default pref file save can be blocking or not.
451 enum class SaveMethod { Blocking, Asynchronous };
453 // Off main thread is only respected for the default aFile value (nullptr).
454 nsresult SavePrefFileInternal(nsIFile* aFile, SaveMethod aSaveMethod);
455 nsresult WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod);
457 nsresult ResetUserPrefs();
459 // Helpers for implementing
460 // Register(Prefix)Callback/Unregister(Prefix)Callback.
461 public:
462 // Public so the ValueObserver classes can use it.
463 enum MatchKind {
464 PrefixMatch,
465 ExactMatch,
468 private:
469 static void SetupTelemetryPref();
470 static nsresult InitInitialObjects(bool aIsStartup);
472 friend struct Internals;
474 static nsresult RegisterCallback(PrefChangedFunc aCallback,
475 const nsACString& aPref, void* aClosure,
476 MatchKind aMatchKind,
477 bool aIsPriority = false);
478 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
479 const nsACString& aPref, void* aClosure,
480 MatchKind aMatchKind);
481 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
482 const nsACString& aPref,
483 void* aClosure, MatchKind aMatchKind);
485 static nsresult RegisterCallbacks(PrefChangedFunc aCallback,
486 const char** aPrefs, void* aClosure,
487 MatchKind aMatchKind);
488 static nsresult UnregisterCallbacks(PrefChangedFunc aCallback,
489 const char** aPrefs, void* aClosure,
490 MatchKind aMatchKind);
492 template <typename T>
493 static nsresult RegisterCallbackImpl(PrefChangedFunc aCallback, T& aPref,
494 void* aClosure, MatchKind aMatchKind,
495 bool aIsPriority = false);
496 template <typename T>
497 static nsresult UnregisterCallbackImpl(PrefChangedFunc aCallback, T& aPref,
498 void* aClosure, MatchKind aMatchKind);
500 static nsresult RegisterCallback(PrefChangedFunc aCallback, const char* aPref,
501 void* aClosure, MatchKind aMatchKind,
502 bool aIsPriority = false) {
503 return RegisterCallback(aCallback, nsDependentCString(aPref), aClosure,
504 aMatchKind, aIsPriority);
506 static nsresult UnregisterCallback(PrefChangedFunc aCallback,
507 const char* aPref, void* aClosure,
508 MatchKind aMatchKind) {
509 return UnregisterCallback(aCallback, nsDependentCString(aPref), aClosure,
510 aMatchKind);
512 static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
513 const char* aPref, void* aClosure,
514 MatchKind aMatchKind) {
515 return RegisterCallbackAndCall(aCallback, nsDependentCString(aPref),
516 aClosure, aMatchKind);
519 private:
520 nsCOMPtr<nsIFile> mCurrentFile;
521 bool mDirty = false;
522 bool mProfileShutdown = false;
523 // We wait a bit after prefs are dirty before writing them. In this period,
524 // mDirty and mSavePending will both be true.
525 bool mSavePending = false;
527 nsCOMPtr<nsIPrefBranch> mRootBranch;
528 nsCOMPtr<nsIPrefBranch> mDefaultRootBranch;
530 static StaticRefPtr<Preferences> sPreferences;
531 static bool sShutdown;
533 // Init static members. Returns true on success.
534 static bool InitStaticMembers();
537 extern Atomic<bool, Relaxed> sOmitBlocklistedPrefValues;
538 extern Atomic<bool, Relaxed> sCrashOnBlocklistedPref;
540 bool IsPreferenceSanitized(const char* aPref);
542 const char kFissionEnforceBlockList[] =
543 "fission.enforceBlocklistedPrefsInSubprocesses";
544 const char kFissionOmitBlockListValues[] =
545 "fission.omitBlocklistedPrefsInSubprocesses";
547 void OnFissionBlocklistPrefChange(const char* aPref, void* aData);
549 } // namespace mozilla
551 #endif // mozilla_Preferences_h