michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_Preferences_h michael@0: #define mozilla_Preferences_h michael@0: michael@0: #ifndef MOZILLA_INTERNAL_API michael@0: #error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)." michael@0: #endif michael@0: michael@0: #include "nsIPrefService.h" michael@0: #include "nsIPrefBranch.h" michael@0: #include "nsIPrefBranchInternal.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsTArray.h" michael@0: #include "nsWeakReference.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: michael@0: class nsIFile; michael@0: class nsCString; michael@0: class nsString; michael@0: class nsAdoptingString; michael@0: class nsAdoptingCString; michael@0: michael@0: #ifndef have_PrefChangedFunc_typedef michael@0: typedef void (*PrefChangedFunc)(const char *, void *); michael@0: #define have_PrefChangedFunc_typedef michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace dom { michael@0: class PrefSetting; michael@0: } michael@0: michael@0: class Preferences : public nsIPrefService, michael@0: public nsIObserver, michael@0: public nsIPrefBranchInternal, michael@0: public nsSupportsWeakReference michael@0: { michael@0: public: michael@0: typedef mozilla::dom::PrefSetting PrefSetting; michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIPREFSERVICE michael@0: NS_FORWARD_NSIPREFBRANCH(sRootBranch->) michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: Preferences(); michael@0: virtual ~Preferences(); michael@0: michael@0: nsresult Init(); michael@0: michael@0: /** michael@0: * Reset loaded user prefs then read them michael@0: */ michael@0: static nsresult ResetAndReadUserPrefs(); michael@0: michael@0: /** michael@0: * Returns the singleton instance which is addreffed. michael@0: */ michael@0: static Preferences* GetInstanceForService(); michael@0: michael@0: /** michael@0: * Finallizes global members. michael@0: */ michael@0: static void Shutdown(); michael@0: michael@0: /** michael@0: * Returns shared pref service instance michael@0: * NOTE: not addreffed. michael@0: */ michael@0: static nsIPrefService* GetService() michael@0: { michael@0: NS_ENSURE_TRUE(InitStaticMembers(), nullptr); michael@0: return sPreferences; michael@0: } michael@0: michael@0: /** michael@0: * Returns shared pref branch instance. michael@0: * NOTE: not addreffed. michael@0: */ michael@0: static nsIPrefBranch* GetRootBranch() michael@0: { michael@0: NS_ENSURE_TRUE(InitStaticMembers(), nullptr); michael@0: return sRootBranch; michael@0: } michael@0: michael@0: /** michael@0: * Returns shared default pref branch instance. michael@0: * NOTE: not addreffed. michael@0: */ michael@0: static nsIPrefBranch* GetDefaultRootBranch() michael@0: { michael@0: NS_ENSURE_TRUE(InitStaticMembers(), nullptr); michael@0: return sDefaultRootBranch; michael@0: } michael@0: michael@0: /** michael@0: * Gets int or bool type pref value with default value if failed to get michael@0: * the pref. michael@0: */ michael@0: static bool GetBool(const char* aPref, bool aDefault = false) michael@0: { michael@0: bool result = aDefault; michael@0: GetBool(aPref, &result); michael@0: return result; michael@0: } michael@0: michael@0: static int32_t GetInt(const char* aPref, int32_t aDefault = 0) michael@0: { michael@0: int32_t result = aDefault; michael@0: GetInt(aPref, &result); michael@0: return result; michael@0: } michael@0: michael@0: static uint32_t GetUint(const char* aPref, uint32_t aDefault = 0) michael@0: { michael@0: uint32_t result = aDefault; michael@0: GetUint(aPref, &result); michael@0: return result; michael@0: } michael@0: michael@0: static float GetFloat(const char* aPref, float aDefault = 0) michael@0: { michael@0: float result = aDefault; michael@0: GetFloat(aPref, &result); michael@0: return result; michael@0: } michael@0: michael@0: /** michael@0: * Gets char type pref value directly. If failed, the get() of result michael@0: * returns nullptr. Even if succeeded but the result was empty string, the michael@0: * get() does NOT return nullptr. So, you can check whether the method michael@0: * succeeded or not by: michael@0: * michael@0: * nsAdoptingString value = Prefereces::GetString("foo.bar"); michael@0: * if (!value) { michael@0: * // failed michael@0: * } michael@0: * michael@0: * Be aware. If you wrote as: michael@0: * michael@0: * nsAutoString value = Preferences::GetString("foo.bar"); michael@0: * if (!value.get()) { michael@0: * // the condition is always FALSE!! michael@0: * } michael@0: * michael@0: * The value.get() doesn't return nullptr. You must use nsAdoptingString michael@0: * when you need to check whether it was failure or not. michael@0: */ michael@0: static nsAdoptingCString GetCString(const char* aPref); michael@0: static nsAdoptingString GetString(const char* aPref); michael@0: static nsAdoptingCString GetLocalizedCString(const char* aPref); michael@0: static nsAdoptingString GetLocalizedString(const char* aPref); michael@0: michael@0: /** michael@0: * Gets int, float, or bool type pref value with raw return value of michael@0: * nsIPrefBranch. michael@0: * michael@0: * @param aPref A pref name. michael@0: * @param aResult Must not be nullptr. The value is never modified michael@0: * when these methods fail. michael@0: */ michael@0: static nsresult GetBool(const char* aPref, bool* aResult); michael@0: static nsresult GetInt(const char* aPref, int32_t* aResult); michael@0: static nsresult GetFloat(const char* aPref, float* aResult); michael@0: static nsresult GetUint(const char* aPref, uint32_t* aResult) michael@0: { michael@0: int32_t result; michael@0: nsresult rv = GetInt(aPref, &result); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: *aResult = static_cast(result); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: /** michael@0: * Gets string type pref value with raw return value of nsIPrefBranch. michael@0: * michael@0: * @param aPref A pref name. michael@0: * @param aResult Must not be nullptr. The value is never modified michael@0: * when these methods fail. michael@0: */ michael@0: static nsresult GetCString(const char* aPref, nsACString* aResult); michael@0: static nsresult GetString(const char* aPref, nsAString* aResult); michael@0: static nsresult GetLocalizedCString(const char* aPref, nsACString* aResult); michael@0: static nsresult GetLocalizedString(const char* aPref, nsAString* aResult); michael@0: michael@0: static nsresult GetComplex(const char* aPref, const nsIID &aType, michael@0: void** aResult); michael@0: michael@0: /** michael@0: * Sets various type pref values. michael@0: */ michael@0: static nsresult SetBool(const char* aPref, bool aValue); michael@0: static nsresult SetInt(const char* aPref, int32_t aValue); michael@0: static nsresult SetUint(const char* aPref, uint32_t aValue) michael@0: { michael@0: return SetInt(aPref, static_cast(aValue)); michael@0: } michael@0: static nsresult SetCString(const char* aPref, const char* aValue); michael@0: static nsresult SetCString(const char* aPref, const nsACString &aValue); michael@0: static nsresult SetString(const char* aPref, const char16_t* aValue); michael@0: static nsresult SetString(const char* aPref, const nsAString &aValue); michael@0: michael@0: static nsresult SetComplex(const char* aPref, const nsIID &aType, michael@0: nsISupports* aValue); michael@0: michael@0: /** michael@0: * Clears user set pref. michael@0: */ michael@0: static nsresult ClearUser(const char* aPref); michael@0: michael@0: /** michael@0: * Whether the pref has a user value or not. michael@0: */ michael@0: static bool HasUserValue(const char* aPref); michael@0: michael@0: /** michael@0: * Gets the type of the pref. michael@0: */ michael@0: static int32_t GetType(const char* aPref); michael@0: michael@0: /** michael@0: * Adds/Removes the observer for the root pref branch. michael@0: * The observer is referenced strongly if AddStrongObserver is used. On the michael@0: * other hand, it is referenced weakly, if AddWeakObserver is used. michael@0: * See nsIPrefBranch.idl for details. michael@0: */ michael@0: static nsresult AddStrongObserver(nsIObserver* aObserver, const char* aPref); michael@0: static nsresult AddWeakObserver(nsIObserver* aObserver, const char* aPref); michael@0: static nsresult RemoveObserver(nsIObserver* aObserver, const char* aPref); michael@0: michael@0: /** michael@0: * Adds/Removes two or more observers for the root pref branch. michael@0: * Pass to aPrefs an array of const char* whose last item is nullptr. michael@0: */ michael@0: static nsresult AddStrongObservers(nsIObserver* aObserver, michael@0: const char** aPrefs); michael@0: static nsresult AddWeakObservers(nsIObserver* aObserver, michael@0: const char** aPrefs); michael@0: static nsresult RemoveObservers(nsIObserver* aObserver, michael@0: const char** aPrefs); michael@0: michael@0: /** michael@0: * Registers/Unregisters the callback function for the aPref. michael@0: */ michael@0: static nsresult RegisterCallback(PrefChangedFunc aCallback, michael@0: const char* aPref, michael@0: void* aClosure = nullptr); michael@0: static nsresult UnregisterCallback(PrefChangedFunc aCallback, michael@0: const char* aPref, michael@0: void* aClosure = nullptr); michael@0: // Like RegisterCallback, but also calls the callback immediately for michael@0: // initialization. michael@0: static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback, michael@0: const char* aPref, michael@0: void* aClosure = nullptr); michael@0: michael@0: /** michael@0: * Adds the aVariable to cache table. aVariable must be a pointer for a michael@0: * static variable. The value will be modified when the pref value is michael@0: * changed but note that even if you modified it, the value isn't assigned to michael@0: * the pref. michael@0: */ michael@0: static nsresult AddBoolVarCache(bool* aVariable, michael@0: const char* aPref, michael@0: bool aDefault = false); michael@0: static nsresult AddIntVarCache(int32_t* aVariable, michael@0: const char* aPref, michael@0: int32_t aDefault = 0); michael@0: static nsresult AddUintVarCache(uint32_t* aVariable, michael@0: const char* aPref, michael@0: uint32_t aDefault = 0); michael@0: static nsresult AddFloatVarCache(float* aVariable, michael@0: const char* aPref, michael@0: float aDefault = 0.0f); michael@0: michael@0: /** michael@0: * Gets the default bool, int or uint value of the pref. michael@0: * The result is raw result of nsIPrefBranch::Get*Pref(). michael@0: * If the pref could have any value, you needed to use these methods. michael@0: * If not so, you could use below methods. michael@0: */ michael@0: static nsresult GetDefaultBool(const char* aPref, bool* aResult); michael@0: static nsresult GetDefaultInt(const char* aPref, int32_t* aResult); michael@0: static nsresult GetDefaultUint(const char* aPref, uint32_t* aResult) michael@0: { michael@0: return GetDefaultInt(aPref, reinterpret_cast(aResult)); michael@0: } michael@0: michael@0: /** michael@0: * Gets the default bool, int or uint value of the pref directly. michael@0: * You can set an invalid value of the pref to aFailedResult. If these michael@0: * methods failed to get the default value, they would return the michael@0: * aFailedResult value. michael@0: */ michael@0: static bool GetDefaultBool(const char* aPref, bool aFailedResult) michael@0: { michael@0: bool result; michael@0: return NS_SUCCEEDED(GetDefaultBool(aPref, &result)) ? result : michael@0: aFailedResult; michael@0: } michael@0: static int32_t GetDefaultInt(const char* aPref, int32_t aFailedResult) michael@0: { michael@0: int32_t result; michael@0: return NS_SUCCEEDED(GetDefaultInt(aPref, &result)) ? result : aFailedResult; michael@0: } michael@0: static uint32_t GetDefaultUint(const char* aPref, uint32_t aFailedResult) michael@0: { michael@0: return static_cast( michael@0: GetDefaultInt(aPref, static_cast(aFailedResult))); michael@0: } michael@0: michael@0: /** michael@0: * Gets the default value of the char type pref. michael@0: * If the get() of the result returned nullptr, that meant the value didn't michael@0: * have default value. michael@0: * michael@0: * See the comment at definition at GetString() and GetCString() for more michael@0: * details of the result. michael@0: */ michael@0: static nsAdoptingString GetDefaultString(const char* aPref); michael@0: static nsAdoptingCString GetDefaultCString(const char* aPref); michael@0: static nsAdoptingString GetDefaultLocalizedString(const char* aPref); michael@0: static nsAdoptingCString GetDefaultLocalizedCString(const char* aPref); michael@0: michael@0: static nsresult GetDefaultCString(const char* aPref, nsACString* aResult); michael@0: static nsresult GetDefaultString(const char* aPref, nsAString* aResult); michael@0: static nsresult GetDefaultLocalizedCString(const char* aPref, michael@0: nsACString* aResult); michael@0: static nsresult GetDefaultLocalizedString(const char* aPref, michael@0: nsAString* aResult); michael@0: michael@0: static nsresult GetDefaultComplex(const char* aPref, const nsIID &aType, michael@0: void** aResult); michael@0: michael@0: /** michael@0: * Gets the type of the pref. michael@0: */ michael@0: static int32_t GetDefaultType(const char* aPref); michael@0: michael@0: // Used to synchronise preferences between chrome and content processes. michael@0: static void GetPreferences(InfallibleTArray* aPrefs); michael@0: static void GetPreference(PrefSetting* aPref); michael@0: static void SetPreference(const PrefSetting& aPref); michael@0: michael@0: static int64_t SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf); michael@0: static nsresult SetFloat(const char* aPref, float aValue); michael@0: michael@0: protected: michael@0: nsresult NotifyServiceObservers(const char *aSubject); michael@0: /** michael@0: * Reads the default pref file or, if that failed, try to save a new one. michael@0: * michael@0: * @return NS_OK if either action succeeded, michael@0: * or the error code related to the read attempt. michael@0: */ michael@0: nsresult UseDefaultPrefFile(); michael@0: nsresult UseUserPrefFile(); michael@0: nsresult ReadAndOwnUserPrefFile(nsIFile *aFile); michael@0: nsresult ReadAndOwnSharedUserPrefFile(nsIFile *aFile); michael@0: nsresult SavePrefFileInternal(nsIFile* aFile); michael@0: nsresult WritePrefFile(nsIFile* aFile); michael@0: nsresult MakeBackupPrefFile(nsIFile *aFile); michael@0: michael@0: private: michael@0: nsCOMPtr mCurrentFile; michael@0: michael@0: static Preferences* sPreferences; michael@0: static nsIPrefBranch* sRootBranch; michael@0: static nsIPrefBranch* sDefaultRootBranch; michael@0: static bool sShutdown; michael@0: michael@0: /** michael@0: * Init static members. TRUE if it succeeded. Otherwise, FALSE. michael@0: */ michael@0: static bool InitStaticMembers(); michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_Preferences_h