Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 #ifndef nsPrefBranch_h
7 #define nsPrefBranch_h
9 #include "nsCOMPtr.h"
10 #include "nsIObserver.h"
11 #include "nsIPrefBranch.h"
12 #include "nsIPrefBranchInternal.h"
13 #include "nsIPrefLocalizedString.h"
14 #include "nsXPCOM.h"
15 #include "nsISupportsPrimitives.h"
16 #include "nsIRelativeFilePref.h"
17 #include "nsIFile.h"
18 #include "nsString.h"
19 #include "nsTArray.h"
20 #include "nsWeakReference.h"
21 #include "nsClassHashtable.h"
22 #include "nsCRT.h"
23 #include "nsISupportsImpl.h"
24 #include "mozilla/HashFunctions.h"
25 #include "mozilla/MemoryReporting.h"
27 namespace mozilla {
28 class PreferenceServiceReporter;
29 } // namespace mozilla;
31 class nsPrefBranch;
33 class PrefCallback : public PLDHashEntryHdr {
34 friend class mozilla::PreferenceServiceReporter;
36 public:
37 typedef PrefCallback* KeyType;
38 typedef const PrefCallback* KeyTypePointer;
40 static const PrefCallback* KeyToPointer(PrefCallback *aKey)
41 {
42 return aKey;
43 }
45 static PLDHashNumber HashKey(const PrefCallback *aKey)
46 {
47 uint32_t hash = mozilla::HashString(aKey->mDomain);
48 return mozilla::AddToHash(hash, aKey->mCanonical);
49 }
52 public:
53 // Create a PrefCallback with a strong reference to its observer.
54 PrefCallback(const char *aDomain, nsIObserver *aObserver,
55 nsPrefBranch *aBranch)
56 : mDomain(aDomain),
57 mBranch(aBranch),
58 mWeakRef(nullptr),
59 mStrongRef(aObserver)
60 {
61 MOZ_COUNT_CTOR(PrefCallback);
62 nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
63 mCanonical = canonical;
64 }
66 // Create a PrefCallback with a weak reference to its observer.
67 PrefCallback(const char *aDomain,
68 nsISupportsWeakReference *aObserver,
69 nsPrefBranch *aBranch)
70 : mDomain(aDomain),
71 mBranch(aBranch),
72 mWeakRef(do_GetWeakReference(aObserver)),
73 mStrongRef(nullptr)
74 {
75 MOZ_COUNT_CTOR(PrefCallback);
76 nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
77 mCanonical = canonical;
78 }
80 // Copy constructor needs to be explicit or the linker complains.
81 PrefCallback(const PrefCallback *&aCopy)
82 : mDomain(aCopy->mDomain),
83 mBranch(aCopy->mBranch),
84 mWeakRef(aCopy->mWeakRef),
85 mStrongRef(aCopy->mStrongRef),
86 mCanonical(aCopy->mCanonical)
87 {
88 MOZ_COUNT_CTOR(PrefCallback);
89 }
91 ~PrefCallback()
92 {
93 MOZ_COUNT_DTOR(PrefCallback);
94 }
96 bool KeyEquals(const PrefCallback *aKey) const
97 {
98 // We want to be able to look up a weakly-referencing PrefCallback after
99 // its observer has died so we can remove it from the table. Once the
100 // callback's observer dies, its canonical pointer is stale -- in
101 // particular, we may have allocated a new observer in the same spot in
102 // memory! So we can't just compare canonical pointers to determine
103 // whether aKey refers to the same observer as this.
104 //
105 // Our workaround is based on the way we use this hashtable: When we ask
106 // the hashtable to remove a PrefCallback whose weak reference has
107 // expired, we use as the key for removal the same object as was inserted
108 // into the hashtable. Thus we can say that if one of the keys' weak
109 // references has expired, the two keys are equal iff they're the same
110 // object.
112 if (IsExpired() || aKey->IsExpired())
113 return this == aKey;
115 if (mCanonical != aKey->mCanonical)
116 return false;
118 return mDomain.Equals(aKey->mDomain);
119 }
121 PrefCallback *GetKey() const
122 {
123 return const_cast<PrefCallback*>(this);
124 }
126 // Get a reference to the callback's observer, or null if the observer was
127 // weakly referenced and has been destroyed.
128 already_AddRefed<nsIObserver> GetObserver() const
129 {
130 if (!IsWeak()) {
131 nsCOMPtr<nsIObserver> copy = mStrongRef;
132 return copy.forget();
133 }
135 nsCOMPtr<nsIObserver> observer = do_QueryReferent(mWeakRef);
136 return observer.forget();
137 }
139 const nsCString& GetDomain() const
140 {
141 return mDomain;
142 }
144 nsPrefBranch* GetPrefBranch() const
145 {
146 return mBranch;
147 }
149 // Has this callback's weak reference died?
150 bool IsExpired() const
151 {
152 if (!IsWeak())
153 return false;
155 nsCOMPtr<nsIObserver> observer(do_QueryReferent(mWeakRef));
156 return !observer;
157 }
159 enum { ALLOW_MEMMOVE = true };
161 private:
162 nsCString mDomain;
163 nsPrefBranch *mBranch;
165 // Exactly one of mWeakRef and mStrongRef should be non-null.
166 nsWeakPtr mWeakRef;
167 nsCOMPtr<nsIObserver> mStrongRef;
169 // We need a canonical nsISupports pointer, per bug 578392.
170 nsISupports *mCanonical;
172 bool IsWeak() const
173 {
174 return !!mWeakRef;
175 }
176 };
178 class nsPrefBranch : public nsIPrefBranchInternal,
179 public nsIObserver,
180 public nsSupportsWeakReference
181 {
182 friend class mozilla::PreferenceServiceReporter;
183 public:
184 NS_DECL_ISUPPORTS
185 NS_DECL_NSIPREFBRANCH
186 NS_DECL_NSIPREFBRANCH2
187 NS_DECL_NSIOBSERVER
189 nsPrefBranch(const char *aPrefRoot, bool aDefaultBranch);
190 virtual ~nsPrefBranch();
192 int32_t GetRootLength() { return mPrefRootLength; }
194 nsresult RemoveObserverFromMap(const char *aDomain, nsISupports *aObserver);
196 static void NotifyObserver(const char *newpref, void *data);
198 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
200 protected:
201 nsPrefBranch() /* disallow use of this constructer */
202 { }
204 nsresult GetDefaultFromPropertiesFile(const char *aPrefName, char16_t **return_buf);
205 // As SetCharPref, but without any check on the length of |aValue|
206 nsresult SetCharPrefInternal(const char *aPrefName, const char *aValue);
207 // Reject strings that are more than 1Mb, warn if strings are more than 16kb
208 nsresult CheckSanityOfStringLength(const char* aPrefName, const nsAString& aValue);
209 nsresult CheckSanityOfStringLength(const char* aPrefName, const char* aValue);
210 nsresult CheckSanityOfStringLength(const char* aPrefName, const uint32_t aLength);
211 void RemoveExpiredCallback(PrefCallback *aCallback);
212 const char *getPrefName(const char *aPrefName);
213 void freeObserverList(void);
215 friend PLDHashOperator
216 FreeObserverFunc(PrefCallback *aKey,
217 nsAutoPtr<PrefCallback> &aCallback,
218 void *aArgs);
220 private:
221 int32_t mPrefRootLength;
222 nsCString mPrefRoot;
223 bool mIsDefault;
225 bool mFreeingObserverList;
226 nsClassHashtable<PrefCallback, PrefCallback> mObservers;
227 };
230 class nsPrefLocalizedString : public nsIPrefLocalizedString,
231 public nsISupportsString
232 {
233 public:
234 nsPrefLocalizedString();
235 virtual ~nsPrefLocalizedString();
237 NS_DECL_ISUPPORTS
238 NS_FORWARD_NSISUPPORTSSTRING(mUnicodeString->)
239 NS_FORWARD_NSISUPPORTSPRIMITIVE(mUnicodeString->)
241 nsresult Init();
243 private:
244 NS_IMETHOD GetData(char16_t**);
245 NS_IMETHOD SetData(const char16_t* aData);
246 NS_IMETHOD SetDataWithLength(uint32_t aLength, const char16_t *aData);
248 nsCOMPtr<nsISupportsString> mUnicodeString;
249 };
252 class nsRelativeFilePref : public nsIRelativeFilePref
253 {
254 public:
255 NS_DECL_ISUPPORTS
256 NS_DECL_NSIRELATIVEFILEPREF
258 nsRelativeFilePref();
259 virtual ~nsRelativeFilePref();
261 private:
262 nsCOMPtr<nsIFile> mFile;
263 nsCString mRelativeToKey;
264 };
266 #endif