/src/mozilla-central/modules/libpref/Preferences.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #ifndef mozilla_Preferences_h |
8 | | #define mozilla_Preferences_h |
9 | | |
10 | | #ifndef MOZILLA_INTERNAL_API |
11 | | #error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)." |
12 | | #endif |
13 | | |
14 | | #include "mozilla/Atomics.h" |
15 | | #include "mozilla/MemoryReporting.h" |
16 | | #include "mozilla/Result.h" |
17 | | #include "mozilla/StaticPtr.h" |
18 | | #include "nsCOMPtr.h" |
19 | | #include "nsIObserver.h" |
20 | | #include "nsIPrefBranch.h" |
21 | | #include "nsIPrefService.h" |
22 | | #include "nsPrintfCString.h" |
23 | | #include "nsString.h" |
24 | | #include "nsTArray.h" |
25 | | #include "nsWeakReference.h" |
26 | | |
27 | | class nsIFile; |
28 | | |
29 | | // The callback function will get passed the pref name which triggered the call |
30 | | // and the void* data which was passed to the registered callback function. |
31 | | typedef void (*PrefChangedFunc)(const char* aPref, void* aData); |
32 | | |
33 | | class nsPrefBranch; |
34 | | |
35 | | namespace mozilla { |
36 | | |
37 | | // A typesafe version of PrefChangeFunc, with its data argument type deduced |
38 | | // from the type of the argument passed to RegisterCallback. |
39 | | // |
40 | | // Note: We specify this as a dependent type TypedPrefChangeFunc<T>::SelfType so |
41 | | // that it does not participate in argument type deduction. This allows us to |
42 | | // use its implicit conversion constructor, and also allows our Register and |
43 | | // Unregister methods to accept non-capturing lambdas (which will not match |
44 | | // void(*)(const char*, T*) when used in type deduction) as callback functions. |
45 | | template<typename T> |
46 | | struct TypedPrefChangeFunc |
47 | | { |
48 | | using Type = TypedPrefChangeFunc<T>; |
49 | | using CallbackType = void (*)(const char*, T*); |
50 | | |
51 | | MOZ_IMPLICIT TypedPrefChangeFunc(CallbackType aCallback) |
52 | | : mCallback(aCallback) |
53 | 0 | { |
54 | 0 | } Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, bool> >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<bool, bool>*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> >*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> >*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<int, int> >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<int, int>*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<int, mozilla::Atomic<int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<int, mozilla::Atomic<int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> >*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, unsigned int> >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<unsigned int, unsigned int>*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> >*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> >*)) Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<float, float> >::TypedPrefChangeFunc(void (*)(char const*, mozilla::Closure<float, float>*)) |
55 | | |
56 | | template<typename F> |
57 | | MOZ_IMPLICIT TypedPrefChangeFunc(F&& aLambda) |
58 | | : mCallback(aLambda) |
59 | | { |
60 | | } |
61 | | |
62 | | operator PrefChangedFunc() const |
63 | 0 | { |
64 | 0 | return reinterpret_cast<PrefChangedFunc>(mCallback); |
65 | 0 | } Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, bool> >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<int, int> >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<int, mozilla::Atomic<int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, unsigned int> >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >::operator void (*)(char const*, void*)() const Unexecuted instantiation: mozilla::TypedPrefChangeFunc<mozilla::Closure<float, float> >::operator void (*)(char const*, void*)() const |
66 | | |
67 | | CallbackType mCallback; |
68 | | }; |
69 | | |
70 | | // Similar to PrefChangedFunc, but for use with instance methods. |
71 | | // |
72 | | // Any instance method with this signature may be passed to the |
73 | | // PREF_CHANGE_METHOD macro, which will wrap it into a typesafe preference |
74 | | // callback function, which accepts a preference name as its first argument, and |
75 | | // an instance of the appropriate class as the second. |
76 | | // |
77 | | // When called, the wrapper will forward the call to the wrapped method on the |
78 | | // given instance, with the notified preference as its only argument. |
79 | | typedef void(PrefChangedMethod)(const char* aPref); |
80 | | |
81 | | namespace detail { |
82 | | // Helper to extract the instance type from any instance method. For an instance |
83 | | // method `Method = U T::*`, InstanceType<Method>::Type returns T. |
84 | | template<typename T> |
85 | | struct InstanceType; |
86 | | |
87 | | template<typename T, typename U> |
88 | | struct InstanceType<U T::*> |
89 | | { |
90 | | using Type = T; |
91 | | }; |
92 | | |
93 | | // A wrapper for a PrefChangeMethod instance method which forwards calls to the |
94 | | // wrapped method on the given instance. |
95 | | template<typename T, PrefChangedMethod T::*Method> |
96 | | void |
97 | | PrefChangeMethod(const char* aPref, T* aInst) |
98 | | { |
99 | | ((*aInst).*Method)(aPref); |
100 | | } |
101 | | } // namespace detail |
102 | | |
103 | | // Creates a wrapper around an instance method, with the signature of |
104 | | // PrefChangedMethod, from an arbitrary class, so that it can be used as a |
105 | | // preference callback. The closure data passed to RegisterCallback must be an |
106 | | // instance of this class. |
107 | | // |
108 | | // Note: This is implemented as a macro rather than a pure template function |
109 | | // because, prior to C++17, value template arguments must have their types |
110 | | // fully-specified. Once all of our supported compilers have C++17 support, we |
111 | | // can give PrefChangeMethod a single <auto Method> argument, and use |
112 | | // PrefChangeMethod<&meth> directly. |
113 | | #define PREF_CHANGE_METHOD(meth) \ |
114 | | (&::mozilla::detail::PrefChangeMethod< \ |
115 | | ::mozilla::detail::InstanceType<decltype(&meth)>::Type, \ |
116 | | &meth>) |
117 | | |
118 | | class PreferenceServiceReporter; |
119 | | |
120 | | namespace dom { |
121 | | class Pref; |
122 | | class PrefValue; |
123 | | } // namespace dom |
124 | | |
125 | | namespace ipc { |
126 | | class FileDescriptor; |
127 | | } // namespace ipc |
128 | | |
129 | | struct PrefsSizes; |
130 | | |
131 | | // Xlib.h defines Bool as a macro constant. Don't try to define this enum if |
132 | | // it's already been included. |
133 | | #ifndef Bool |
134 | | |
135 | | // Keep this in sync with PrefType in parser/src/lib.rs. |
136 | | enum class PrefType : uint8_t |
137 | | { |
138 | | None = 0, // only used when neither the default nor user value is set |
139 | | String = 1, |
140 | | Int = 2, |
141 | | Bool = 3, |
142 | | }; |
143 | | |
144 | | #endif |
145 | | |
146 | | #ifdef XP_UNIX |
147 | | // We need to send two shared memory descriptors to every child process: |
148 | | // |
149 | | // 1) A read-only/write-protected snapshot of the initial state of the |
150 | | // preference database. This memory is shared between all processes, and |
151 | | // therefore cannot be modified once it has been created. |
152 | | // |
153 | | // 2) A set of changes on top of the snapshot, containing the current values of |
154 | | // all preferences which have changed since it was created. |
155 | | // |
156 | | // Since the second set will be different for every process, and the first set |
157 | | // cannot be modified, it is unfortunately not possible to combine them into a |
158 | | // single file descriptor. |
159 | | // |
160 | | // XXX: bug 1440207 is about improving how fixed fds such as this are used. |
161 | | static const int kPrefsFileDescriptor = 8; |
162 | | static const int kPrefMapFileDescriptor = 9; |
163 | | #endif |
164 | | |
165 | | // Keep this in sync with PrefType in parser/src/lib.rs. |
166 | | enum class PrefValueKind : uint8_t |
167 | | { |
168 | | Default, |
169 | | User |
170 | | }; |
171 | | |
172 | | class Preferences final |
173 | | : public nsIPrefService |
174 | | , public nsIObserver |
175 | | , public nsIPrefBranch |
176 | | , public nsSupportsWeakReference |
177 | | { |
178 | | friend class ::nsPrefBranch; |
179 | | |
180 | | public: |
181 | | NS_DECL_THREADSAFE_ISUPPORTS |
182 | | NS_DECL_NSIPREFSERVICE |
183 | | NS_FORWARD_NSIPREFBRANCH(mRootBranch->) |
184 | | NS_DECL_NSIOBSERVER |
185 | | |
186 | | Preferences(); |
187 | | |
188 | | // Returns true if the Preferences service is available, false otherwise. |
189 | | static bool IsServiceAvailable(); |
190 | | |
191 | | // Initialize user prefs from prefs.js/user.js |
192 | | static void InitializeUserPrefs(); |
193 | | |
194 | | // Returns the singleton instance which is addreffed. |
195 | | static already_AddRefed<Preferences> GetInstanceForService(); |
196 | | |
197 | | // Finallizes global members. |
198 | | static void Shutdown(); |
199 | | |
200 | | // Returns shared pref service instance NOTE: not addreffed. |
201 | | static nsIPrefService* GetService() |
202 | | { |
203 | | NS_ENSURE_TRUE(InitStaticMembers(), nullptr); |
204 | | return sPreferences; |
205 | | } |
206 | | |
207 | | // Returns shared pref branch instance. NOTE: not addreffed. |
208 | | static nsIPrefBranch* GetRootBranch(PrefValueKind aKind = PrefValueKind::User) |
209 | | { |
210 | | NS_ENSURE_TRUE(InitStaticMembers(), nullptr); |
211 | | return (aKind == PrefValueKind::Default) ? sPreferences->mDefaultRootBranch |
212 | | : sPreferences->mRootBranch; |
213 | | } |
214 | | |
215 | | // Gets the type of the pref. |
216 | | static int32_t GetType(const char* aPrefName); |
217 | | |
218 | | // Fallible value getters. When `aKind` is `User` they will get the user |
219 | | // value if possible, and fall back to the default value otherwise. |
220 | | static nsresult GetBool(const char* aPrefName, |
221 | | bool* aResult, |
222 | | PrefValueKind aKind = PrefValueKind::User); |
223 | | static nsresult GetInt(const char* aPrefName, |
224 | | int32_t* aResult, |
225 | | PrefValueKind aKind = PrefValueKind::User); |
226 | | static nsresult GetUint(const char* aPrefName, |
227 | | uint32_t* aResult, |
228 | | PrefValueKind aKind = PrefValueKind::User) |
229 | | { |
230 | | return GetInt(aPrefName, reinterpret_cast<int32_t*>(aResult), aKind); |
231 | | } |
232 | | static nsresult GetFloat(const char* aPrefName, |
233 | | float* aResult, |
234 | | PrefValueKind aKind = PrefValueKind::User); |
235 | | static nsresult GetCString(const char* aPrefName, |
236 | | nsACString& aResult, |
237 | | PrefValueKind aKind = PrefValueKind::User); |
238 | | static nsresult GetString(const char* aPrefName, |
239 | | nsAString& aResult, |
240 | | PrefValueKind aKind = PrefValueKind::User); |
241 | | static nsresult GetLocalizedCString( |
242 | | const char* aPrefName, |
243 | | nsACString& aResult, |
244 | | PrefValueKind aKind = PrefValueKind::User); |
245 | | static nsresult GetLocalizedString(const char* aPrefName, |
246 | | nsAString& aResult, |
247 | | PrefValueKind aKind = PrefValueKind::User); |
248 | | static nsresult GetComplex(const char* aPrefName, |
249 | | const nsIID& aType, |
250 | | void** aResult, |
251 | | PrefValueKind aKind = PrefValueKind::User); |
252 | | |
253 | | // Infallible getters of user or default values, with fallback results on |
254 | | // failure. When `aKind` is `User` they will get the user value if possible, |
255 | | // and fall back to the default value otherwise. |
256 | | static bool GetBool(const char* aPrefName, |
257 | | bool aFallback = false, |
258 | | PrefValueKind aKind = PrefValueKind::User) |
259 | | { |
260 | | bool result = aFallback; |
261 | | GetBool(aPrefName, &result, aKind); |
262 | | return result; |
263 | | } |
264 | | static int32_t GetInt(const char* aPrefName, |
265 | | int32_t aFallback = 0, |
266 | | PrefValueKind aKind = PrefValueKind::User) |
267 | | { |
268 | | int32_t result = aFallback; |
269 | | GetInt(aPrefName, &result, aKind); |
270 | | return result; |
271 | | } |
272 | | static uint32_t GetUint(const char* aPrefName, |
273 | | uint32_t aFallback = 0, |
274 | | PrefValueKind aKind = PrefValueKind::User) |
275 | | { |
276 | | uint32_t result = aFallback; |
277 | | GetUint(aPrefName, &result, aKind); |
278 | | return result; |
279 | | } |
280 | | static float GetFloat(const char* aPrefName, |
281 | | float aFallback = 0.0f, |
282 | | PrefValueKind aKind = PrefValueKind::User) |
283 | | { |
284 | | float result = aFallback; |
285 | | GetFloat(aPrefName, &result, aKind); |
286 | | return result; |
287 | | } |
288 | | |
289 | | // Value setters. These fail if run outside the parent process. |
290 | | |
291 | | static nsresult SetBool(const char* aPrefName, |
292 | | bool aValue, |
293 | | PrefValueKind aKind = PrefValueKind::User); |
294 | | static nsresult SetInt(const char* aPrefName, |
295 | | int32_t aValue, |
296 | | PrefValueKind aKind = PrefValueKind::User); |
297 | | static nsresult SetCString(const char* aPrefName, |
298 | | const nsACString& aValue, |
299 | | PrefValueKind aKind = PrefValueKind::User); |
300 | | |
301 | | static nsresult SetUint(const char* aPrefName, |
302 | | uint32_t aValue, |
303 | | PrefValueKind aKind = PrefValueKind::User) |
304 | | { |
305 | | return SetInt(aPrefName, static_cast<int32_t>(aValue), aKind); |
306 | | } |
307 | | |
308 | | static nsresult SetFloat(const char* aPrefName, |
309 | | float aValue, |
310 | | PrefValueKind aKind = PrefValueKind::User) |
311 | | { |
312 | | return SetCString(aPrefName, nsPrintfCString("%f", aValue), aKind); |
313 | | } |
314 | | |
315 | | static nsresult SetCString(const char* aPrefName, |
316 | | const char* aValue, |
317 | | PrefValueKind aKind = PrefValueKind::User) |
318 | | { |
319 | | return Preferences::SetCString( |
320 | | aPrefName, nsDependentCString(aValue), aKind); |
321 | | } |
322 | | |
323 | | static nsresult SetString(const char* aPrefName, |
324 | | const char16ptr_t aValue, |
325 | | PrefValueKind aKind = PrefValueKind::User) |
326 | | { |
327 | | return Preferences::SetCString( |
328 | | aPrefName, NS_ConvertUTF16toUTF8(aValue), aKind); |
329 | | } |
330 | | |
331 | | static nsresult SetString(const char* aPrefName, |
332 | | const nsAString& aValue, |
333 | | PrefValueKind aKind = PrefValueKind::User) |
334 | | { |
335 | | return Preferences::SetCString( |
336 | | aPrefName, NS_ConvertUTF16toUTF8(aValue), aKind); |
337 | | } |
338 | | |
339 | | static nsresult SetComplex(const char* aPrefName, |
340 | | const nsIID& aType, |
341 | | nsISupports* aValue, |
342 | | PrefValueKind aKind = PrefValueKind::User); |
343 | | |
344 | | static nsresult Lock(const char* aPrefName); |
345 | | static nsresult Unlock(const char* aPrefName); |
346 | | static bool IsLocked(const char* aPrefName); |
347 | | |
348 | | // Clears user set pref. Fails if run outside the parent process. |
349 | | static nsresult ClearUser(const char* aPrefName); |
350 | | |
351 | | // Whether the pref has a user value or not. |
352 | | static bool HasUserValue(const char* aPref); |
353 | | |
354 | | // Adds/Removes the observer for the root pref branch. See nsIPrefBranch.idl |
355 | | // for details. |
356 | | static nsresult AddStrongObserver(nsIObserver* aObserver, |
357 | | const nsACString& aPref); |
358 | | static nsresult AddWeakObserver(nsIObserver* aObserver, |
359 | | const nsACString& aPref); |
360 | | static nsresult RemoveObserver(nsIObserver* aObserver, |
361 | | const nsACString& aPref); |
362 | | |
363 | | template<int N> |
364 | | static nsresult AddStrongObserver(nsIObserver* aObserver, |
365 | | const char (&aPref)[N]) |
366 | | { |
367 | | return AddStrongObserver(aObserver, nsLiteralCString(aPref)); |
368 | | } |
369 | | template<int N> |
370 | | static nsresult AddWeakObserver(nsIObserver* aObserver, |
371 | | const char (&aPref)[N]) |
372 | | { |
373 | | return AddWeakObserver(aObserver, nsLiteralCString(aPref)); |
374 | | } |
375 | | template<int N> |
376 | | static nsresult RemoveObserver(nsIObserver* aObserver, const char (&aPref)[N]) |
377 | | { |
378 | | return RemoveObserver(aObserver, nsLiteralCString(aPref)); |
379 | | } |
380 | | |
381 | | // Adds/Removes two or more observers for the root pref branch. Pass to |
382 | | // aPrefs an array of const char* whose last item is nullptr. |
383 | | // Note: All preference strings *must* be statically-allocated string |
384 | | // literals. |
385 | | static nsresult AddStrongObservers(nsIObserver* aObserver, |
386 | | const char** aPrefs); |
387 | | static nsresult AddWeakObservers(nsIObserver* aObserver, const char** aPrefs); |
388 | | static nsresult RemoveObservers(nsIObserver* aObserver, const char** aPrefs); |
389 | | |
390 | | // Registers/Unregisters the callback function for the aPref. |
391 | | template<typename T = void> |
392 | | static nsresult RegisterCallback( |
393 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
394 | | const nsACString& aPref, |
395 | | T* aClosure = nullptr) |
396 | 0 | { |
397 | 0 | return RegisterCallback(aCallback, aPref, aClosure, ExactMatch); |
398 | 0 | } Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<bool, bool> >(mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, bool> >::Type, nsTSubstring<char> const&, mozilla::Closure<bool, bool>*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >(mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::Type, nsTSubstring<char> const&, mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> >*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >(mozilla::TypedPrefChangeFunc<mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >::Type, nsTSubstring<char> const&, mozilla::Closure<bool, mozilla::Atomic<bool, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> >*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<int, int> >(mozilla::TypedPrefChangeFunc<mozilla::Closure<int, int> >::Type, nsTSubstring<char> const&, mozilla::Closure<int, int>*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<int, mozilla::Atomic<int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >(mozilla::TypedPrefChangeFunc<mozilla::Closure<int, mozilla::Atomic<int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::Type, nsTSubstring<char> const&, mozilla::Closure<int, mozilla::Atomic<int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> >*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<unsigned int, unsigned int> >(mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, unsigned int> >::Type, nsTSubstring<char> const&, mozilla::Closure<unsigned int, unsigned int>*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >(mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> > >::Type, nsTSubstring<char> const&, mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)0, (mozilla::recordreplay::Behavior)1, void> >*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >(mozilla::TypedPrefChangeFunc<mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> > >::Type, nsTSubstring<char> const&, mozilla::Closure<unsigned int, mozilla::Atomic<unsigned int, (mozilla::MemoryOrdering)1, (mozilla::recordreplay::Behavior)1, void> >*) Unexecuted instantiation: nsresult mozilla::Preferences::RegisterCallback<mozilla::Closure<float, float> >(mozilla::TypedPrefChangeFunc<mozilla::Closure<float, float> >::Type, nsTSubstring<char> const&, mozilla::Closure<float, float>*) |
399 | | |
400 | | template<typename T = void> |
401 | | static nsresult UnregisterCallback( |
402 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
403 | | const nsACString& aPref, |
404 | | T* aClosure = nullptr) |
405 | | { |
406 | | return UnregisterCallback(aCallback, aPref, aClosure, ExactMatch); |
407 | | } |
408 | | |
409 | | // Like RegisterCallback, but also calls the callback immediately for |
410 | | // initialization. |
411 | | template<typename T = void> |
412 | | static nsresult RegisterCallbackAndCall( |
413 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
414 | | const nsACString& aPref, |
415 | | T* aClosure = nullptr) |
416 | | { |
417 | | return RegisterCallbackAndCall(aCallback, aPref, aClosure, ExactMatch); |
418 | | } |
419 | | |
420 | | // Like RegisterCallback, but registers a callback for a prefix of multiple |
421 | | // pref names, not a single pref name. |
422 | | template<typename T = void> |
423 | | static nsresult RegisterPrefixCallback( |
424 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
425 | | const nsACString& aPref, |
426 | | T* aClosure = nullptr) |
427 | | { |
428 | | return RegisterCallback(aCallback, aPref, aClosure, PrefixMatch); |
429 | | } |
430 | | |
431 | | // Like RegisterPrefixCallback, but also calls the callback immediately for |
432 | | // initialization. |
433 | | template<typename T = void> |
434 | | static nsresult RegisterPrefixCallbackAndCall( |
435 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
436 | | const nsACString& aPref, |
437 | | T* aClosure = nullptr) |
438 | | { |
439 | | return RegisterCallbackAndCall(aCallback, aPref, aClosure, PrefixMatch); |
440 | | } |
441 | | |
442 | | // Unregister a callback registered with RegisterPrefixCallback or |
443 | | // RegisterPrefixCallbackAndCall. |
444 | | template<typename T = void> |
445 | | static nsresult UnregisterPrefixCallback( |
446 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
447 | | const nsACString& aPref, |
448 | | T* aClosure = nullptr) |
449 | | { |
450 | | return UnregisterCallback(aCallback, aPref, aClosure, PrefixMatch); |
451 | | } |
452 | | |
453 | | // Variants of the above which register a single callback to handle multiple |
454 | | // preferences. |
455 | | // |
456 | | // The array of preference names must be null terminated. It may be |
457 | | // dynamically allocated, but the caller is responsible for keeping it alive |
458 | | // until the callback is unregistered. |
459 | | // |
460 | | // Also note that the exact same aPrefs pointer must be passed to the |
461 | | // Unregister call as was passed to the Register call. |
462 | | template<typename T = void> |
463 | | static nsresult RegisterCallbacks( |
464 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
465 | | const char** aPrefs, |
466 | | T* aClosure = nullptr) |
467 | | { |
468 | | return RegisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch); |
469 | | } |
470 | | static nsresult RegisterCallbacksAndCall(PrefChangedFunc aCallback, |
471 | | const char** aPrefs, |
472 | | void* aClosure = nullptr); |
473 | | template<typename T = void> |
474 | | static nsresult UnregisterCallbacks( |
475 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
476 | | const char** aPrefs, |
477 | | T* aClosure = nullptr) |
478 | | { |
479 | | return UnregisterCallbacks(aCallback, aPrefs, aClosure, ExactMatch); |
480 | | } |
481 | | template<typename T = void> |
482 | | static nsresult RegisterPrefixCallbacks( |
483 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
484 | | const char** aPrefs, |
485 | | T* aClosure = nullptr) |
486 | | { |
487 | | return RegisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch); |
488 | | } |
489 | | template<typename T = void> |
490 | | static nsresult UnregisterPrefixCallbacks( |
491 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
492 | | const char** aPrefs, |
493 | | T* aClosure = nullptr) |
494 | | { |
495 | | return UnregisterCallbacks(aCallback, aPrefs, aClosure, PrefixMatch); |
496 | | } |
497 | | |
498 | | template<int N, typename T = void> |
499 | | static nsresult RegisterCallback( |
500 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
501 | | const char (&aPref)[N], |
502 | | T* aClosure = nullptr) |
503 | | { |
504 | | return RegisterCallback( |
505 | | aCallback, nsLiteralCString(aPref), aClosure, ExactMatch); |
506 | | } |
507 | | |
508 | | template<int N, typename T = void> |
509 | | static nsresult UnregisterCallback( |
510 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
511 | | const char (&aPref)[N], |
512 | | T* aClosure = nullptr) |
513 | | { |
514 | | return UnregisterCallback( |
515 | | aCallback, nsLiteralCString(aPref), aClosure, ExactMatch); |
516 | | } |
517 | | |
518 | | template<int N, typename T = void> |
519 | | static nsresult RegisterCallbackAndCall( |
520 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
521 | | const char (&aPref)[N], |
522 | | T* aClosure = nullptr) |
523 | | { |
524 | | return RegisterCallbackAndCall( |
525 | | aCallback, nsLiteralCString(aPref), aClosure, ExactMatch); |
526 | | } |
527 | | |
528 | | template<int N, typename T = void> |
529 | | static nsresult RegisterPrefixCallback( |
530 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
531 | | const char (&aPref)[N], |
532 | | T* aClosure = nullptr) |
533 | | { |
534 | | return RegisterCallback( |
535 | | aCallback, nsLiteralCString(aPref), aClosure, PrefixMatch); |
536 | | } |
537 | | |
538 | | template<int N, typename T = void> |
539 | | static nsresult RegisterPrefixCallbackAndCall( |
540 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
541 | | const char (&aPref)[N], |
542 | | T* aClosure = nullptr) |
543 | | { |
544 | | return RegisterCallbackAndCall( |
545 | | aCallback, nsLiteralCString(aPref), aClosure, PrefixMatch); |
546 | | } |
547 | | |
548 | | template<int N, typename T = void> |
549 | | static nsresult UnregisterPrefixCallback( |
550 | | typename TypedPrefChangeFunc<T>::Type aCallback, |
551 | | const char (&aPref)[N], |
552 | | T* aClosure = nullptr) |
553 | | { |
554 | | return UnregisterCallback( |
555 | | aCallback, nsLiteralCString(aPref), aClosure, PrefixMatch); |
556 | | } |
557 | | |
558 | | // Adds the aVariable to cache table. |aVariable| must be a pointer for a |
559 | | // static variable. The value will be modified when the pref value is changed |
560 | | // but note that even if you modified it, the value isn't assigned to the |
561 | | // pref. |
562 | | static nsresult AddBoolVarCache(bool* aVariable, |
563 | | const nsACString& aPref, |
564 | | bool aDefault = false, |
565 | | bool aSkipAssignment = false); |
566 | | template<MemoryOrdering Order> |
567 | | static nsresult AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable, |
568 | | const nsACString& aPref, |
569 | | bool aDefault = false, |
570 | | bool aSkipAssignment = false); |
571 | | static nsresult AddIntVarCache(int32_t* aVariable, |
572 | | const nsACString& aPref, |
573 | | int32_t aDefault = 0, |
574 | | bool aSkipAssignment = false); |
575 | | template<MemoryOrdering Order> |
576 | | static nsresult AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable, |
577 | | const nsACString& aPref, |
578 | | int32_t aDefault = 0, |
579 | | bool aSkipAssignment = false); |
580 | | static nsresult AddUintVarCache(uint32_t* aVariable, |
581 | | const nsACString& aPref, |
582 | | uint32_t aDefault = 0, |
583 | | bool aSkipAssignment = false); |
584 | | template<MemoryOrdering Order> |
585 | | static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable, |
586 | | const nsACString& aPref, |
587 | | uint32_t aDefault = 0, |
588 | | bool aSkipAssignment = false); |
589 | | static nsresult AddFloatVarCache(float* aVariable, |
590 | | const nsACString& aPref, |
591 | | float aDefault = 0.0f, |
592 | | bool aSkipAssignment = false); |
593 | | |
594 | | template<int N> |
595 | | static nsresult AddBoolVarCache(bool* aVariable, |
596 | | const char (&aPref)[N], |
597 | | bool aDefault = false, |
598 | | bool aSkipAssignment = false) |
599 | | { |
600 | | return AddBoolVarCache( |
601 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
602 | | } |
603 | | template<MemoryOrdering Order, int N> |
604 | | static nsresult AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable, |
605 | | const char (&aPref)[N], |
606 | | bool aDefault = false, |
607 | | bool aSkipAssignment = false) |
608 | | { |
609 | | return AddAtomicBoolVarCache<Order>( |
610 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
611 | | } |
612 | | template<int N> |
613 | | static nsresult AddIntVarCache(int32_t* aVariable, |
614 | | const char (&aPref)[N], |
615 | | int32_t aDefault = 0, |
616 | | bool aSkipAssignment = false) |
617 | | { |
618 | | return AddIntVarCache( |
619 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
620 | | } |
621 | | template<MemoryOrdering Order, int N> |
622 | | static nsresult AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable, |
623 | | const char (&aPref)[N], |
624 | | int32_t aDefault = 0, |
625 | | bool aSkipAssignment = false) |
626 | | { |
627 | | return AddAtomicIntVarCache<Order>( |
628 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
629 | | } |
630 | | template<int N> |
631 | | static nsresult AddUintVarCache(uint32_t* aVariable, |
632 | | const char (&aPref)[N], |
633 | | uint32_t aDefault = 0, |
634 | | bool aSkipAssignment = false) |
635 | | { |
636 | | return AddUintVarCache( |
637 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
638 | | } |
639 | | template<MemoryOrdering Order, int N> |
640 | | static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable, |
641 | | const char (&aPref)[N], |
642 | | uint32_t aDefault = 0, |
643 | | bool aSkipAssignment = false) |
644 | | { |
645 | | return AddAtomicUintVarCache<Order>( |
646 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
647 | | } |
648 | | template<int N> |
649 | | static nsresult AddFloatVarCache(float* aVariable, |
650 | | const char (&aPref)[N], |
651 | | float aDefault = 0.0f, |
652 | | bool aSkipAssignment = false) |
653 | | { |
654 | | return AddFloatVarCache( |
655 | | aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment); |
656 | | } |
657 | | |
658 | | // When a content process is created these methods are used to pass changed |
659 | | // prefs in bulk from the parent process, via shared memory. |
660 | | static void SerializePreferences(nsCString& aStr); |
661 | | static void DeserializePreferences(char* aStr, size_t aPrefsLen); |
662 | | |
663 | | static mozilla::ipc::FileDescriptor EnsureSnapshot(size_t* aSize); |
664 | | static void InitSnapshot(const mozilla::ipc::FileDescriptor&, size_t aSize); |
665 | | |
666 | | // When a single pref is changed in the parent process, these methods are |
667 | | // used to pass the update to content processes. |
668 | | static void GetPreference(dom::Pref* aPref); |
669 | | static void SetPreference(const dom::Pref& aPref); |
670 | | |
671 | | #ifdef DEBUG |
672 | | static bool ArePrefsInitedInContentProcess(); |
673 | | #endif |
674 | | |
675 | | static void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
676 | | PrefsSizes& aSizes); |
677 | | |
678 | | static void HandleDirty(); |
679 | | |
680 | | // Explicitly choosing synchronous or asynchronous (if allowed) preferences |
681 | | // file write. Only for the default file. The guarantee for the "blocking" |
682 | | // is that when it returns, the file on disk reflect the current state of |
683 | | // preferences. |
684 | | nsresult SavePrefFileBlocking(); |
685 | | nsresult SavePrefFileAsynchronous(); |
686 | | |
687 | | private: |
688 | | virtual ~Preferences(); |
689 | | |
690 | | nsresult NotifyServiceObservers(const char* aSubject); |
691 | | |
692 | | // Loads the prefs.js file from the profile, or creates a new one. Returns |
693 | | // the prefs file if successful, or nullptr on failure. |
694 | | already_AddRefed<nsIFile> ReadSavedPrefs(); |
695 | | |
696 | | // Loads the user.js file from the profile if present. |
697 | | void ReadUserOverridePrefs(); |
698 | | |
699 | | nsresult MakeBackupPrefFile(nsIFile* aFile); |
700 | | |
701 | | // Default pref file save can be blocking or not. |
702 | | enum class SaveMethod |
703 | | { |
704 | | Blocking, |
705 | | Asynchronous |
706 | | }; |
707 | | |
708 | | // Off main thread is only respected for the default aFile value (nullptr). |
709 | | nsresult SavePrefFileInternal(nsIFile* aFile, SaveMethod aSaveMethod); |
710 | | nsresult WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod); |
711 | | |
712 | | // If this is false, only blocking writes, on main thread are allowed. |
713 | | bool AllowOffMainThreadSave(); |
714 | | |
715 | | // Helpers for implementing |
716 | | // Register(Prefix)Callback/Unregister(Prefix)Callback. |
717 | | public: |
718 | | // Public so the ValueObserver classes can use it. |
719 | | enum MatchKind |
720 | | { |
721 | | PrefixMatch, |
722 | | ExactMatch, |
723 | | }; |
724 | | |
725 | | private: |
726 | | static void SetupTelemetryPref(); |
727 | | static mozilla::Result<mozilla::Ok, const char*> InitInitialObjects( |
728 | | bool aIsStartup); |
729 | | |
730 | | static nsresult RegisterCallback(PrefChangedFunc aCallback, |
731 | | const nsACString& aPref, |
732 | | void* aClosure, |
733 | | MatchKind aMatchKind, |
734 | | bool aIsPriority = false); |
735 | | static nsresult UnregisterCallback(PrefChangedFunc aCallback, |
736 | | const nsACString& aPref, |
737 | | void* aClosure, |
738 | | MatchKind aMatchKind); |
739 | | static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback, |
740 | | const nsACString& aPref, |
741 | | void* aClosure, |
742 | | MatchKind aMatchKind); |
743 | | |
744 | | static nsresult RegisterCallbacks(PrefChangedFunc aCallback, |
745 | | const char** aPrefs, |
746 | | void* aClosure, |
747 | | MatchKind aMatchKind); |
748 | | static nsresult UnregisterCallbacks(PrefChangedFunc aCallback, |
749 | | const char** aPrefs, |
750 | | void* aClosure, |
751 | | MatchKind aMatchKind); |
752 | | |
753 | | template<typename T> |
754 | | static nsresult RegisterCallbackImpl(PrefChangedFunc aCallback, |
755 | | T& aPref, |
756 | | void* aClosure, |
757 | | MatchKind aMatchKind, |
758 | | bool aIsPriority = false); |
759 | | template<typename T> |
760 | | static nsresult UnregisterCallbackImpl(PrefChangedFunc aCallback, |
761 | | T& aPref, |
762 | | void* aClosure, |
763 | | MatchKind aMatchKind); |
764 | | |
765 | | static nsresult RegisterCallback(PrefChangedFunc aCallback, |
766 | | const char* aPref, |
767 | | void* aClosure, |
768 | | MatchKind aMatchKind, |
769 | | bool aIsPriority = false) |
770 | | { |
771 | | return RegisterCallback( |
772 | | aCallback, nsDependentCString(aPref), aClosure, aMatchKind, aIsPriority); |
773 | | } |
774 | | static nsresult UnregisterCallback(PrefChangedFunc aCallback, |
775 | | const char* aPref, |
776 | | void* aClosure, |
777 | | MatchKind aMatchKind) |
778 | | { |
779 | | return UnregisterCallback( |
780 | | aCallback, nsDependentCString(aPref), aClosure, aMatchKind); |
781 | | } |
782 | | static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback, |
783 | | const char* aPref, |
784 | | void* aClosure, |
785 | | MatchKind aMatchKind) |
786 | | { |
787 | | return RegisterCallbackAndCall( |
788 | | aCallback, nsDependentCString(aPref), aClosure, aMatchKind); |
789 | | } |
790 | | |
791 | | private: |
792 | | nsCOMPtr<nsIFile> mCurrentFile; |
793 | | bool mDirty = false; |
794 | | bool mProfileShutdown = false; |
795 | | // We wait a bit after prefs are dirty before writing them. In this period, |
796 | | // mDirty and mSavePending will both be true. |
797 | | bool mSavePending = false; |
798 | | |
799 | | nsCOMPtr<nsIPrefBranch> mRootBranch; |
800 | | nsCOMPtr<nsIPrefBranch> mDefaultRootBranch; |
801 | | |
802 | | static StaticRefPtr<Preferences> sPreferences; |
803 | | static bool sShutdown; |
804 | | |
805 | | // Init static members. Returns true on success. |
806 | | static bool InitStaticMembers(); |
807 | | }; |
808 | | |
809 | | } // namespace mozilla |
810 | | |
811 | | #endif // mozilla_Preferences_h |