Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef mozilla_Preferences_h
7 : #define mozilla_Preferences_h
8 :
9 : #ifndef MOZILLA_INTERNAL_API
10 : #error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)."
11 : #endif
12 :
13 : #include "nsIPrefService.h"
14 : #include "nsIPrefBranch.h"
15 : #include "nsIPrefBranchInternal.h"
16 : #include "nsIObserver.h"
17 : #include "nsCOMPtr.h"
18 : #include "nsTArray.h"
19 : #include "nsWeakReference.h"
20 : #include "mozilla/Atomics.h"
21 : #include "mozilla/MemoryReporting.h"
22 :
23 : class nsIFile;
24 : class nsAdoptingString;
25 : class nsAdoptingCString;
26 :
27 : #ifndef have_PrefChangedFunc_typedef
28 : typedef void (*PrefChangedFunc)(const char *, void *);
29 : #define have_PrefChangedFunc_typedef
30 : #endif
31 :
32 : #ifdef DEBUG
33 : enum pref_initPhase {
34 : START,
35 : BEGIN_INIT_PREFS,
36 : END_INIT_PREFS,
37 : BEGIN_ALL_PREFS,
38 : END_ALL_PREFS
39 : };
40 :
41 : #define SET_PREF_PHASE(p) Preferences::SetInitPhase(p)
42 : #else
43 : #define SET_PREF_PHASE(p) do { } while (0)
44 : #endif
45 :
46 : namespace mozilla {
47 :
48 : namespace dom {
49 : class PrefSetting;
50 : } // namespace dom
51 :
52 : class Preferences final : public nsIPrefService,
53 : public nsIObserver,
54 : public nsIPrefBranchInternal,
55 : public nsSupportsWeakReference
56 : {
57 : public:
58 : typedef mozilla::dom::PrefSetting PrefSetting;
59 :
60 : NS_DECL_THREADSAFE_ISUPPORTS
61 : NS_DECL_NSIPREFSERVICE
62 897 : NS_FORWARD_NSIPREFBRANCH(sRootBranch->)
63 : NS_DECL_NSIOBSERVER
64 :
65 : Preferences();
66 :
67 : nsresult Init();
68 :
69 : /**
70 : * Returns true if the Preferences service is available, false otherwise.
71 : */
72 : static bool IsServiceAvailable();
73 :
74 : /**
75 : * Reset loaded user prefs then read them
76 : */
77 : static nsresult ResetAndReadUserPrefs();
78 :
79 : /**
80 : * Returns the singleton instance which is addreffed.
81 : */
82 : static Preferences* GetInstanceForService();
83 :
84 : /**
85 : * Finallizes global members.
86 : */
87 : static void Shutdown();
88 :
89 : /**
90 : * Returns shared pref service instance
91 : * NOTE: not addreffed.
92 : */
93 0 : static nsIPrefService* GetService()
94 : {
95 0 : NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
96 0 : return sPreferences;
97 : }
98 :
99 : /**
100 : * Returns shared pref branch instance.
101 : * NOTE: not addreffed.
102 : */
103 24 : static nsIPrefBranch* GetRootBranch()
104 : {
105 24 : NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
106 24 : return sRootBranch;
107 : }
108 :
109 : /**
110 : * Returns shared default pref branch instance.
111 : * NOTE: not addreffed.
112 : */
113 0 : static nsIPrefBranch* GetDefaultRootBranch()
114 : {
115 0 : NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
116 0 : return sDefaultRootBranch;
117 : }
118 :
119 : /**
120 : * Gets int or bool type pref value with default value if failed to get
121 : * the pref.
122 : */
123 3658 : static bool GetBool(const char* aPref, bool aDefault = false)
124 : {
125 3658 : bool result = aDefault;
126 3658 : GetBool(aPref, &result);
127 3658 : return result;
128 : }
129 :
130 1171 : static int32_t GetInt(const char* aPref, int32_t aDefault = 0)
131 : {
132 1171 : int32_t result = aDefault;
133 1171 : GetInt(aPref, &result);
134 1171 : return result;
135 : }
136 :
137 227 : static uint32_t GetUint(const char* aPref, uint32_t aDefault = 0)
138 : {
139 227 : uint32_t result = aDefault;
140 227 : GetUint(aPref, &result);
141 227 : return result;
142 : }
143 :
144 142 : static float GetFloat(const char* aPref, float aDefault = 0)
145 : {
146 142 : float result = aDefault;
147 142 : GetFloat(aPref, &result);
148 142 : return result;
149 : }
150 :
151 : /**
152 : * Gets char type pref value directly. If failed, the get() of result
153 : * returns nullptr. Even if succeeded but the result was empty string, the
154 : * get() does NOT return nullptr. So, you can check whether the method
155 : * succeeded or not by:
156 : *
157 : * nsAdoptingString value = Prefereces::GetString("foo.bar");
158 : * if (!value) {
159 : * // failed
160 : * }
161 : *
162 : * Be aware. If you wrote as:
163 : *
164 : * nsAutoString value = Preferences::GetString("foo.bar");
165 : * if (!value.get()) {
166 : * // the condition is always FALSE!!
167 : * }
168 : *
169 : * The value.get() doesn't return nullptr. You must use nsAdoptingString
170 : * when you need to check whether it was failure or not.
171 : */
172 : static nsAdoptingCString GetCString(const char* aPref);
173 : static nsAdoptingString GetString(const char* aPref);
174 : static nsAdoptingCString GetLocalizedCString(const char* aPref);
175 : static nsAdoptingString GetLocalizedString(const char* aPref);
176 :
177 : /**
178 : * Gets int, float, or bool type pref value with raw return value of
179 : * nsIPrefBranch.
180 : *
181 : * @param aPref A pref name.
182 : * @param aResult Must not be nullptr. The value is never modified
183 : * when these methods fail.
184 : */
185 : static nsresult GetBool(const char* aPref, bool* aResult);
186 : static nsresult GetInt(const char* aPref, int32_t* aResult);
187 : static nsresult GetFloat(const char* aPref, float* aResult);
188 227 : static nsresult GetUint(const char* aPref, uint32_t* aResult)
189 : {
190 : int32_t result;
191 227 : nsresult rv = GetInt(aPref, &result);
192 227 : if (NS_SUCCEEDED(rv)) {
193 165 : *aResult = static_cast<uint32_t>(result);
194 : }
195 227 : return rv;
196 : }
197 :
198 : /**
199 : * Gets string type pref value with raw return value of nsIPrefBranch.
200 : *
201 : * @param aPref A pref name.
202 : * @param aResult Must not be nullptr. The value is never modified
203 : * when these methods fail.
204 : */
205 : static nsresult GetCString(const char* aPref, nsACString* aResult);
206 : static nsresult GetString(const char* aPref, nsAString* aResult);
207 : static nsresult GetLocalizedCString(const char* aPref, nsACString* aResult);
208 : static nsresult GetLocalizedString(const char* aPref, nsAString* aResult);
209 :
210 : static nsresult GetComplex(const char* aPref, const nsIID &aType,
211 : void** aResult);
212 :
213 : /**
214 : * Sets various type pref values.
215 : */
216 : static nsresult SetBool(const char* aPref, bool aValue);
217 : static nsresult SetInt(const char* aPref, int32_t aValue);
218 0 : static nsresult SetUint(const char* aPref, uint32_t aValue)
219 : {
220 0 : return SetInt(aPref, static_cast<int32_t>(aValue));
221 : }
222 : static nsresult SetFloat(const char* aPref, float aValue);
223 : static nsresult SetCString(const char* aPref, const char* aValue);
224 : static nsresult SetCString(const char* aPref, const nsACString &aValue);
225 : static nsresult SetString(const char* aPref, const char16ptr_t aValue);
226 : static nsresult SetString(const char* aPref, const nsAString &aValue);
227 :
228 : static nsresult SetComplex(const char* aPref, const nsIID &aType,
229 : nsISupports* aValue);
230 :
231 : /**
232 : * Clears user set pref.
233 : */
234 : static nsresult ClearUser(const char* aPref);
235 :
236 : /**
237 : * Whether the pref has a user value or not.
238 : */
239 : static bool HasUserValue(const char* aPref);
240 :
241 : /**
242 : * Gets the type of the pref.
243 : */
244 : static int32_t GetType(const char* aPref);
245 :
246 : /**
247 : * Adds/Removes the observer for the root pref branch.
248 : * The observer is referenced strongly if AddStrongObserver is used. On the
249 : * other hand, it is referenced weakly, if AddWeakObserver is used.
250 : * See nsIPrefBranch.idl for details.
251 : */
252 : static nsresult AddStrongObserver(nsIObserver* aObserver, const char* aPref);
253 : static nsresult AddWeakObserver(nsIObserver* aObserver, const char* aPref);
254 : static nsresult RemoveObserver(nsIObserver* aObserver, const char* aPref);
255 :
256 : /**
257 : * Adds/Removes two or more observers for the root pref branch.
258 : * Pass to aPrefs an array of const char* whose last item is nullptr.
259 : */
260 : static nsresult AddStrongObservers(nsIObserver* aObserver,
261 : const char** aPrefs);
262 : static nsresult AddWeakObservers(nsIObserver* aObserver,
263 : const char** aPrefs);
264 : static nsresult RemoveObservers(nsIObserver* aObserver,
265 : const char** aPrefs);
266 :
267 : /**
268 : * Registers/Unregisters the callback function for the aPref.
269 : */
270 714 : static nsresult RegisterCallback(PrefChangedFunc aCallback,
271 : const char* aPref,
272 : void* aClosure = nullptr)
273 : {
274 714 : return RegisterCallback(aCallback, aPref, aClosure, ExactMatch);
275 : }
276 0 : static nsresult UnregisterCallback(PrefChangedFunc aCallback,
277 : const char* aPref,
278 : void* aClosure = nullptr)
279 : {
280 0 : return UnregisterCallback(aCallback, aPref, aClosure, ExactMatch);
281 : }
282 : // Like RegisterCallback, but also calls the callback immediately for
283 : // initialization.
284 108 : static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
285 : const char* aPref,
286 : void* aClosure = nullptr)
287 : {
288 108 : return RegisterCallbackAndCall(aCallback, aPref, aClosure, ExactMatch);
289 : }
290 :
291 : /**
292 : * Like RegisterCallback, but registers a callback for a prefix of multiple
293 : * pref names, not a single pref name.
294 : */
295 119 : static nsresult RegisterPrefixCallback(PrefChangedFunc aCallback,
296 : const char* aPref,
297 : void* aClosure = nullptr)
298 : {
299 119 : return RegisterCallback(aCallback, aPref, aClosure, PrefixMatch);
300 : }
301 :
302 : /**
303 : * Like RegisterPrefixCallback, but also calls the callback immediately for
304 : * initialization.
305 : */
306 2 : static nsresult RegisterPrefixCallbackAndCall(PrefChangedFunc aCallback,
307 : const char* aPref,
308 : void* aClosure = nullptr)
309 : {
310 2 : return RegisterCallbackAndCall(aCallback, aPref, aClosure, PrefixMatch);
311 : }
312 :
313 : /**
314 : * Unregister a callback registered with RegisterPrefixCallback or
315 : * RegisterPrefixCallbackAndCall.
316 : */
317 0 : static nsresult UnregisterPrefixCallback(PrefChangedFunc aCallback,
318 : const char* aPref,
319 : void* aClosure = nullptr)
320 : {
321 0 : return UnregisterCallback(aCallback, aPref, aClosure, PrefixMatch);
322 : }
323 :
324 : /**
325 : * Adds the aVariable to cache table. aVariable must be a pointer for a
326 : * static variable. The value will be modified when the pref value is
327 : * changed but note that even if you modified it, the value isn't assigned to
328 : * the pref.
329 : */
330 : static nsresult AddBoolVarCache(bool* aVariable,
331 : const char* aPref,
332 : bool aDefault = false);
333 : static nsresult AddIntVarCache(int32_t* aVariable,
334 : const char* aPref,
335 : int32_t aDefault = 0);
336 : static nsresult AddUintVarCache(uint32_t* aVariable,
337 : const char* aPref,
338 : uint32_t aDefault = 0);
339 : template <MemoryOrdering Order>
340 : static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable,
341 : const char* aPref,
342 : uint32_t aDefault = 0);
343 : static nsresult AddFloatVarCache(float* aVariable,
344 : const char* aPref,
345 : float aDefault = 0.0f);
346 :
347 : /**
348 : * Gets the default bool, int or uint value of the pref.
349 : * The result is raw result of nsIPrefBranch::Get*Pref().
350 : * If the pref could have any value, you needed to use these methods.
351 : * If not so, you could use below methods.
352 : */
353 : static nsresult GetDefaultBool(const char* aPref, bool* aResult);
354 : static nsresult GetDefaultInt(const char* aPref, int32_t* aResult);
355 : static nsresult GetDefaultUint(const char* aPref, uint32_t* aResult)
356 : {
357 : return GetDefaultInt(aPref, reinterpret_cast<int32_t*>(aResult));
358 : }
359 :
360 : /**
361 : * Gets the default bool, int or uint value of the pref directly.
362 : * You can set an invalid value of the pref to aFailedResult. If these
363 : * methods failed to get the default value, they would return the
364 : * aFailedResult value.
365 : */
366 0 : static bool GetDefaultBool(const char* aPref, bool aFailedResult)
367 : {
368 : bool result;
369 0 : return NS_SUCCEEDED(GetDefaultBool(aPref, &result)) ? result :
370 0 : aFailedResult;
371 : }
372 4 : static int32_t GetDefaultInt(const char* aPref, int32_t aFailedResult)
373 : {
374 : int32_t result;
375 4 : return NS_SUCCEEDED(GetDefaultInt(aPref, &result)) ? result : aFailedResult;
376 : }
377 : static uint32_t GetDefaultUint(const char* aPref, uint32_t aFailedResult)
378 : {
379 : return static_cast<uint32_t>(
380 : GetDefaultInt(aPref, static_cast<int32_t>(aFailedResult)));
381 : }
382 :
383 : /**
384 : * Gets the default value of the char type pref.
385 : * If the get() of the result returned nullptr, that meant the value didn't
386 : * have default value.
387 : *
388 : * See the comment at definition at GetString() and GetCString() for more
389 : * details of the result.
390 : */
391 : static nsAdoptingString GetDefaultString(const char* aPref);
392 : static nsAdoptingCString GetDefaultCString(const char* aPref);
393 : static nsAdoptingString GetDefaultLocalizedString(const char* aPref);
394 : static nsAdoptingCString GetDefaultLocalizedCString(const char* aPref);
395 :
396 : static nsresult GetDefaultCString(const char* aPref, nsACString* aResult);
397 : static nsresult GetDefaultString(const char* aPref, nsAString* aResult);
398 : static nsresult GetDefaultLocalizedCString(const char* aPref,
399 : nsACString* aResult);
400 : static nsresult GetDefaultLocalizedString(const char* aPref,
401 : nsAString* aResult);
402 :
403 : static nsresult GetDefaultComplex(const char* aPref, const nsIID &aType,
404 : void** aResult);
405 :
406 : /**
407 : * Gets the type of the pref.
408 : */
409 : static int32_t GetDefaultType(const char* aPref);
410 :
411 : // Used to synchronise preferences between chrome and content processes.
412 : static void GetPreferences(InfallibleTArray<PrefSetting>* aPrefs);
413 : static void GetPreference(PrefSetting* aPref);
414 : static void SetPreference(const PrefSetting& aPref);
415 :
416 : static void SetInitPreferences(nsTArray<PrefSetting>* aPrefs);
417 :
418 : #ifdef DEBUG
419 : static void SetInitPhase(pref_initPhase phase);
420 : static pref_initPhase InitPhase();
421 : #endif
422 :
423 : static int64_t SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf);
424 :
425 : static void DirtyCallback();
426 :
427 : // Explicitly choosing synchronous or asynchronous (if allowed)
428 : // preferences file write. Only for the default file. The guarantee
429 : // for the "blocking" is that when it returns, the file on disk
430 : // reflect the current state of preferences.
431 : nsresult SavePrefFileBlocking();
432 : nsresult SavePrefFileAsynchronous();
433 :
434 : protected:
435 : virtual ~Preferences();
436 :
437 : nsresult NotifyServiceObservers(const char *aSubject);
438 : /**
439 : * Reads the default pref file or, if that failed, try to save a new one.
440 : *
441 : * @return NS_OK if either action succeeded,
442 : * or the error code related to the read attempt.
443 : */
444 : nsresult UseDefaultPrefFile();
445 : void UseUserPrefFile();
446 : nsresult MakeBackupPrefFile(nsIFile *aFile);
447 :
448 : // Default pref file save can be blocking or not.
449 : enum class SaveMethod {
450 : Blocking,
451 : Asynchronous
452 : };
453 :
454 : // Off main thread is only respected for the default aFile value (nullptr)
455 : nsresult SavePrefFileInternal(nsIFile* aFile, SaveMethod aSaveMethod);
456 : nsresult WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod);
457 :
458 : // If this is false, only blocking writes, on main thread are allowed.
459 : bool AllowOffMainThreadSave();
460 :
461 : /**
462 : * Helpers for implementing
463 : * Register(Prefix)Callback/Unregister(Prefix)Callback.
464 : */
465 : public:
466 : // Public so the ValueObserver classes can use it.
467 : enum MatchKind {
468 : PrefixMatch,
469 : ExactMatch,
470 : };
471 :
472 : protected:
473 : static nsresult RegisterCallback(PrefChangedFunc aCallback,
474 : const char* aPref,
475 : void* aClosure,
476 : MatchKind aMatchKind);
477 : static nsresult UnregisterCallback(PrefChangedFunc aCallback,
478 : const char* aPref,
479 : void* aClosure,
480 : MatchKind aMatchKind);
481 : static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
482 : const char* aPref,
483 : void* aClosure,
484 : MatchKind aMatchKind);
485 :
486 : private:
487 : nsCOMPtr<nsIFile> mCurrentFile;
488 : bool mDirty = false;
489 : bool mProfileShutdown = false;
490 :
491 : static Preferences* sPreferences;
492 : static nsIPrefBranch* sRootBranch;
493 : static nsIPrefBranch* sDefaultRootBranch;
494 : static bool sShutdown;
495 :
496 : /**
497 : * Init static members. TRUE if it succeeded. Otherwise, FALSE.
498 : */
499 : static bool InitStaticMembers();
500 : };
501 :
502 : } // namespace mozilla
503 :
504 : #endif // mozilla_Preferences_h
|