1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/libpref/src/nsPrefBranch.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,266 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsPrefBranch_h 1.10 +#define nsPrefBranch_h 1.11 + 1.12 +#include "nsCOMPtr.h" 1.13 +#include "nsIObserver.h" 1.14 +#include "nsIPrefBranch.h" 1.15 +#include "nsIPrefBranchInternal.h" 1.16 +#include "nsIPrefLocalizedString.h" 1.17 +#include "nsXPCOM.h" 1.18 +#include "nsISupportsPrimitives.h" 1.19 +#include "nsIRelativeFilePref.h" 1.20 +#include "nsIFile.h" 1.21 +#include "nsString.h" 1.22 +#include "nsTArray.h" 1.23 +#include "nsWeakReference.h" 1.24 +#include "nsClassHashtable.h" 1.25 +#include "nsCRT.h" 1.26 +#include "nsISupportsImpl.h" 1.27 +#include "mozilla/HashFunctions.h" 1.28 +#include "mozilla/MemoryReporting.h" 1.29 + 1.30 +namespace mozilla { 1.31 +class PreferenceServiceReporter; 1.32 +} // namespace mozilla; 1.33 + 1.34 +class nsPrefBranch; 1.35 + 1.36 +class PrefCallback : public PLDHashEntryHdr { 1.37 + friend class mozilla::PreferenceServiceReporter; 1.38 + 1.39 + public: 1.40 + typedef PrefCallback* KeyType; 1.41 + typedef const PrefCallback* KeyTypePointer; 1.42 + 1.43 + static const PrefCallback* KeyToPointer(PrefCallback *aKey) 1.44 + { 1.45 + return aKey; 1.46 + } 1.47 + 1.48 + static PLDHashNumber HashKey(const PrefCallback *aKey) 1.49 + { 1.50 + uint32_t hash = mozilla::HashString(aKey->mDomain); 1.51 + return mozilla::AddToHash(hash, aKey->mCanonical); 1.52 + } 1.53 + 1.54 + 1.55 + public: 1.56 + // Create a PrefCallback with a strong reference to its observer. 1.57 + PrefCallback(const char *aDomain, nsIObserver *aObserver, 1.58 + nsPrefBranch *aBranch) 1.59 + : mDomain(aDomain), 1.60 + mBranch(aBranch), 1.61 + mWeakRef(nullptr), 1.62 + mStrongRef(aObserver) 1.63 + { 1.64 + MOZ_COUNT_CTOR(PrefCallback); 1.65 + nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver); 1.66 + mCanonical = canonical; 1.67 + } 1.68 + 1.69 + // Create a PrefCallback with a weak reference to its observer. 1.70 + PrefCallback(const char *aDomain, 1.71 + nsISupportsWeakReference *aObserver, 1.72 + nsPrefBranch *aBranch) 1.73 + : mDomain(aDomain), 1.74 + mBranch(aBranch), 1.75 + mWeakRef(do_GetWeakReference(aObserver)), 1.76 + mStrongRef(nullptr) 1.77 + { 1.78 + MOZ_COUNT_CTOR(PrefCallback); 1.79 + nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver); 1.80 + mCanonical = canonical; 1.81 + } 1.82 + 1.83 + // Copy constructor needs to be explicit or the linker complains. 1.84 + PrefCallback(const PrefCallback *&aCopy) 1.85 + : mDomain(aCopy->mDomain), 1.86 + mBranch(aCopy->mBranch), 1.87 + mWeakRef(aCopy->mWeakRef), 1.88 + mStrongRef(aCopy->mStrongRef), 1.89 + mCanonical(aCopy->mCanonical) 1.90 + { 1.91 + MOZ_COUNT_CTOR(PrefCallback); 1.92 + } 1.93 + 1.94 + ~PrefCallback() 1.95 + { 1.96 + MOZ_COUNT_DTOR(PrefCallback); 1.97 + } 1.98 + 1.99 + bool KeyEquals(const PrefCallback *aKey) const 1.100 + { 1.101 + // We want to be able to look up a weakly-referencing PrefCallback after 1.102 + // its observer has died so we can remove it from the table. Once the 1.103 + // callback's observer dies, its canonical pointer is stale -- in 1.104 + // particular, we may have allocated a new observer in the same spot in 1.105 + // memory! So we can't just compare canonical pointers to determine 1.106 + // whether aKey refers to the same observer as this. 1.107 + // 1.108 + // Our workaround is based on the way we use this hashtable: When we ask 1.109 + // the hashtable to remove a PrefCallback whose weak reference has 1.110 + // expired, we use as the key for removal the same object as was inserted 1.111 + // into the hashtable. Thus we can say that if one of the keys' weak 1.112 + // references has expired, the two keys are equal iff they're the same 1.113 + // object. 1.114 + 1.115 + if (IsExpired() || aKey->IsExpired()) 1.116 + return this == aKey; 1.117 + 1.118 + if (mCanonical != aKey->mCanonical) 1.119 + return false; 1.120 + 1.121 + return mDomain.Equals(aKey->mDomain); 1.122 + } 1.123 + 1.124 + PrefCallback *GetKey() const 1.125 + { 1.126 + return const_cast<PrefCallback*>(this); 1.127 + } 1.128 + 1.129 + // Get a reference to the callback's observer, or null if the observer was 1.130 + // weakly referenced and has been destroyed. 1.131 + already_AddRefed<nsIObserver> GetObserver() const 1.132 + { 1.133 + if (!IsWeak()) { 1.134 + nsCOMPtr<nsIObserver> copy = mStrongRef; 1.135 + return copy.forget(); 1.136 + } 1.137 + 1.138 + nsCOMPtr<nsIObserver> observer = do_QueryReferent(mWeakRef); 1.139 + return observer.forget(); 1.140 + } 1.141 + 1.142 + const nsCString& GetDomain() const 1.143 + { 1.144 + return mDomain; 1.145 + } 1.146 + 1.147 + nsPrefBranch* GetPrefBranch() const 1.148 + { 1.149 + return mBranch; 1.150 + } 1.151 + 1.152 + // Has this callback's weak reference died? 1.153 + bool IsExpired() const 1.154 + { 1.155 + if (!IsWeak()) 1.156 + return false; 1.157 + 1.158 + nsCOMPtr<nsIObserver> observer(do_QueryReferent(mWeakRef)); 1.159 + return !observer; 1.160 + } 1.161 + 1.162 + enum { ALLOW_MEMMOVE = true }; 1.163 + 1.164 + private: 1.165 + nsCString mDomain; 1.166 + nsPrefBranch *mBranch; 1.167 + 1.168 + // Exactly one of mWeakRef and mStrongRef should be non-null. 1.169 + nsWeakPtr mWeakRef; 1.170 + nsCOMPtr<nsIObserver> mStrongRef; 1.171 + 1.172 + // We need a canonical nsISupports pointer, per bug 578392. 1.173 + nsISupports *mCanonical; 1.174 + 1.175 + bool IsWeak() const 1.176 + { 1.177 + return !!mWeakRef; 1.178 + } 1.179 +}; 1.180 + 1.181 +class nsPrefBranch : public nsIPrefBranchInternal, 1.182 + public nsIObserver, 1.183 + public nsSupportsWeakReference 1.184 +{ 1.185 + friend class mozilla::PreferenceServiceReporter; 1.186 +public: 1.187 + NS_DECL_ISUPPORTS 1.188 + NS_DECL_NSIPREFBRANCH 1.189 + NS_DECL_NSIPREFBRANCH2 1.190 + NS_DECL_NSIOBSERVER 1.191 + 1.192 + nsPrefBranch(const char *aPrefRoot, bool aDefaultBranch); 1.193 + virtual ~nsPrefBranch(); 1.194 + 1.195 + int32_t GetRootLength() { return mPrefRootLength; } 1.196 + 1.197 + nsresult RemoveObserverFromMap(const char *aDomain, nsISupports *aObserver); 1.198 + 1.199 + static void NotifyObserver(const char *newpref, void *data); 1.200 + 1.201 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); 1.202 + 1.203 +protected: 1.204 + nsPrefBranch() /* disallow use of this constructer */ 1.205 + { } 1.206 + 1.207 + nsresult GetDefaultFromPropertiesFile(const char *aPrefName, char16_t **return_buf); 1.208 + // As SetCharPref, but without any check on the length of |aValue| 1.209 + nsresult SetCharPrefInternal(const char *aPrefName, const char *aValue); 1.210 + // Reject strings that are more than 1Mb, warn if strings are more than 16kb 1.211 + nsresult CheckSanityOfStringLength(const char* aPrefName, const nsAString& aValue); 1.212 + nsresult CheckSanityOfStringLength(const char* aPrefName, const char* aValue); 1.213 + nsresult CheckSanityOfStringLength(const char* aPrefName, const uint32_t aLength); 1.214 + void RemoveExpiredCallback(PrefCallback *aCallback); 1.215 + const char *getPrefName(const char *aPrefName); 1.216 + void freeObserverList(void); 1.217 + 1.218 + friend PLDHashOperator 1.219 + FreeObserverFunc(PrefCallback *aKey, 1.220 + nsAutoPtr<PrefCallback> &aCallback, 1.221 + void *aArgs); 1.222 + 1.223 +private: 1.224 + int32_t mPrefRootLength; 1.225 + nsCString mPrefRoot; 1.226 + bool mIsDefault; 1.227 + 1.228 + bool mFreeingObserverList; 1.229 + nsClassHashtable<PrefCallback, PrefCallback> mObservers; 1.230 +}; 1.231 + 1.232 + 1.233 +class nsPrefLocalizedString : public nsIPrefLocalizedString, 1.234 + public nsISupportsString 1.235 +{ 1.236 +public: 1.237 + nsPrefLocalizedString(); 1.238 + virtual ~nsPrefLocalizedString(); 1.239 + 1.240 + NS_DECL_ISUPPORTS 1.241 + NS_FORWARD_NSISUPPORTSSTRING(mUnicodeString->) 1.242 + NS_FORWARD_NSISUPPORTSPRIMITIVE(mUnicodeString->) 1.243 + 1.244 + nsresult Init(); 1.245 + 1.246 +private: 1.247 + NS_IMETHOD GetData(char16_t**); 1.248 + NS_IMETHOD SetData(const char16_t* aData); 1.249 + NS_IMETHOD SetDataWithLength(uint32_t aLength, const char16_t *aData); 1.250 + 1.251 + nsCOMPtr<nsISupportsString> mUnicodeString; 1.252 +}; 1.253 + 1.254 + 1.255 +class nsRelativeFilePref : public nsIRelativeFilePref 1.256 +{ 1.257 +public: 1.258 + NS_DECL_ISUPPORTS 1.259 + NS_DECL_NSIRELATIVEFILEPREF 1.260 + 1.261 + nsRelativeFilePref(); 1.262 + virtual ~nsRelativeFilePref(); 1.263 + 1.264 +private: 1.265 + nsCOMPtr<nsIFile> mFile; 1.266 + nsCString mRelativeToKey; 1.267 +}; 1.268 + 1.269 +#endif