modules/libpref/src/nsPrefBranch.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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

mercurial