diff --git a/content/base/src/nsContentPolicy.cpp b/content/base/src/nsContentPolicy.cpp index 1bbd27a7c61..b6b58a97df9 100644 --- a/content/base/src/nsContentPolicy.cpp +++ b/content/base/src/nsContentPolicy.cpp @@ -117,7 +117,8 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, * their permissions. */ nsresult rv; - const nsCOMArray& entries = mPolicies.GetEntries(); + nsCOMArray entries; + mPolicies.GetEntries(entries); int32_t count = entries.Count(); for (int32_t i = 0; i < count; i++) { /* check the appropriate policy */ diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp index b68d240f350..1e088c5306a 100644 --- a/modules/libpref/src/Preferences.cpp +++ b/modules/libpref/src/Preferences.cpp @@ -15,6 +15,7 @@ #include "mozilla/Preferences.h" #include "nsAppDirectoryServiceDefs.h" +#include "nsDataHashtable.h" #include "nsDirectoryServiceDefs.h" #include "nsICategoryManager.h" #include "nsCategoryManagerUtils.h" diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index 70ef0854f06..3bd42287f47 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -2326,7 +2326,8 @@ NS_SniffContent(const char* aSnifferType, nsIRequest* aRequest, return; } - const nsCOMArray& sniffers = cache->GetEntries(); + nsCOMArray sniffers; + cache->GetEntries(sniffers); for (int32_t i = 0; i < sniffers.Count(); ++i) { nsresult rv = sniffers[i]->GetMIMETypeFromContent(aRequest, aData, aLength, aSniffedType); if (NS_SUCCEEDED(rv) && !aSniffedType.IsEmpty()) { diff --git a/netwerk/base/src/nsIOService.cpp b/netwerk/base/src/nsIOService.cpp index 139838fb7f8..baf90608ef4 100644 --- a/netwerk/base/src/nsIOService.cpp +++ b/netwerk/base/src/nsIOService.cpp @@ -319,8 +319,8 @@ nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan, } // Finally, our category - const nsCOMArray& entries = - mChannelEventSinks.GetEntries(); + nsCOMArray entries; + mChannelEventSinks.GetEntries(entries); int32_t len = entries.Count(); for (int32_t i = 0; i < len; ++i) { nsresult rv = helper->DelegateOnChannelRedirect(entries[i], oldChan, diff --git a/storage/src/VacuumManager.cpp b/storage/src/VacuumManager.cpp index 1100375cedd..c016763522d 100644 --- a/storage/src/VacuumManager.cpp +++ b/storage/src/VacuumManager.cpp @@ -364,8 +364,8 @@ VacuumManager::Observe(nsISupports *aSubject, if (strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY) == 0) { // Try to run vacuum on all registered entries. Will stop at the first // successful one. - const nsCOMArray &entries = - mParticipants.GetEntries(); + nsCOMArray entries; + mParticipants.GetEntries(entries); // If there are more entries than what a month can contain, we could end up // skipping some, since we run daily. So we use a starting index. static const char* kPrefName = PREF_VACUUM_BRANCH "index"; diff --git a/toolkit/components/places/nsPlacesMacros.h b/toolkit/components/places/nsPlacesMacros.h index 964704e9527..af1306082c1 100644 --- a/toolkit/components/places/nsPlacesMacros.h +++ b/toolkit/components/places/nsPlacesMacros.h @@ -16,7 +16,8 @@ #define NOTIFY_OBSERVERS(canFire, cache, array, type, method) \ PR_BEGIN_MACRO \ if (canFire) { \ - const nsCOMArray &entries = cache.GetEntries(); \ + nsCOMArray entries; \ + cache.GetEntries(entries); \ for (int32_t idx = 0; idx < entries.Count(); ++idx) \ entries[idx]->method; \ ENUMERATE_WEAKARRAY(array, type, method) \ diff --git a/widget/xpwidgets/nsIdleService.cpp b/widget/xpwidgets/nsIdleService.cpp index 8941e327afc..06bd6e11d16 100644 --- a/widget/xpwidgets/nsIdleService.cpp +++ b/widget/xpwidgets/nsIdleService.cpp @@ -105,7 +105,8 @@ nsIdleServiceDaily::Observe(nsISupports *, nullptr); // Notify the category observers. - const nsCOMArray &entries = mCategoryObservers.GetEntries(); + nsCOMArray entries; + mCategoryObservers.GetEntries(entries); for (int32_t i = 0; i < entries.Count(); ++i) { (void)entries[i]->Observe(nullptr, OBSERVER_TOPIC_IDLE_DAILY, nullptr); } diff --git a/xpcom/glue/nsCategoryCache.cpp b/xpcom/glue/nsCategoryCache.cpp index 47c2e0d326c..9a7f85086f4 100644 --- a/xpcom/glue/nsCategoryCache.cpp +++ b/xpcom/glue/nsCategoryCache.cpp @@ -6,17 +6,16 @@ #include "nsIObserverService.h" #include "mozilla/Services.h" #include "nsISupportsPrimitives.h" +#include "nsIStringEnumerator.h" #include "nsXPCOMCID.h" #include "nsCategoryCache.h" -nsCategoryObserver::nsCategoryObserver(const char* aCategory, - nsCategoryListener* aListener) - : mListener(nullptr), mCategory(aCategory), mObserversRemoved(false) +nsCategoryObserver::nsCategoryObserver(const char* aCategory) + : mCategory(aCategory) + , mObserversRemoved(false) { - mListener = aListener; - // First, enumerate the currently existing entries nsCOMPtr catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID); @@ -29,23 +28,22 @@ nsCategoryObserver::nsCategoryObserver(const char* aCategory, if (NS_FAILED(rv)) return; - nsTArray entries; - nsCOMPtr entry; - while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) { - nsCOMPtr entryName = do_QueryInterface(entry, &rv); + nsCOMPtr strings = do_QueryInterface(enumerator); + MOZ_ASSERT(strings); + bool more; + while (NS_SUCCEEDED(strings->HasMore(&more)) && more) { + nsAutoCString entryName; + strings->GetNext(entryName); + + nsCString entryValue; + rv = catMan->GetCategoryEntry(aCategory, + entryName.get(), + getter_Copies(entryValue)); if (NS_SUCCEEDED(rv)) { - nsAutoCString categoryEntry; - rv = entryName->GetData(categoryEntry); - - nsCString entryValue; - catMan->GetCategoryEntry(aCategory, - categoryEntry.get(), - getter_Copies(entryValue)); - - if (NS_SUCCEEDED(rv)) { - mHash.Put(categoryEntry, entryValue); - entries.AppendElement(entryValue); + nsCOMPtr service = do_GetService(entryValue.get()); + if (service) { + mHash.Put(entryName, service); } } } @@ -59,9 +57,6 @@ nsCategoryObserver::nsCategoryObserver(const char* aCategory, serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID, false); serv->AddObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID, false); } - - for (int32_t i = entries.Length() - 1; i >= 0; --i) - mListener->EntryAdded(entries[i]); } nsCategoryObserver::~nsCategoryObserver() { @@ -71,11 +66,10 @@ NS_IMPL_ISUPPORTS1(nsCategoryObserver, nsIObserver) void nsCategoryObserver::ListenerDied() { - mListener = nullptr; RemoveObservers(); } -NS_HIDDEN_(void) +void nsCategoryObserver::RemoveObservers() { if (mObserversRemoved) return; @@ -94,12 +88,8 @@ nsCategoryObserver::RemoveObservers() { NS_IMETHODIMP nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) { - if (!mListener) - return NS_OK; - if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { mHash.Clear(); - mListener->CategoryCleared(); RemoveObservers(); return NS_OK; @@ -120,7 +110,7 @@ nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic, // added and an nsCategoryObserver gets instantiated before events get // processed, we'd get the notification for an existing entry. // Do nothing in that case. - if (mHash.Get(str, nullptr)) + if (mHash.GetWeak(str)) return NS_OK; nsCOMPtr catMan = @@ -133,17 +123,15 @@ nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic, str.get(), getter_Copies(entryValue)); - mHash.Put(str, entryValue); - mListener->EntryAdded(entryValue); - } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID) == 0) { - nsAutoCString val; - if (mHash.Get(str, &val)) { - mHash.Remove(str); - mListener->EntryRemoved(val); + nsCOMPtr service = do_GetService(entryValue.get()); + + if (service) { + mHash.Put(str, service); } + } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID) == 0) { + mHash.Remove(str); } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID) == 0) { mHash.Clear(); - mListener->CategoryCleared(); } return NS_OK; } diff --git a/xpcom/glue/nsCategoryCache.h b/xpcom/glue/nsCategoryCache.h index ff9821d9819..a0d756e2bfb 100644 --- a/xpcom/glue/nsCategoryCache.h +++ b/xpcom/glue/nsCategoryCache.h @@ -16,39 +16,30 @@ #include "nsAutoPtr.h" #include "nsCOMArray.h" -#include "nsDataHashtable.h" +#include "nsInterfaceHashtable.h" #include "nsXPCOM.h" -class NS_NO_VTABLE nsCategoryListener { - protected: - // no virtual destructor (people shouldn't delete through an - // nsCategoryListener pointer) - ~nsCategoryListener() {} - +class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver +{ public: - virtual void EntryAdded(const nsCString& aValue) = 0; - virtual void EntryRemoved(const nsCString& aValue) = 0; - virtual void CategoryCleared() = 0; -}; - -class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver { - public: - nsCategoryObserver(const char* aCategory, - nsCategoryListener* aCategoryListener); + nsCategoryObserver(const char* aCategory); ~nsCategoryObserver(); void ListenerDied(); + nsInterfaceHashtable& GetHash() + { + return mHash; + } NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER private: - NS_HIDDEN_(void) RemoveObservers(); + void RemoveObservers(); - nsDataHashtable mHash; - nsCategoryListener* mListener; - nsCString mCategory; - bool mObserversRemoved; + nsInterfaceHashtable mHash; + nsCString mCategory; + bool mObserversRemoved; }; /** @@ -59,59 +50,46 @@ class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver { * then get the name of the category. */ template -class nsCategoryCache MOZ_FINAL : protected nsCategoryListener { +class nsCategoryCache MOZ_FINAL +{ public: - explicit nsCategoryCache(const char* aCategory); - ~nsCategoryCache() { if (mObserver) mObserver->ListenerDied(); } + explicit nsCategoryCache(const char* aCategory) + : mCategoryName(aCategory) + { + } + ~nsCategoryCache() { + if (mObserver) + mObserver->ListenerDied(); + } - const nsCOMArray& GetEntries() { + void GetEntries(nsCOMArray& result) { // Lazy initialization, so that services in this category can't // cause reentrant getService (bug 386376) if (!mObserver) - mObserver = new nsCategoryObserver(mCategoryName.get(), this); - return mEntries; - } - protected: - virtual void EntryAdded(const nsCString& aValue); - virtual void EntryRemoved(const nsCString& aValue); - virtual void CategoryCleared(); - private: - friend class CategoryObserver; + mObserver = new nsCategoryObserver(mCategoryName.get()); + mObserver->GetHash().EnumerateRead(EntriesToArray, &result); + } + + private: // Not to be implemented nsCategoryCache(const nsCategoryCache&); + static PLDHashOperator EntriesToArray(const nsACString& key, + nsISupports* entry, void* arg) + { + nsCOMArray& entries = *static_cast*>(arg); + + nsCOMPtr service = do_QueryInterface(entry); + if (service) { + entries.AppendObject(service); + } + return PL_DHASH_NEXT; + } + nsCString mCategoryName; - nsCOMArray mEntries; nsRefPtr mObserver; + }; -// ----------------------------------- -// Implementation - -template -nsCategoryCache::nsCategoryCache(const char* aCategory) -: mCategoryName(aCategory) -{ -} - -template -void nsCategoryCache::EntryAdded(const nsCString& aValue) { - nsCOMPtr catEntry = do_GetService(aValue.get()); - if (catEntry) - mEntries.AppendObject(catEntry); -} - -template -void nsCategoryCache::EntryRemoved(const nsCString& aValue) { - nsCOMPtr catEntry = do_GetService(aValue.get()); - if (catEntry) - mEntries.RemoveObject(catEntry); -} - -template -void nsCategoryCache::CategoryCleared() { - mEntries.Clear(); -} - #endif