Comment 57 for bug 225379

Revision history for this message
In , Mc-hack (mc-hack) wrote :

(In reply to comment #54)
> Post a diff?

Oh. Sorry. Sure. To apply, cut and paste this text to a file called, say, "mjpeg.patch" and cd to mozilla/modules/libpr0n/src, then

% patch < mjpeg.patch

--- imgRequest.h-orig 2008-09-15 14:25:41.000000000 +0200
+++ imgRequest.h 2008-09-15 14:26:13.000000000 +0200
@@ -49,6 +49,7 @@
 #include "nsICacheEntryDescriptor.h"
 #include "nsIContentSniffer.h"
 #include "nsIRequest.h"
+#include "nsIChannel.h"
 #include "nsIProperties.h"
 #include "nsIStreamListener.h"
 #include "nsIURI.h"
@@ -151,6 +152,7 @@
   NS_DECL_NSIREQUESTOBSERVER

 private:
+ nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsIRequest> mRequest;
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIPrincipal> mPrincipal;
--- imgRequest.cpp-orig 2008-09-15 14:25:49.000000000 +0200
+++ imgRequest.cpp 2008-09-15 14:26:16.000000000 +0200
@@ -106,6 +106,7 @@
   if (!mProperties)
     return NS_ERROR_OUT_OF_MEMORY;

+ mChannel = do_QueryInterface(aRequest);
   mURI = aURI;
   mRequest = aRequest;

@@ -171,7 +172,7 @@
        This way, if a proxy is destroyed without calling cancel on it, it won't leak
        and won't leave a bad pointer in mObservers.
      */
- if (mRequest && mLoading && NS_FAILED(aStatus)) {
+ if (mChannel && mRequest && mLoading && NS_FAILED(aStatus)) {
       LOG_MSG(gImgLog, "imgRequest::RemoveProxy", "load in progress. canceling");

       mImageStatus |= imgIRequest::STATUS_LOAD_PARTIAL;
@@ -292,14 +293,16 @@
     RemoveFromCache();
   }

- if (mRequest && mLoading)
+ if (mChannel && mRequest && mLoading) {
+ /* Cancel both channel and request. */
     mRequest->Cancel(aStatus);
+ mChannel->Cancel(aStatus);
+ }
 }

 nsresult imgRequest::GetURI(nsIURI **aURI)
 {
   LOG_FUNC(gImgLog, "imgRequest::GetURI");
-
   if (mURI) {
     *aURI = mURI;
     NS_ADDREF(*aURI);
@@ -587,7 +590,24 @@

   NS_ASSERTION(!mDecoder, "imgRequest::OnStartRequest -- we already have a decoder");

+ /* if mChannel isn't set here, use aRequest.
+ *
+ * Having mChannel set is important for Canceling the load, and
+ * since we set mChannel to null in OnStopRequest. Since with
+ * multipart/x-mixed-replace, you can get multiple OnStartRequests,
+ * we need to reinstance mChannel so that when/if Cancel() gets
+ * called, we have a channel to cancel and we don't leave the
+ * channel open forever.
+ */
   nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest));
+
+ if (!mChannel) {
+ if (mpchan)
+ mpchan->GetBaseChannel(getter_AddRefs(mChannel));
+ else
+ mChannel = do_QueryInterface(aRequest);
+ }
+
   if (mpchan)
       mIsMultiPartChannel = PR_TRUE;

@@ -674,6 +694,8 @@
   // Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace...
   if (mObservers.IsEmpty()) {
     this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
+ // Shut down the channel explictly.
+ mChannel->Cancel(NS_IMAGELIB_ERROR_FAILURE);
   }

   return NS_OK;
@@ -711,6 +733,10 @@
     mRequest = nsnull; // we no longer need the request
   }

+ if (mChannel) {
+ mChannel = nsnull; // we no longer need the channel
+ }
+
   // If mImage is still null, we didn't properly load the image.
   if (NS_FAILED(status) || !mImage) {
     this->Cancel(status); // sets status, stops animations, removes from cache