diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 60b6dc52ba2e..f5b549db2e26 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -69,7 +69,6 @@ #include "nsIPrefBranch2.h" #include "mozilla/AutoRestore.h" #include "nsINode.h" -#include "nsHashtable.h" #include "jsapi.h" @@ -111,7 +110,6 @@ class nsIScriptContext; class nsIRunnable; class nsIInterfaceRequestor; template class nsCOMArray; -template class nsRefPtrHashtable; struct JSRuntime; class nsIUGenCategory; class nsIWidget; @@ -121,7 +119,6 @@ class nsPIDOMEventTarget; class nsIPresShell; class nsIXPConnectJSObjectHolder; class nsPrefOldCallback; -class nsPrefObserverHashKey; #ifdef MOZ_XTF class nsIXTFService; #endif @@ -1713,8 +1710,7 @@ private: static nsIPrefBranch2 *sPrefBranch; // For old compatibility of RegisterPrefCallback - static nsRefPtrHashtable - *sPrefCallbackTable; + static nsCOMArray *sPrefCallbackList; static bool sImgLoaderInitialized; static void InitImgLoader(); diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 5999578446f8..b7b3c2aa0bdc 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -262,8 +262,7 @@ PRBool nsContentUtils::sIsHandlingKeyBoardEvent = PR_FALSE; PRBool nsContentUtils::sInitialized = PR_FALSE; -nsRefPtrHashtable - *nsContentUtils::sPrefCallbackTable = nsnull; +nsCOMArray *nsContentUtils::sPrefCallbackList = nsnull; static PLDHashTable sEventListenerManagersHash; @@ -314,95 +313,39 @@ class nsSameOriginChecker : public nsIChannelEventSink, NS_DECL_NSIINTERFACEREQUESTOR }; -class nsPrefObserverHashKey : public PLDHashEntryHdr { -public: - typedef nsPrefObserverHashKey* KeyType; - typedef const nsPrefObserverHashKey* KeyTypePointer; - - static const nsPrefObserverHashKey* KeyToPointer(nsPrefObserverHashKey *aKey) - { - return aKey; - } - - static PLDHashNumber HashKey(const nsPrefObserverHashKey *aKey) - { - PRUint32 strHash = nsCRT::HashCode(aKey->mPref.BeginReading(), - aKey->mPref.Length()); - return PR_ROTATE_LEFT32(strHash, 4) ^ - NS_PTR_TO_UINT32(aKey->mCallback); - } - - nsPrefObserverHashKey(const char *aPref, PrefChangedFunc aCallback) : - mPref(aPref), mCallback(aCallback) { } - - nsPrefObserverHashKey(const nsPrefObserverHashKey *aOther) : - mPref(aOther->mPref), mCallback(aOther->mCallback) - { } - - PRBool KeyEquals(const nsPrefObserverHashKey *aOther) const - { - return mCallback == aOther->mCallback && - mPref.Equals(aOther->mPref); - } - - nsPrefObserverHashKey *GetKey() const - { - return const_cast(this); - } - - enum { ALLOW_MEMMOVE = PR_TRUE }; - -public: - nsCString mPref; - PrefChangedFunc mCallback; -}; - // For nsContentUtils::RegisterPrefCallback/UnregisterPrefCallback -class nsPrefOldCallback : public nsIObserver, - public nsPrefObserverHashKey +class nsPrefOldCallback : public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER public: - nsPrefOldCallback(const char *aPref, PrefChangedFunc aCallback) - : nsPrefObserverHashKey(aPref, aCallback) { } - - ~nsPrefOldCallback() { - nsContentUtils::GetPrefBranch()->RemoveObserver(mPref.get(), this); + nsPrefOldCallback(const char *aPref, PrefChangedFunc aCallback, void *aClosure) : mPref(aPref), mCallback(aCallback), mClosure(aClosure) { } - void AppendClosure(void *aClosure) { - mClosures.AppendElement(aClosure); - } - - void RemoveClosure(void *aClosure) { - mClosures.RemoveElement(aClosure); - } - - PRBool HasNoClosures() { - return mClosures.Length() == 0; + PRBool IsEqual(const char *aPref, PrefChangedFunc aCallback, void *aClosure) { + return aCallback == mCallback && + aClosure == mClosure && + mPref.Equals(aPref); } public: - nsTObserverArray mClosures; + nsCString mPref; + PrefChangedFunc mCallback; + void *mClosure; }; NS_IMPL_ISUPPORTS1(nsPrefOldCallback, nsIObserver) NS_IMETHODIMP -nsPrefOldCallback::Observe(nsISupports *aSubject, - const char *aTopic, - const PRUnichar *aData) +nsPrefOldCallback::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) { NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic"); - NS_LossyConvertUTF16toASCII data(aData); - nsTObserverArray::ForwardIterator iter(mClosures); - while (iter.HasMore()) { - mCallback(data.get(), iter.GetNext()); - } + mCallback(NS_LossyConvertUTF16toASCII(aData).get(), mClosure); return NS_OK; } @@ -1109,9 +1052,16 @@ nsContentUtils::Shutdown() NS_IF_RELEASE(sStringBundles[i]); // Clean up c-style's observer - if (sPrefCallbackTable) { - delete sPrefCallbackTable; - sPrefCallbackTable = nsnull; + if (sPrefCallbackList) { + while (sPrefCallbackList->Count() > 0) { + nsRefPtr callback = (*sPrefCallbackList)[0]; + NS_ABORT_IF_FALSE(callback, "Invalid c-style callback is appended"); + if (sPrefBranch) + sPrefBranch->RemoveObserver(callback->mPref.get(), callback); + sPrefCallbackList->RemoveObject(callback); + } + delete sPrefCallbackList; + sPrefCallbackList = nsnull; } delete sPrefCacheData; @@ -2670,8 +2620,8 @@ nsContentUtils::GetStringPref(const char *aPref) return result; } -// RegisterPrefCallback/UnregisterPrefCallback are for backward compatiblity -// with c-style observers. +// RegisterPrefCallback/UnregisterPrefCallback are backward compatiblity for +// c-style observer. // static void @@ -2680,24 +2630,20 @@ nsContentUtils::RegisterPrefCallback(const char *aPref, void * aClosure) { if (sPrefBranch) { - if (!sPrefCallbackTable) { - sPrefCallbackTable = - new nsRefPtrHashtable(); - sPrefCallbackTable->Init(); + if (!sPrefCallbackList) { + sPrefCallbackList = new nsCOMArray (); + if (!sPrefCallbackList) + return; } - nsPrefObserverHashKey hashKey(aPref, aCallback); - nsRefPtr callback; - sPrefCallbackTable->Get(&hashKey, getter_AddRefs(callback)); + nsPrefOldCallback *callback = new nsPrefOldCallback(aPref, aCallback, aClosure); if (callback) { - callback->AppendClosure(aClosure); - return; - } - - callback = new nsPrefOldCallback(aPref, aCallback); - callback->AppendClosure(aClosure); - if (NS_SUCCEEDED(sPrefBranch->AddObserver(aPref, callback, PR_FALSE))) { - sPrefCallbackTable->Put(callback, callback); + if (NS_SUCCEEDED(sPrefBranch->AddObserver(aPref, callback, PR_FALSE))) { + sPrefCallbackList->AppendObject(callback); + return; + } + // error to get/add nsIPrefBranch2. Destroy callback information + delete callback; } } } @@ -2709,19 +2655,16 @@ nsContentUtils::UnregisterPrefCallback(const char *aPref, void * aClosure) { if (sPrefBranch) { - if (!sPrefCallbackTable) { + if (!sPrefCallbackList) return; - } - nsPrefObserverHashKey hashKey(aPref, aCallback); - nsRefPtr callback; - sPrefCallbackTable->Get(&hashKey, getter_AddRefs(callback)); - - if (callback) { - callback->RemoveClosure(aClosure); - if (callback->HasNoClosures()) { - // Delete the callback since its list of closures is empty. - sPrefCallbackTable->Remove(callback); + int i; + for (i = 0; i < sPrefCallbackList->Count(); i++) { + nsRefPtr callback = (*sPrefCallbackList)[i]; + if (callback && callback->IsEqual(aPref, aCallback, aClosure)) { + sPrefBranch->RemoveObserver(aPref, callback); + sPrefCallbackList->RemoveObject(callback); + return; } } } diff --git a/modules/libpref/src/prefapi.cpp b/modules/libpref/src/prefapi.cpp index 8ba30f3f70cf..1f8b274404b1 100644 --- a/modules/libpref/src/prefapi.cpp +++ b/modules/libpref/src/prefapi.cpp @@ -852,9 +852,9 @@ PREF_UnregisterCallback(const char *pref_node, while (node != NULL) { - if ( node->func == callback && - node->data == instance_data && - strcmp(node->domain, pref_node) == 0) + if ( strcmp(node->domain, pref_node) == 0 && + node->func == callback && + node->data == instance_data) { if (gCallbacksInProgress) {