123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef nsPrefBranch_h
- #define nsPrefBranch_h
- #include "nsCOMPtr.h"
- #include "nsIObserver.h"
- #include "nsIPrefBranch.h"
- #include "nsIPrefBranchInternal.h"
- #include "nsIPrefLocalizedString.h"
- #include "nsXPCOM.h"
- #include "nsISupportsPrimitives.h"
- #include "nsIRelativeFilePref.h"
- #include "nsIFile.h"
- #include "nsString.h"
- #include "nsTArray.h"
- #include "nsWeakReference.h"
- #include "nsClassHashtable.h"
- #include "nsCRT.h"
- #include "nsISupportsImpl.h"
- #include "mozilla/HashFunctions.h"
- #include "mozilla/MemoryReporting.h"
- namespace mozilla {
- class PreferenceServiceReporter;
- } // namespace mozilla
- class nsPrefBranch;
- class PrefCallback : public PLDHashEntryHdr {
- friend class mozilla::PreferenceServiceReporter;
- public:
- typedef PrefCallback* KeyType;
- typedef const PrefCallback* KeyTypePointer;
- static const PrefCallback* KeyToPointer(PrefCallback *aKey)
- {
- return aKey;
- }
- static PLDHashNumber HashKey(const PrefCallback *aKey)
- {
- uint32_t hash = mozilla::HashString(aKey->mDomain);
- return mozilla::AddToHash(hash, aKey->mCanonical);
- }
- public:
- // Create a PrefCallback with a strong reference to its observer.
- PrefCallback(const char *aDomain, nsIObserver *aObserver,
- nsPrefBranch *aBranch)
- : mDomain(aDomain),
- mBranch(aBranch),
- mWeakRef(nullptr),
- mStrongRef(aObserver)
- {
- MOZ_COUNT_CTOR(PrefCallback);
- nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
- mCanonical = canonical;
- }
- // Create a PrefCallback with a weak reference to its observer.
- PrefCallback(const char *aDomain,
- nsISupportsWeakReference *aObserver,
- nsPrefBranch *aBranch)
- : mDomain(aDomain),
- mBranch(aBranch),
- mWeakRef(do_GetWeakReference(aObserver)),
- mStrongRef(nullptr)
- {
- MOZ_COUNT_CTOR(PrefCallback);
- nsCOMPtr<nsISupports> canonical = do_QueryInterface(aObserver);
- mCanonical = canonical;
- }
- // Copy constructor needs to be explicit or the linker complains.
- explicit PrefCallback(const PrefCallback *&aCopy)
- : mDomain(aCopy->mDomain),
- mBranch(aCopy->mBranch),
- mWeakRef(aCopy->mWeakRef),
- mStrongRef(aCopy->mStrongRef),
- mCanonical(aCopy->mCanonical)
- {
- MOZ_COUNT_CTOR(PrefCallback);
- }
- ~PrefCallback()
- {
- MOZ_COUNT_DTOR(PrefCallback);
- }
- bool KeyEquals(const PrefCallback *aKey) const
- {
- // We want to be able to look up a weakly-referencing PrefCallback after
- // its observer has died so we can remove it from the table. Once the
- // callback's observer dies, its canonical pointer is stale -- in
- // particular, we may have allocated a new observer in the same spot in
- // memory! So we can't just compare canonical pointers to determine
- // whether aKey refers to the same observer as this.
- //
- // Our workaround is based on the way we use this hashtable: When we ask
- // the hashtable to remove a PrefCallback whose weak reference has
- // expired, we use as the key for removal the same object as was inserted
- // into the hashtable. Thus we can say that if one of the keys' weak
- // references has expired, the two keys are equal iff they're the same
- // object.
- if (IsExpired() || aKey->IsExpired())
- return this == aKey;
- if (mCanonical != aKey->mCanonical)
- return false;
- return mDomain.Equals(aKey->mDomain);
- }
- PrefCallback *GetKey() const
- {
- return const_cast<PrefCallback*>(this);
- }
- // Get a reference to the callback's observer, or null if the observer was
- // weakly referenced and has been destroyed.
- already_AddRefed<nsIObserver> GetObserver() const
- {
- if (!IsWeak()) {
- nsCOMPtr<nsIObserver> copy = mStrongRef;
- return copy.forget();
- }
- nsCOMPtr<nsIObserver> observer = do_QueryReferent(mWeakRef);
- return observer.forget();
- }
- const nsCString& GetDomain() const
- {
- return mDomain;
- }
- nsPrefBranch* GetPrefBranch() const
- {
- return mBranch;
- }
- // Has this callback's weak reference died?
- bool IsExpired() const
- {
- if (!IsWeak())
- return false;
- nsCOMPtr<nsIObserver> observer(do_QueryReferent(mWeakRef));
- return !observer;
- }
- enum { ALLOW_MEMMOVE = true };
- private:
- nsCString mDomain;
- nsPrefBranch *mBranch;
- // Exactly one of mWeakRef and mStrongRef should be non-null.
- nsWeakPtr mWeakRef;
- nsCOMPtr<nsIObserver> mStrongRef;
- // We need a canonical nsISupports pointer, per bug 578392.
- nsISupports *mCanonical;
- bool IsWeak() const
- {
- return !!mWeakRef;
- }
- };
- class nsPrefBranch final : public nsIPrefBranchInternal,
- public nsIObserver,
- public nsSupportsWeakReference
- {
- friend class mozilla::PreferenceServiceReporter;
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIPREFBRANCH
- NS_DECL_NSIPREFBRANCH2
- NS_DECL_NSIOBSERVER
- nsPrefBranch(const char *aPrefRoot, bool aDefaultBranch);
- int32_t GetRootLength() { return mPrefRootLength; }
- nsresult RemoveObserverFromMap(const char *aDomain, nsISupports *aObserver);
- static void NotifyObserver(const char *newpref, void *data);
- size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
- static void ReportToConsole(const nsAString& aMessage);
- protected:
- virtual ~nsPrefBranch();
- nsPrefBranch() /* disallow use of this constructer */
- : mPrefRootLength(0)
- , mIsDefault(false)
- , mFreeingObserverList(false)
- {}
- nsresult GetDefaultFromPropertiesFile(const char *aPrefName, char16_t **return_buf);
- // As SetCharPref, but without any check on the length of |aValue|
- nsresult SetCharPrefInternal(const char *aPrefName, const char *aValue);
- // Reject strings that are more than 1Mb, warn if strings are more than 16kb
- nsresult CheckSanityOfStringLength(const char* aPrefName, const nsAString& aValue);
- nsresult CheckSanityOfStringLength(const char* aPrefName, const char* aValue);
- nsresult CheckSanityOfStringLength(const char* aPrefName, const uint32_t aLength);
- void RemoveExpiredCallback(PrefCallback *aCallback);
- const char *getPrefName(const char *aPrefName);
- void freeObserverList(void);
- private:
- int32_t mPrefRootLength;
- nsCString mPrefRoot;
- bool mIsDefault;
- bool mFreeingObserverList;
- nsClassHashtable<PrefCallback, PrefCallback> mObservers;
- };
- class nsPrefLocalizedString final : public nsIPrefLocalizedString,
- public nsISupportsString
- {
- public:
- nsPrefLocalizedString();
- NS_DECL_ISUPPORTS
- NS_FORWARD_NSISUPPORTSSTRING(mUnicodeString->)
- NS_FORWARD_NSISUPPORTSPRIMITIVE(mUnicodeString->)
- nsresult Init();
- private:
- virtual ~nsPrefLocalizedString();
- NS_IMETHOD GetData(char16_t**) override;
- NS_IMETHOD SetData(const char16_t* aData) override;
- NS_IMETHOD SetDataWithLength(uint32_t aLength, const char16_t *aData) override;
- nsCOMPtr<nsISupportsString> mUnicodeString;
- };
- class nsRelativeFilePref : public nsIRelativeFilePref
- {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIRELATIVEFILEPREF
- nsRelativeFilePref();
- private:
- virtual ~nsRelativeFilePref();
- nsCOMPtr<nsIFile> mFile;
- nsCString mRelativeToKey;
- };
- #endif
|