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)."
16 #include "mozilla/Atomics.h"
17 #include "mozilla/MemoryReporting.h"
18 #include "mozilla/MozPromise.h"
19 #include "mozilla/StaticPtr.h"
21 #include "nsIObserver.h"
22 #include "nsIPrefBranch.h"
23 #include "nsIPrefService.h"
26 #include "nsWeakReference.h"
27 #include "nsXULAppAPI.h"
33 // The callback function will get passed the pref name which triggered the call
34 // and the void* data which was passed to the registered callback function.
35 typedef void (*PrefChangedFunc
)(const char* aPref
, void* aData
);
41 struct RegisterCallbacksInternal
;
43 void UnloadPrefsModule();
45 class PreferenceServiceReporter
;
58 // Xlib.h defines Bool as a macro constant. Don't try to define this enum if
59 // it's already been included.
62 // Keep this in sync with PrefType in parser/src/lib.rs.
63 enum class PrefType
: uint8_t {
64 None
= 0, // only used when neither the default nor user value is set
73 // We need to send two shared memory descriptors to every child process:
75 // 1) A read-only/write-protected snapshot of the initial state of the
76 // preference database. This memory is shared between all processes, and
77 // therefore cannot be modified once it has been created.
79 // 2) A set of changes on top of the snapshot, containing the current values of
80 // all preferences which have changed since it was created.
82 // Since the second set will be different for every process, and the first set
83 // cannot be modified, it is unfortunately not possible to combine them into a
84 // single file descriptor.
86 // XXX: bug 1440207 is about improving how fixed fds such as this are used.
87 static const int kPrefsFileDescriptor
= 8;
88 static const int kPrefMapFileDescriptor
= 9;
91 // Keep this in sync with PrefType in parser/src/lib.rs.
92 enum class PrefValueKind
: uint8_t { Default
, User
};
94 class Preferences final
: public nsIPrefService
,
97 public nsSupportsWeakReference
{
98 friend class ::nsPrefBranch
;
101 using WritePrefFilePromise
= MozPromise
<bool, nsresult
, false>;
103 NS_DECL_THREADSAFE_ISUPPORTS
104 NS_DECL_NSIPREFSERVICE
105 NS_FORWARD_NSIPREFBRANCH(mRootBranch
->)
110 // Returns true if the Preferences service is available, false otherwise.
111 static bool IsServiceAvailable();
113 // Initialize user prefs from prefs.js/user.js
114 static void InitializeUserPrefs();
115 static void FinishInitializingUserPrefs();
117 // Returns the singleton instance which is addreffed.
118 static already_AddRefed
<Preferences
> GetInstanceForService();
120 // Finallizes global members.
121 static void Shutdown();
123 // Returns shared pref service instance NOTE: not addreffed.
124 static nsIPrefService
* GetService() {
125 NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
129 // Returns shared pref branch instance. NOTE: not addreffed.
130 static nsIPrefBranch
* GetRootBranch(
131 PrefValueKind aKind
= PrefValueKind::User
) {
132 NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
133 return (aKind
== PrefValueKind::Default
) ? sPreferences
->mDefaultRootBranch
134 : sPreferences
->mRootBranch
;
137 // Gets the type of the pref.
138 static int32_t GetType(const char* aPrefName
);
140 // Fallible value getters. When `aKind` is `User` they will get the user
141 // value if possible, and fall back to the default value otherwise.
142 static nsresult
GetBool(const char* aPrefName
, bool* aResult
,
143 PrefValueKind aKind
= PrefValueKind::User
);
144 static nsresult
GetInt(const char* aPrefName
, int32_t* aResult
,
145 PrefValueKind aKind
= PrefValueKind::User
);
146 static nsresult
GetUint(const char* aPrefName
, uint32_t* aResult
,
147 PrefValueKind aKind
= PrefValueKind::User
) {
148 return GetInt(aPrefName
, reinterpret_cast<int32_t*>(aResult
), aKind
);
150 static nsresult
GetFloat(const char* aPrefName
, float* aResult
,
151 PrefValueKind aKind
= PrefValueKind::User
);
152 static nsresult
GetCString(const char* aPrefName
, nsACString
& aResult
,
153 PrefValueKind aKind
= PrefValueKind::User
);
154 static nsresult
GetString(const char* aPrefName
, nsAString
& aResult
,
155 PrefValueKind aKind
= PrefValueKind::User
);
156 static nsresult
GetLocalizedCString(
157 const char* aPrefName
, nsACString
& aResult
,
158 PrefValueKind aKind
= PrefValueKind::User
);
159 static nsresult
GetLocalizedString(const char* aPrefName
, nsAString
& aResult
,
160 PrefValueKind aKind
= PrefValueKind::User
);
161 static nsresult
GetComplex(const char* aPrefName
, const nsIID
& aType
,
163 PrefValueKind aKind
= PrefValueKind::User
);
165 // Infallible getters of user or default values, with fallback results on
166 // failure. When `aKind` is `User` they will get the user value if possible,
167 // and fall back to the default value otherwise.
168 static bool GetBool(const char* aPrefName
, bool aFallback
= false,
169 PrefValueKind aKind
= PrefValueKind::User
);
170 static int32_t GetInt(const char* aPrefName
, int32_t aFallback
= 0,
171 PrefValueKind aKind
= PrefValueKind::User
);
172 static uint32_t GetUint(const char* aPrefName
, uint32_t aFallback
= 0,
173 PrefValueKind aKind
= PrefValueKind::User
);
174 static float GetFloat(const char* aPrefName
, float aFallback
= 0.0f
,
175 PrefValueKind aKind
= PrefValueKind::User
);
177 // Value setters. These fail if run outside the parent process.
179 static nsresult
SetBool(const char* aPrefName
, bool aValue
,
180 PrefValueKind aKind
= PrefValueKind::User
);
181 static nsresult
SetInt(const char* aPrefName
, int32_t aValue
,
182 PrefValueKind aKind
= PrefValueKind::User
);
183 static nsresult
SetCString(const char* aPrefName
, const nsACString
& aValue
,
184 PrefValueKind aKind
= PrefValueKind::User
);
186 static nsresult
SetUint(const char* aPrefName
, uint32_t aValue
,
187 PrefValueKind aKind
= PrefValueKind::User
) {
188 return SetInt(aPrefName
, static_cast<int32_t>(aValue
), aKind
);
191 static nsresult
SetFloat(const char* aPrefName
, float aValue
,
192 PrefValueKind aKind
= PrefValueKind::User
) {
194 value
.AppendFloat(aValue
);
195 return SetCString(aPrefName
, value
, aKind
);
198 static nsresult
SetCString(const char* aPrefName
, const char* aValue
,
199 PrefValueKind aKind
= PrefValueKind::User
) {
200 return Preferences::SetCString(aPrefName
, nsDependentCString(aValue
),
204 static nsresult
SetString(const char* aPrefName
, const char16ptr_t aValue
,
205 PrefValueKind aKind
= PrefValueKind::User
) {
206 return Preferences::SetCString(aPrefName
, NS_ConvertUTF16toUTF8(aValue
),
210 static nsresult
SetString(const char* aPrefName
, const nsAString
& aValue
,
211 PrefValueKind aKind
= PrefValueKind::User
) {
212 return Preferences::SetCString(aPrefName
, NS_ConvertUTF16toUTF8(aValue
),
216 static nsresult
SetComplex(const char* aPrefName
, const nsIID
& aType
,
218 PrefValueKind aKind
= PrefValueKind::User
);
220 static nsresult
Lock(const char* aPrefName
);
221 static nsresult
Unlock(const char* aPrefName
);
222 static bool IsLocked(const char* aPrefName
);
223 static bool IsSanitized(const char* aPrefName
);
225 // Clears user set pref. Fails if run outside the parent process.
226 static nsresult
ClearUser(const char* aPrefName
);
228 // Whether the pref has a user value or not.
229 static bool HasUserValue(const char* aPref
);
231 // Whether the pref has a user value or not.
232 static bool HasDefaultValue(const char* aPref
);
234 // Adds/Removes the observer for the root pref branch. See nsIPrefBranch.idl
236 static nsresult
AddStrongObserver(nsIObserver
* aObserver
,
237 const nsACString
& aPref
);
238 static nsresult
AddWeakObserver(nsIObserver
* aObserver
,
239 const nsACString
& aPref
);
240 static nsresult
RemoveObserver(nsIObserver
* aObserver
,
241 const nsACString
& aPref
);
244 static nsresult
AddStrongObserver(nsIObserver
* aObserver
,
245 const char (&aPref
)[N
]) {
246 return AddStrongObserver(aObserver
, nsLiteralCString(aPref
));
249 static nsresult
AddWeakObserver(nsIObserver
* aObserver
,
250 const char (&aPref
)[N
]) {
251 return AddWeakObserver(aObserver
, nsLiteralCString(aPref
));
254 static nsresult
RemoveObserver(nsIObserver
* aObserver
,
255 const char (&aPref
)[N
]) {
256 return RemoveObserver(aObserver
, nsLiteralCString(aPref
));
259 // Adds/Removes two or more observers for the root pref branch. Pass to
260 // aPrefs an array of const char* whose last item is nullptr.
261 // Note: All preference strings *must* be statically-allocated string
263 static nsresult
AddStrongObservers(nsIObserver
* aObserver
,
264 const char* const* aPrefs
);
265 static nsresult
AddWeakObservers(nsIObserver
* aObserver
,
266 const char* const* aPrefs
);
267 static nsresult
RemoveObservers(nsIObserver
* aObserver
,
268 const char* const* aPrefs
);
270 // Registers/Unregisters the callback function for the aPref.
271 template <typename T
= void>
272 static nsresult
RegisterCallback(PrefChangedFunc aCallback
,
273 const nsACString
& aPref
,
274 T
* aClosure
= nullptr) {
275 return RegisterCallback(aCallback
, aPref
, aClosure
, ExactMatch
);
278 template <typename T
= void>
279 static nsresult
UnregisterCallback(PrefChangedFunc aCallback
,
280 const nsACString
& aPref
,
281 T
* aClosure
= nullptr) {
282 return UnregisterCallback(aCallback
, aPref
, aClosure
, ExactMatch
);
285 // Like RegisterCallback, but also calls the callback immediately for
287 template <typename T
= void>
288 static nsresult
RegisterCallbackAndCall(PrefChangedFunc aCallback
,
289 const nsACString
& aPref
,
290 T
* aClosure
= nullptr) {
291 return RegisterCallbackAndCall(aCallback
, aPref
, aClosure
, ExactMatch
);
294 // Like RegisterCallback, but registers a callback for a prefix of multiple
295 // pref names, not a single pref name.
296 template <typename T
= void>
297 static nsresult
RegisterPrefixCallback(PrefChangedFunc aCallback
,
298 const nsACString
& aPref
,
299 T
* aClosure
= nullptr) {
300 return RegisterCallback(aCallback
, aPref
, aClosure
, PrefixMatch
);
303 // Like RegisterPrefixCallback, but also calls the callback immediately for
305 template <typename T
= void>
306 static nsresult
RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback
,
307 const nsACString
& aPref
,
308 T
* aClosure
= nullptr) {
309 return RegisterCallbackAndCall(aCallback
, aPref
, aClosure
, PrefixMatch
);
312 // Unregister a callback registered with RegisterPrefixCallback or
313 // RegisterPrefixCallbackAndCall.
314 template <typename T
= void>
315 static nsresult
UnregisterPrefixCallback(PrefChangedFunc aCallback
,
316 const nsACString
& aPref
,
317 T
* aClosure
= nullptr) {
318 return UnregisterCallback(aCallback
, aPref
, aClosure
, PrefixMatch
);
321 // Variants of the above which register a single callback to handle multiple
324 // The array of preference names must be null terminated. It may be
325 // dynamically allocated, but the caller is responsible for keeping it alive
326 // until the callback is unregistered.
328 // Also note that the exact same aPrefs pointer must be passed to the
329 // Unregister call as was passed to the Register call.
330 template <typename T
= void>
331 static nsresult
RegisterCallbacks(PrefChangedFunc aCallback
,
332 const char* const* aPrefs
,
333 T
* aClosure
= nullptr) {
334 return RegisterCallbacks(aCallback
, aPrefs
, aClosure
, ExactMatch
);
336 static nsresult
RegisterCallbacksAndCall(PrefChangedFunc aCallback
,
337 const char* const* aPrefs
,
338 void* aClosure
= nullptr);
339 template <typename T
= void>
340 static nsresult
UnregisterCallbacks(PrefChangedFunc aCallback
,
341 const char* const* aPrefs
,
342 T
* aClosure
= nullptr) {
343 return UnregisterCallbacks(aCallback
, aPrefs
, aClosure
, ExactMatch
);
345 template <typename T
= void>
346 static nsresult
RegisterPrefixCallbacks(PrefChangedFunc aCallback
,
347 const char* const* aPrefs
,
348 T
* aClosure
= nullptr) {
349 return RegisterCallbacks(aCallback
, aPrefs
, aClosure
, PrefixMatch
);
351 template <typename T
= void>
352 static nsresult
UnregisterPrefixCallbacks(PrefChangedFunc aCallback
,
353 const char* const* aPrefs
,
354 T
* aClosure
= nullptr) {
355 return UnregisterCallbacks(aCallback
, aPrefs
, aClosure
, PrefixMatch
);
358 template <int N
, typename T
= void>
359 static nsresult
RegisterCallback(PrefChangedFunc aCallback
,
360 const char (&aPref
)[N
],
361 T
* aClosure
= nullptr) {
362 return RegisterCallback(aCallback
, nsLiteralCString(aPref
), aClosure
,
366 template <int N
, typename T
= void>
367 static nsresult
UnregisterCallback(PrefChangedFunc aCallback
,
368 const char (&aPref
)[N
],
369 T
* aClosure
= nullptr) {
370 return UnregisterCallback(aCallback
, nsLiteralCString(aPref
), aClosure
,
374 template <int N
, typename T
= void>
375 static nsresult
RegisterCallbackAndCall(PrefChangedFunc aCallback
,
376 const char (&aPref
)[N
],
377 T
* aClosure
= nullptr) {
378 return RegisterCallbackAndCall(aCallback
, nsLiteralCString(aPref
), aClosure
,
382 template <int N
, typename T
= void>
383 static nsresult
RegisterPrefixCallback(PrefChangedFunc aCallback
,
384 const char (&aPref
)[N
],
385 T
* aClosure
= nullptr) {
386 return RegisterCallback(aCallback
, nsLiteralCString(aPref
), aClosure
,
390 template <int N
, typename T
= void>
391 static nsresult
RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback
,
392 const char (&aPref
)[N
],
393 T
* aClosure
= nullptr) {
394 return RegisterCallbackAndCall(aCallback
, nsLiteralCString(aPref
), aClosure
,
398 template <int N
, typename T
= void>
399 static nsresult
UnregisterPrefixCallback(PrefChangedFunc aCallback
,
400 const char (&aPref
)[N
],
401 T
* aClosure
= nullptr) {
402 return UnregisterCallback(aCallback
, nsLiteralCString(aPref
), aClosure
,
406 // When a content process is created these methods are used to pass changed
407 // prefs in bulk from the parent process, via shared memory.
408 static void SerializePreferences(nsCString
& aStr
,
409 bool aIsDestinationWebContentProcess
);
410 static void DeserializePreferences(char* aStr
, size_t aPrefsLen
);
412 static mozilla::ipc::FileDescriptor
EnsureSnapshot(size_t* aSize
);
413 static void InitSnapshot(const mozilla::ipc::FileDescriptor
&, size_t aSize
);
415 // When a single pref is changed in the parent process, these methods are
416 // used to pass the update to content processes.
417 static void GetPreference(dom::Pref
* aPref
,
418 const GeckoProcessType aDestinationProcessType
,
419 const nsACString
& aDestinationRemoteType
);
420 static void SetPreference(const dom::Pref
& aPref
);
423 static bool ArePrefsInitedInContentProcess();
426 static void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
429 static void HandleDirty();
431 // Explicitly choosing synchronous or asynchronous (if allowed) preferences
432 // file write. Only for the default file. The guarantee for the "blocking"
433 // is that when it returns, the file on disk reflect the current state of
435 nsresult
SavePrefFileBlocking();
436 nsresult
SavePrefFileAsynchronous();
438 // If this is false, only blocking writes, on main thread are allowed.
439 bool AllowOffMainThreadSave();
442 virtual ~Preferences();
444 nsresult
NotifyServiceObservers(const char* aSubject
);
446 // Loads the prefs.js file from the profile, or creates a new one. Returns
447 // the prefs file if successful, or nullptr on failure.
448 already_AddRefed
<nsIFile
> ReadSavedPrefs();
450 // Loads the user.js file from the profile if present.
451 void ReadUserOverridePrefs();
453 nsresult
MakeBackupPrefFile(nsIFile
* aFile
);
455 // Default pref file save can be blocking or not.
456 enum class SaveMethod
{ Blocking
, Asynchronous
};
458 // Off main thread is only respected for the default aFile value (nullptr).
459 nsresult
SavePrefFileInternal(nsIFile
* aFile
, SaveMethod aSaveMethod
);
460 nsresult
WritePrefFile(
461 nsIFile
* aFile
, SaveMethod aSaveMethod
,
462 UniquePtr
<MozPromiseHolder
<WritePrefFilePromise
>> aPromise
= nullptr);
464 nsresult
ResetUserPrefs();
466 // Helpers for implementing
467 // Register(Prefix)Callback/Unregister(Prefix)Callback.
469 // Public so the ValueObserver classes can use it.
476 static void SetupTelemetryPref();
477 static nsresult
InitInitialObjects(bool aIsStartup
);
479 friend struct Internals
;
481 static nsresult
RegisterCallback(PrefChangedFunc aCallback
,
482 const nsACString
& aPref
, void* aClosure
,
483 MatchKind aMatchKind
,
484 bool aIsPriority
= false);
485 static nsresult
UnregisterCallback(PrefChangedFunc aCallback
,
486 const nsACString
& aPref
, void* aClosure
,
487 MatchKind aMatchKind
);
488 static nsresult
RegisterCallbackAndCall(PrefChangedFunc aCallback
,
489 const nsACString
& aPref
,
490 void* aClosure
, MatchKind aMatchKind
);
492 static nsresult
RegisterCallbacks(PrefChangedFunc aCallback
,
493 const char* const* aPrefs
, void* aClosure
,
494 MatchKind aMatchKind
);
495 static nsresult
UnregisterCallbacks(PrefChangedFunc aCallback
,
496 const char* const* aPrefs
, void* aClosure
,
497 MatchKind aMatchKind
);
499 template <typename T
>
500 static nsresult
RegisterCallbackImpl(PrefChangedFunc aCallback
, T
& aPref
,
501 void* aClosure
, MatchKind aMatchKind
,
502 bool aIsPriority
= false);
503 template <typename T
>
504 static nsresult
UnregisterCallbackImpl(PrefChangedFunc aCallback
, T
& aPref
,
505 void* aClosure
, MatchKind aMatchKind
);
507 static nsresult
RegisterCallback(PrefChangedFunc aCallback
, const char* aPref
,
508 void* aClosure
, MatchKind aMatchKind
,
509 bool aIsPriority
= false) {
510 return RegisterCallback(aCallback
, nsDependentCString(aPref
), aClosure
,
511 aMatchKind
, aIsPriority
);
513 static nsresult
UnregisterCallback(PrefChangedFunc aCallback
,
514 const char* aPref
, void* aClosure
,
515 MatchKind aMatchKind
) {
516 return UnregisterCallback(aCallback
, nsDependentCString(aPref
), aClosure
,
519 static nsresult
RegisterCallbackAndCall(PrefChangedFunc aCallback
,
520 const char* aPref
, void* aClosure
,
521 MatchKind aMatchKind
) {
522 return RegisterCallbackAndCall(aCallback
, nsDependentCString(aPref
),
523 aClosure
, aMatchKind
);
527 nsCOMPtr
<nsIFile
> mCurrentFile
;
528 // Time since unix epoch in ms (JS Date compatible)
529 PRTime mUserPrefsFileLastModifiedAtStartup
= 0;
531 bool mProfileShutdown
= false;
532 // We wait a bit after prefs are dirty before writing them. In this period,
533 // mDirty and mSavePending will both be true.
534 bool mSavePending
= false;
536 nsCOMPtr
<nsIPrefBranch
> mRootBranch
;
537 nsCOMPtr
<nsIPrefBranch
> mDefaultRootBranch
;
539 static StaticRefPtr
<Preferences
> sPreferences
;
540 static bool sShutdown
;
542 // Init static members. Returns true on success.
543 static bool InitStaticMembers();
546 extern Atomic
<bool, Relaxed
> sOmitBlocklistedPrefValues
;
547 extern Atomic
<bool, Relaxed
> sCrashOnBlocklistedPref
;
549 bool IsPreferenceSanitized(const char* aPref
);
551 const char kFissionEnforceBlockList
[] =
552 "fission.enforceBlocklistedPrefsInSubprocesses";
553 const char kFissionOmitBlockListValues
[] =
554 "fission.omitBlocklistedPrefsInSubprocesses";
556 void OnFissionBlocklistPrefChange(const char* aPref
, void* aData
);
558 } // namespace mozilla
560 #endif // mozilla_Preferences_h