diff --git a/content/html/content/src/nsHTMLDNSPrefetch.cpp b/content/html/content/src/nsHTMLDNSPrefetch.cpp --- a/content/html/content/src/nsHTMLDNSPrefetch.cpp +++ b/content/html/content/src/nsHTMLDNSPrefetch.cpp @@ -50,16 +50,17 @@ #include "nsIDNSService.h" #include "nsICancelable.h" #include "nsContentUtils.h" #include "nsGkAtoms.h" #include "nsIDocument.h" #include "nsThreadUtils.h" #include "nsGenericHTMLElement.h" #include "nsITimer.h" +#include "nsIObserverService.h" static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID); static PRBool sDisablePrefetchHTTPSPref; static PRBool sInitialized = PR_FALSE; static nsIDNSService *sDNSService = nsnull; static nsHTMLDNSPrefetch::nsDeferrals *sPrefetches = nsnull; nsresult @@ -204,31 +205,44 @@ nsHTMLDNSPrefetch::nsDeferrals::nsDeferr mActiveLoaderCount(0), mTimerArmed(PR_FALSE) { mTimer = do_CreateInstance("@mozilla.org/timer;1"); } nsHTMLDNSPrefetch::nsDeferrals::~nsDeferrals() { + nsresult rv; + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1", &rv); + if (NS_SUCCEEDED(rv)) + observerService->RemoveObserver(this, "xpcom-shutdown"); + if (mTimerArmed) { mTimerArmed = PR_FALSE; mTimer->Cancel(); } + Flush(); +} + +NS_IMPL_THREADSAFE_ISUPPORTS4(nsHTMLDNSPrefetch::nsDeferrals, + nsIDNSListener, + nsIWebProgressListener, + nsISupportsWeakReference, + nsIObserver) + +void +nsHTMLDNSPrefetch::nsDeferrals::Flush() +{ while (mHead != mTail) { mEntries[mTail].mElement = nsnull; mTail = (mTail + 1) & sMaxDeferredMask; } } - -NS_IMPL_THREADSAFE_ISUPPORTS3(nsHTMLDNSPrefetch::nsDeferrals, - nsIDNSListener, - nsIWebProgressListener, - nsISupportsWeakReference) nsresult nsHTMLDNSPrefetch::nsDeferrals::Add(PRUint16 flags, nsGenericHTMLElement *aElement) { // The FIFO has no lock, so it can only be accessed on main thread NS_ASSERTION(NS_IsMainThread(), "nsDeferrals::Add must be on main thread"); if (((mHead + 1) & sMaxDeferredMask) == mTail) @@ -279,16 +293,23 @@ void void nsHTMLDNSPrefetch::nsDeferrals::Activate() { // Register as an observer for the document loader nsCOMPtr progress = do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID); if (progress) progress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT); + + // Register as an observer for xpcom shutdown events so we can drop any element refs + nsresult rv; + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1", &rv); + if (NS_SUCCEEDED(rv)) + observerService->AddObserver(this, "xpcom-shutdown", PR_TRUE); } // nsITimer related method void nsHTMLDNSPrefetch::nsDeferrals::Tick(nsITimer *aTimer, void *aClosure) { nsHTMLDNSPrefetch::nsDeferrals *self = (nsHTMLDNSPrefetch::nsDeferrals *) aClosure; @@ -374,8 +395,21 @@ nsHTMLDNSPrefetch::nsDeferrals::OnStatus NS_IMETHODIMP nsHTMLDNSPrefetch::nsDeferrals::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) { return NS_OK; } + +//////////// nsIObserver method + +NS_IMETHODIMP +nsHTMLDNSPrefetch::nsDeferrals::Observe(nsISupports *subject, + const char *topic, + const PRUnichar *data) +{ + if (!strcmp(topic, "xpcom-shutdown")) + Flush(); + + return NS_OK; +} diff --git a/content/html/content/src/nsHTMLDNSPrefetch.h b/content/html/content/src/nsHTMLDNSPrefetch.h --- a/content/html/content/src/nsHTMLDNSPrefetch.h +++ b/content/html/content/src/nsHTMLDNSPrefetch.h @@ -41,16 +41,17 @@ #include "nsCOMPtr.h" #include "nsAutoPtr.h" #include "nsString.h" #include "nsIDNSListener.h" #include "nsIWebProgressListener.h" #include "nsWeakReference.h" +#include "nsIObserver.h" class nsIDocument; class nsGenericHTMLElement; class nsITimer; class nsHTMLDNSPrefetch { public: @@ -81,29 +82,32 @@ private: static nsresult Prefetch(nsAString &host, PRUint16 flags); static nsresult Prefetch(nsGenericHTMLElement *aElement, PRUint16 flags); static PRBool IsSecureBaseContext(nsIDocument *aDocument); public: class nsDeferrals : public nsIDNSListener , public nsIWebProgressListener , public nsSupportsWeakReference + , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIDNSLISTENER NS_DECL_NSIWEBPROGRESSLISTENER - + NS_DECL_NSIOBSERVER + nsDeferrals(); void Activate(); nsresult Add(PRUint16 flags, nsGenericHTMLElement *aElement); private: ~nsDeferrals(); + void Flush(); void SubmitQueue(); PRUint16 mHead; PRUint16 mTail; PRUint32 mActiveLoaderCount; nsCOMPtr mTimer;