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** 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
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
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
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
,
328 T
* aClosure
= nullptr) {
329 return RegisterCallbacks(aCallback
, aPrefs
, aClosure
, ExactMatch
);
331 static nsresult
RegisterCallbacksAndCall(PrefChangedFunc aCallback
,
333 void* aClosure
= nullptr);
334 template <typename T
= void>
335 static nsresult
UnregisterCallbacks(PrefChangedFunc aCallback
,
337 T
* aClosure
= nullptr) {
338 return UnregisterCallbacks(aCallback
, aPrefs
, aClosure
, ExactMatch
);
340 template <typename T
= void>
341 static nsresult
RegisterPrefixCallbacks(PrefChangedFunc aCallback
,
343 T
* aClosure
= nullptr) {
344 return RegisterCallbacks(aCallback
, aPrefs
, aClosure
, PrefixMatch
);
346 template <typename T
= void>
347 static nsresult
UnregisterPrefixCallbacks(PrefChangedFunc aCallback
,
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
,
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
,
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
,
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
,
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
,
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
,
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
);
418 static bool ArePrefsInitedInContentProcess();
421 static void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
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
430 nsresult
SavePrefFileBlocking();
431 nsresult
SavePrefFileAsynchronous();
433 // If this is false, only blocking writes, on main thread are allowed.
434 bool AllowOffMainThreadSave();
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.
462 // Public so the ValueObserver classes can use it.
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
,
512 static nsresult
RegisterCallbackAndCall(PrefChangedFunc aCallback
,
513 const char* aPref
, void* aClosure
,
514 MatchKind aMatchKind
) {
515 return RegisterCallbackAndCall(aCallback
, nsDependentCString(aPref
),
516 aClosure
, aMatchKind
);
520 nsCOMPtr
<nsIFile
> mCurrentFile
;
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