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/StaticPtr.h"
20 #include "nsIObserver.h"
21 #include "nsIPrefBranch.h"
22 #include "nsIPrefService.h"
25 #include "nsWeakReference.h"
26 #include "nsXULAppAPI.h"
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
);
40 struct RegisterCallbacksInternal
;
42 void UnloadPrefsModule();
44 class PreferenceServiceReporter
;
57 // Xlib.h defines Bool as a macro constant. Don't try to define this enum if
58 // it's already been included.
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
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;
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
,
96 public nsSupportsWeakReference
{
97 friend class ::nsPrefBranch
;
100 NS_DECL_THREADSAFE_ISUPPORTS
101 NS_DECL_NSIPREFSERVICE
102 NS_FORWARD_NSIPREFBRANCH(mRootBranch
->)
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);
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
,
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
) {
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
),
201 static nsresult
SetString(const char* aPrefName
, const char16ptr_t aValue
,
202 PrefValueKind aKind
= PrefValueKind::User
) {
203 return Preferences::SetCString(aPrefName
, NS_ConvertUTF16toUTF8(aValue
),
207 static nsresult
SetString(const char* aPrefName
, const nsAString
& aValue
,
208 PrefValueKind aKind
= PrefValueKind::User
) {
209 return Preferences::SetCString(aPrefName
, NS_ConvertUTF16toUTF8(aValue
),
213 static nsresult
SetComplex(const char* aPrefName
, const nsIID
& aType
,
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
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
);
241 static nsresult
AddStrongObserver(nsIObserver
* aObserver
,
242 const char (&aPref
)[N
]) {
243 return AddStrongObserver(aObserver
, nsLiteralCString(aPref
));
246 static nsresult
AddWeakObserver(nsIObserver
* aObserver
,
247 const char (&aPref
)[N
]) {
248 return AddWeakObserver(aObserver
, nsLiteralCString(aPref
));
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
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
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
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
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
,
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
,
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
,
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
,
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
,
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
,
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
);
420 static bool ArePrefsInitedInContentProcess();
423 static void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
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
432 nsresult
SavePrefFileBlocking();
433 nsresult
SavePrefFileAsynchronous();
435 // If this is false, only blocking writes, on main thread are allowed.
436 bool AllowOffMainThreadSave();
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.
464 // Public so the ValueObserver classes can use it.
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
,
514 static nsresult
RegisterCallbackAndCall(PrefChangedFunc aCallback
,
515 const char* aPref
, void* aClosure
,
516 MatchKind aMatchKind
) {
517 return RegisterCallbackAndCall(aCallback
, nsDependentCString(aPref
),
518 aClosure
, aMatchKind
);
522 nsCOMPtr
<nsIFile
> mCurrentFile
;
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