nsPrefBranch.h 7.6 KB

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