Bug 1611081 - Add multipart support to nsStreamListenerTee. r=mayhemer
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 16 Mar 2020 00:58:34 +0000
changeset 518884 77436c074c255a2b407685db4c4e5b9e5707b331
parent 518883 ef75f461147c5148755e505ed8b8c2d9ca20f856
child 518885 10998b6bf6d86d1201bdc9c0027154cf42970315
push id37218
push userrmaries@mozilla.com
push dateMon, 16 Mar 2020 09:28:04 +0000
treeherdermozilla-central@6199f7b91e8b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1611081
milestone76.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1611081 - Add multipart support to nsStreamListenerTee. r=mayhemer Differential Revision: https://phabricator.services.mozilla.com/D66713
devtools/server/actors/network-monitor/network-response-listener.js
netwerk/base/nsStreamListenerTee.cpp
netwerk/base/nsStreamListenerTee.h
--- a/devtools/server/actors/network-monitor/network-response-listener.js
+++ b/devtools/server/actors/network-monitor/network-response-listener.js
@@ -210,16 +210,17 @@ NetworkResponseListener.prototype = {
   /**
    * See documentation at
    * https://developer.mozilla.org/En/NsIRequestObserver
    *
    * @param nsIRequest request
    * @param nsISupports context
    */
   onStartRequest: function(request) {
+    request = request.QueryInterface(Ci.nsIChannel);
     // Converter will call this again, we should just ignore that.
     if (this.request) {
       return;
     }
 
     this.request = request;
     this._getSecurityInfo();
     this._findOpenResponse();
--- a/netwerk/base/nsStreamListenerTee.cpp
+++ b/netwerk/base/nsStreamListenerTee.cpp
@@ -4,21 +4,28 @@
 
 #include "nsStreamListenerTee.h"
 #include "nsProxyRelease.h"
 
 namespace mozilla {
 namespace net {
 
 NS_IMPL_ISUPPORTS(nsStreamListenerTee, nsIStreamListener, nsIRequestObserver,
-                  nsIStreamListenerTee, nsIThreadRetargetableStreamListener)
+                  nsIStreamListenerTee, nsIThreadRetargetableStreamListener,
+                  nsIMultiPartChannelListener)
 
 NS_IMETHODIMP
 nsStreamListenerTee::OnStartRequest(nsIRequest* request) {
   NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
+
+  nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(request);
+  if (multiPartChannel) {
+    mIsMultiPart = true;
+  }
+
   nsresult rv1 = mListener->OnStartRequest(request);
   nsresult rv2 = NS_OK;
   if (mObserver) rv2 = mObserver->OnStartRequest(request);
 
   // Preserve NS_SUCCESS_XXX in rv1 in case mObserver didn't throw
   return (NS_FAILED(rv2) && NS_SUCCEEDED(rv1)) ? rv2 : rv1;
 }
 
@@ -26,26 +33,31 @@ NS_IMETHODIMP
 nsStreamListenerTee::OnStopRequest(nsIRequest* request, nsresult status) {
   NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
   // it is critical that we close out the input stream tee
   if (mInputTee) {
     mInputTee->SetSink(nullptr);
     mInputTee = nullptr;
   }
 
-  // release sink on the same thread where the data was written (bug 716293)
-  if (mEventTarget) {
-    NS_ProxyRelease("nsStreamListenerTee::mSink", mEventTarget, mSink.forget());
-  } else {
-    mSink = nullptr;
+  if (!mIsMultiPart) {
+    // release sink on the same thread where the data was written (bug 716293)
+    if (mEventTarget) {
+      NS_ProxyRelease("nsStreamListenerTee::mSink", mEventTarget,
+                      mSink.forget());
+    } else {
+      mSink = nullptr;
+    }
   }
 
   nsresult rv = mListener->OnStopRequest(request, status);
   if (mObserver) mObserver->OnStopRequest(request, status);
-  mObserver = nullptr;
+  if (!mIsMultiPart) {
+    mObserver = nullptr;
+  }
   return rv;
 }
 
 NS_IMETHODIMP
 nsStreamListenerTee::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
                                      uint64_t offset, uint32_t count) {
   NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
   NS_ENSURE_TRUE(mSink, NS_ERROR_NOT_INITIALIZED);
@@ -70,16 +82,40 @@ nsStreamListenerTee::OnDataAvailable(nsI
 
     tee = mInputTee;
   }
 
   return mListener->OnDataAvailable(request, tee, offset, count);
 }
 
 NS_IMETHODIMP
+nsStreamListenerTee::OnAfterLastPart(nsresult aStatus) {
+  // release sink on the same thread where the data was written (bug 716293)
+  if (mEventTarget) {
+    NS_ProxyRelease("nsStreamListenerTee::mSink", mEventTarget, mSink.forget());
+  } else {
+    mSink = nullptr;
+  }
+
+  if (nsCOMPtr<nsIMultiPartChannelListener> multi =
+          do_QueryInterface(mListener)) {
+    multi->OnAfterLastPart(aStatus);
+  }
+  if (!SameCOMIdentity(mListener, mObserver)) {
+    if (nsCOMPtr<nsIMultiPartChannelListener> multi =
+            do_QueryInterface(mObserver)) {
+      multi->OnAfterLastPart(aStatus);
+    }
+  }
+
+  mObserver = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsStreamListenerTee::CheckListenerChain() {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
   nsresult rv = NS_OK;
   nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
       do_QueryInterface(mListener, &rv);
   if (retargetableListener) {
     rv = retargetableListener->CheckListenerChain();
   }
--- a/netwerk/base/nsStreamListenerTee.h
+++ b/netwerk/base/nsStreamListenerTee.h
@@ -6,37 +6,41 @@
 #define nsStreamListenerTee_h__
 
 #include "nsIStreamListenerTee.h"
 #include "nsIThreadRetargetableStreamListener.h"
 #include "nsIInputStreamTee.h"
 #include "nsIOutputStream.h"
 #include "nsCOMPtr.h"
 #include "nsIEventTarget.h"
+#include "nsIMultiPartChannel.h"
 
 namespace mozilla {
 namespace net {
 
 class nsStreamListenerTee : public nsIStreamListenerTee,
-                            public nsIThreadRetargetableStreamListener {
+                            public nsIThreadRetargetableStreamListener,
+                            public nsIMultiPartChannelListener {
  public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
   NS_DECL_NSISTREAMLISTENERTEE
+  NS_DECL_NSIMULTIPARTCHANNELLISTENER
 
   nsStreamListenerTee() = default;
 
  private:
   virtual ~nsStreamListenerTee() = default;
 
   nsCOMPtr<nsIInputStreamTee> mInputTee;
   nsCOMPtr<nsIOutputStream> mSink;
   nsCOMPtr<nsIStreamListener> mListener;
   nsCOMPtr<nsIRequestObserver> mObserver;
   nsCOMPtr<nsIEventTarget> mEventTarget;
+  bool mIsMultiPart = false;
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif