Bug 474704 - drop channel on cross-site load failure to avoid leak. r=bz,jonas, sr=jonas
authorJohn Daggett <jdaggett@mozilla.com>
Sat, 31 Jan 2009 17:58:42 +0900
changeset 24480 d27323792a598c3df63bfff5e6b44e4281960b62
parent 24479 ff62653d0cd846c7797c7b3a3a5c438f279d1c23
child 24481 1ef539e37fbaefc3f7547102f44940f722cdc7b4
push idunknown
push userunknown
push dateunknown
reviewersbz, jonas, jonas
bugs474704
milestone1.9.2a1pre
Bug 474704 - drop channel on cross-site load failure to avoid leak. r=bz,jonas, sr=jonas
content/base/src/nsCrossSiteListenerProxy.cpp
layout/style/crashtests/crashtests.list
layout/style/nsFontFaceLoader.cpp
layout/style/nsFontFaceLoader.h
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -71,16 +71,21 @@ nsCrossSiteListenerProxy::nsCrossSiteLis
     mRequestApproved(PR_FALSE),
     mHasBeenCrossSite(PR_FALSE),
     mIsPreflight(PR_FALSE)
 {
   aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
   aChannel->SetNotificationCallbacks(this);
 
   *aResult = UpdateChannel(aChannel);
+  if (NS_FAILED(*aResult)) {
+    mOuterListener = nsnull;
+    mRequestingPrincipal = nsnull;
+    mOuterNotificationCallbacks = nsnull;
+  }
 }
 
 
 nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
                                                    nsIPrincipal* aRequestingPrincipal,
                                                    nsIChannel* aChannel,
                                                    PRBool aWithCredentials,
                                                    const nsCString& aPreflightMethod,
@@ -94,16 +99,21 @@ nsCrossSiteListenerProxy::nsCrossSiteLis
     mIsPreflight(PR_TRUE),
     mPreflightMethod(aPreflightMethod),
     mPreflightHeaders(aPreflightHeaders)
 {
   aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
   aChannel->SetNotificationCallbacks(this);
 
   *aResult = UpdateChannel(aChannel);
+  if (NS_FAILED(*aResult)) {
+    mOuterListener = nsnull;
+    mRequestingPrincipal = nsnull;
+    mOuterNotificationCallbacks = nsnull;
+  }
 }
 
 NS_IMETHODIMP
 nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
                                          nsISupports* aContext)
 {
   mRequestApproved = NS_SUCCEEDED(CheckRequestApproved(aRequest, PR_FALSE));
   if (!mRequestApproved) {
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -21,13 +21,14 @@ load 444848-1.html
 load 447776-1.html
 load 447783-1.html
 load 448161-1.html
 load 448161-2.html
 load 456196.html
 load 460217-1.html
 load 466845-1.html
 load 472195-1.html
+load 472237-1.html # will fail, test for leak (474704)
 HTTP(..) load 472237-1.html
 load 473720-1.html
 load 473892-1.html
 load 473914-1.html
 load long-url-list-stack-overflow.html
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -302,16 +302,19 @@ nsUserFontSet::StartLoad(gfxFontEntry *a
                            &inherits);
   if (NS_SUCCEEDED(rv) && inherits) {
     // allow data, javascript, etc URI's
     rv = channel->AsyncOpen(streamLoader, nsnull);
   } else {
     nsCOMPtr<nsIStreamListener> listener =
       new nsCrossSiteListenerProxy(streamLoader, principal, channel, 
                                    PR_FALSE, &rv);
+    if (NS_FAILED(rv)) {
+      fontLoader->DropChannel();  // explicitly need to break ref cycle
+    }
     NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = channel->AsyncOpen(listener, nsnull);
   }
 
   if (NS_SUCCEEDED(rv)) {
     mLoaders.PutEntry(fontLoader);
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -100,20 +100,22 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTREAMLOADEROBSERVER 
 
   // initiate the load
   nsresult Init();
   // cancel the load and remove its reference to mFontSet
   void Cancel();
 
+  void DropChannel() { mChannel = nsnull; }
+
   static nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
                                    nsIURI* aTargetURI,
                                    nsISupports* aContext);
-  
+
 private:
   nsRefPtr<gfxFontEntry>  mFontEntry;
   nsCOMPtr<nsIURI>        mFontURI;
   nsRefPtr<nsUserFontSet> mFontSet;
   nsCOMPtr<nsIChannel>    mChannel;
 };
 
 #endif /* !defined(nsFontFaceLoader_h_) */