LCOV - code coverage report
Current view: top level - modules/libpref - nsPrefBranch.h (source / functions) Hit Total Coverage
Test: output.info Lines: 62 69 89.9 %
Date: 2017-07-14 16:53:18 Functions: 23 26 88.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       6             : #ifndef nsPrefBranch_h
       7             : #define nsPrefBranch_h
       8             : 
       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"
      26             : #include "mozilla/Variant.h"
      27             : 
      28             : namespace mozilla {
      29             : class PreferenceServiceReporter;
      30             : } // namespace mozilla
      31             : 
      32             : class nsPrefBranch;
      33             : 
      34             : class PrefCallback : public PLDHashEntryHdr {
      35             :   friend class mozilla::PreferenceServiceReporter;
      36             : 
      37             :   public:
      38             :     typedef PrefCallback* KeyType;
      39             :     typedef const PrefCallback* KeyTypePointer;
      40             : 
      41         928 :     static const PrefCallback* KeyToPointer(PrefCallback *aKey)
      42             :     {
      43         928 :       return aKey;
      44             :     }
      45             : 
      46         928 :     static PLDHashNumber HashKey(const PrefCallback *aKey)
      47             :     {
      48         928 :       uint32_t hash = mozilla::HashString(aKey->mDomain);
      49         928 :       return mozilla::AddToHash(hash, aKey->mCanonical);
      50             :     }
      51             : 
      52             : 
      53             :   public:
      54             :     // Create a PrefCallback with a strong reference to its observer.
      55         784 :     PrefCallback(const char *aDomain, nsIObserver *aObserver,
      56             :                  nsPrefBranch *aBranch)
      57         784 :       : mDomain(aDomain),
      58             :         mBranch(aBranch),
      59             :         mWeakRef(nullptr),
      60         784 :         mStrongRef(aObserver)
      61             :     {
      62         784 :       MOZ_COUNT_CTOR(PrefCallback);
      63        1568 :       nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
      64         784 :       mCanonical = canonical;
      65         784 :     }
      66             : 
      67             :     // Create a PrefCallback with a weak reference to its observer.
      68         144 :     PrefCallback(const char *aDomain,
      69             :                  nsISupportsWeakReference *aObserver,
      70             :                  nsPrefBranch *aBranch)
      71         144 :       : mDomain(aDomain),
      72             :         mBranch(aBranch),
      73         288 :         mWeakRef(do_GetWeakReference(aObserver)),
      74         432 :         mStrongRef(nullptr)
      75             :     {
      76         144 :       MOZ_COUNT_CTOR(PrefCallback);
      77         288 :       nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
      78         144 :       mCanonical = canonical;
      79         144 :     }
      80             : 
      81             :     // Copy constructor needs to be explicit or the linker complains.
      82         925 :     explicit PrefCallback(const PrefCallback *&aCopy)
      83        1850 :       : mDomain(aCopy->mDomain),
      84         925 :         mBranch(aCopy->mBranch),
      85         925 :         mWeakRef(aCopy->mWeakRef),
      86         925 :         mStrongRef(aCopy->mStrongRef),
      87        4625 :         mCanonical(aCopy->mCanonical)
      88             :     {
      89         925 :       MOZ_COUNT_CTOR(PrefCallback);
      90         925 :     }
      91             : 
      92           9 :     ~PrefCallback()
      93           9 :     {
      94           9 :       MOZ_COUNT_DTOR(PrefCallback);
      95           9 :     }
      96             : 
      97           3 :     bool KeyEquals(const PrefCallback *aKey) const
      98             :     {
      99             :       // We want to be able to look up a weakly-referencing PrefCallback after
     100             :       // its observer has died so we can remove it from the table.  Once the
     101             :       // callback's observer dies, its canonical pointer is stale -- in
     102             :       // particular, we may have allocated a new observer in the same spot in
     103             :       // memory!  So we can't just compare canonical pointers to determine
     104             :       // whether aKey refers to the same observer as this.
     105             :       //
     106             :       // Our workaround is based on the way we use this hashtable: When we ask
     107             :       // the hashtable to remove a PrefCallback whose weak reference has
     108             :       // expired, we use as the key for removal the same object as was inserted
     109             :       // into the hashtable.  Thus we can say that if one of the keys' weak
     110             :       // references has expired, the two keys are equal iff they're the same
     111             :       // object.
     112             : 
     113           3 :       if (IsExpired() || aKey->IsExpired())
     114           0 :         return this == aKey;
     115             : 
     116           3 :       if (mCanonical != aKey->mCanonical)
     117           0 :         return false;
     118             : 
     119           3 :       return mDomain.Equals(aKey->mDomain);
     120             :     }
     121             : 
     122             :     PrefCallback *GetKey() const
     123             :     {
     124             :       return const_cast<PrefCallback*>(this);
     125             :     }
     126             : 
     127             :     // Get a reference to the callback's observer, or null if the observer was
     128             :     // weakly referenced and has been destroyed.
     129          49 :     already_AddRefed<nsIObserver> GetObserver() const
     130             :     {
     131          49 :       if (!IsWeak()) {
     132          88 :         nsCOMPtr<nsIObserver> copy = mStrongRef;
     133          44 :         return copy.forget();
     134             :       }
     135             : 
     136          10 :       nsCOMPtr<nsIObserver> observer = do_QueryReferent(mWeakRef);
     137           5 :       return observer.forget();
     138             :     }
     139             : 
     140           0 :     const nsCString& GetDomain() const
     141             :     {
     142           0 :       return mDomain;
     143             :     }
     144             : 
     145          98 :     nsPrefBranch* GetPrefBranch() const
     146             :     {
     147          98 :       return mBranch;
     148             :     }
     149             : 
     150             :     // Has this callback's weak reference died?
     151           6 :     bool IsExpired() const
     152             :     {
     153           6 :       if (!IsWeak())
     154           6 :         return false;
     155             : 
     156           0 :       nsCOMPtr<nsIObserver> observer(do_QueryReferent(mWeakRef));
     157           0 :       return !observer;
     158             :     }
     159             : 
     160             :     enum { ALLOW_MEMMOVE = true };
     161             : 
     162             :   private:
     163             :     nsCString             mDomain;
     164             :     nsPrefBranch         *mBranch;
     165             : 
     166             :     // Exactly one of mWeakRef and mStrongRef should be non-null.
     167             :     nsWeakPtr             mWeakRef;
     168             :     nsCOMPtr<nsIObserver> mStrongRef;
     169             : 
     170             :     // We need a canonical nsISupports pointer, per bug 578392.
     171             :     nsISupports          *mCanonical;
     172             : 
     173          55 :     bool IsWeak() const
     174             :     {
     175          55 :       return !!mWeakRef;
     176             :     }
     177             : };
     178             : 
     179             : class nsPrefBranch final : public nsIPrefBranchInternal,
     180             :                            public nsIObserver,
     181             :                            public nsSupportsWeakReference
     182             : {
     183             :   friend class mozilla::PreferenceServiceReporter;
     184             : public:
     185             :   NS_DECL_ISUPPORTS
     186             :   NS_DECL_NSIPREFBRANCH
     187             :   NS_DECL_NSIPREFBRANCH2
     188             :   NS_DECL_NSIOBSERVER
     189             : 
     190             :   nsPrefBranch(const char *aPrefRoot, bool aDefaultBranch);
     191             :   nsPrefBranch() = delete;
     192             : 
     193          49 :   int32_t GetRootLength() const { return mPrefRoot.Length(); }
     194             : 
     195             :   nsresult RemoveObserverFromMap(const char *aDomain, nsISupports *aObserver);
     196             : 
     197             :   static void NotifyObserver(const char *newpref, void *data);
     198             : 
     199             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
     200             : 
     201             :   static void ReportToConsole(const nsAString& aMessage);
     202             : 
     203             : protected:
     204             :   /**
     205             :    * Helper class for either returning a raw cstring or nsCString.
     206             :    */
     207             :   typedef mozilla::Variant<const char*, const nsCString> PrefNameBase;
     208        2629 :   class PrefName : public PrefNameBase
     209             :   {
     210             :   public:
     211        2415 :     explicit PrefName(const char* aName) : PrefNameBase(aName) {}
     212         214 :     explicit PrefName(const nsCString& aName) : PrefNameBase(aName) {}
     213             : 
     214             :     /**
     215             :      * Use default move constructors, disallow copy constructors.
     216             :      */
     217             :     PrefName(PrefName&& aOther) = default;
     218             :     PrefName& operator=(PrefName&& aOther) = default;
     219             :     PrefName(const PrefName&) = delete;
     220             :     PrefName& operator=(const PrefName&) = delete;
     221             : 
     222             :     struct PtrMatcher {
     223       47560 :       static const char* match(const char* aVal) { return aVal; }
     224       39579 :       static const char* match(const nsCString& aVal) { return aVal.get(); }
     225             :     };
     226             : 
     227             :     struct LenMatcher {
     228          15 :       static size_t match(const char* aVal) { return strlen(aVal); }
     229          13 :       static size_t match(const nsCString& aVal) { return aVal.Length(); }
     230             :     };
     231             : 
     232       87139 :     const char* get() const {
     233             :       static PtrMatcher m;
     234       87139 :       return match(m);
     235             :     }
     236             : 
     237          28 :     size_t Length() const {
     238             :       static LenMatcher m;
     239          28 :       return match(m);
     240             :     }
     241             :   };
     242             : 
     243             :   virtual ~nsPrefBranch();
     244             : 
     245             :   nsresult   GetDefaultFromPropertiesFile(const char *aPrefName, char16_t **return_buf);
     246             :   // As SetCharPref, but without any check on the length of |aValue|
     247             :   nsresult   SetCharPrefInternal(const char *aPrefName, const char *aValue);
     248             :   // Reject strings that are more than 1Mb, warn if strings are more than 16kb
     249             :   nsresult   CheckSanityOfStringLength(const char* aPrefName, const nsAString& aValue);
     250             :   nsresult   CheckSanityOfStringLength(const char* aPrefName, const nsACString& aValue);
     251             :   nsresult   CheckSanityOfStringLength(const char* aPrefName, const char* aValue);
     252             :   nsresult   CheckSanityOfStringLength(const char* aPrefName, const uint32_t aLength);
     253             :   void RemoveExpiredCallback(PrefCallback *aCallback);
     254             :   PrefName getPrefName(const char *aPrefName) const;
     255             :   void       freeObserverList(void);
     256             : 
     257             : private:
     258             :   const nsCString mPrefRoot;
     259             :   bool                  mIsDefault;
     260             : 
     261             :   bool                  mFreeingObserverList;
     262             :   nsClassHashtable<PrefCallback, PrefCallback> mObservers;
     263             : };
     264             : 
     265             : 
     266             : class nsPrefLocalizedString final : public nsIPrefLocalizedString,
     267             :                                     public nsISupportsString
     268             : {
     269             : public:
     270             :   nsPrefLocalizedString();
     271             : 
     272             :   NS_DECL_ISUPPORTS
     273          40 :   NS_FORWARD_NSISUPPORTSSTRING(mUnicodeString->)
     274           0 :   NS_FORWARD_NSISUPPORTSPRIMITIVE(mUnicodeString->)
     275             : 
     276             :   nsresult Init();
     277             : 
     278             : private:
     279             :   virtual ~nsPrefLocalizedString();
     280             : 
     281             :   NS_IMETHOD GetData(char16_t**) override;
     282             :   NS_IMETHOD SetData(const char16_t* aData) override;
     283             :   NS_IMETHOD SetDataWithLength(uint32_t aLength, const char16_t *aData) override;
     284             : 
     285             :   nsCOMPtr<nsISupportsString> mUnicodeString;
     286             : };
     287             : 
     288             : 
     289             : class nsRelativeFilePref : public nsIRelativeFilePref
     290             : {
     291             : public:
     292             :   NS_DECL_ISUPPORTS
     293             :   NS_DECL_NSIRELATIVEFILEPREF
     294             : 
     295             :   nsRelativeFilePref();
     296             : 
     297             : private:
     298             :   virtual ~nsRelativeFilePref();
     299             : 
     300             :   nsCOMPtr<nsIFile> mFile;
     301             :   nsCString mRelativeToKey;
     302             : };
     303             : 
     304             : #endif

Generated by: LCOV version 1.13