Bug 1578919 - Don't allow AutoIPCStream to outlive its IPCStream r=asuth
authorPerry Jiang <perry@mozilla.com>
Fri, 11 Oct 2019 23:22:31 +0000
changeset 497333 f62280bf339a179ad3a90348e1f6ff43eb8c6540
parent 497332 15e4b16324a618ac62e7100995b5d4009c07392f
child 497334 0464faa83b959a5f00f2e6e7951d2818f419c6ac
push id36682
push userncsoregi@mozilla.com
push dateSat, 12 Oct 2019 09:52:03 +0000
treeherdermozilla-central@06ea2371f897 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1578919
milestone71.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 1578919 - Don't allow AutoIPCStream to outlive its IPCStream r=asuth In ServiceWorkerPrivateImpl::SendFetchEvent, a heap-allocated AutoIPCStream can point to a stack-allocated IPCStream (part of an IPCInternalRequest). If this IPCStream is destroyed before the AutoIPCStream, the AutoIPCStream will have a dangling pointer (and this is the case if SendFetchEvent is called when the Service Worker's state is "activating" rather than "activated"). This patch moves around the logic to handle the AutoIPCStream's lifetime to ensure it its lifetime is within its IPCStream's lifetime. The larger issue might be that AutoIPCStream doesn't have inherent lifetime guarantees (it'll definitely outlive its IPCStream if it points to its embedded one, but it doesn't own any external IPCStreams it might point to). Differential Revision: https://phabricator.services.mozilla.com/D48935
dom/serviceworkers/FetchEventOpChild.cpp
dom/serviceworkers/FetchEventOpChild.h
dom/serviceworkers/ServiceWorkerPrivateImpl.cpp
dom/serviceworkers/ServiceWorkerPrivateImpl.h
--- a/dom/serviceworkers/FetchEventOpChild.cpp
+++ b/dom/serviceworkers/FetchEventOpChild.cpp
@@ -11,41 +11,52 @@
 #include "MainThreadUtils.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsIChannel.h"
 #include "nsIConsoleReportCollector.h"
 #include "nsIContentPolicy.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsIHttpHeaderVisitor.h"
 #include "nsIInputStream.h"
 #include "nsILoadInfo.h"
 #include "nsINetworkInterceptController.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 #include "nsISupportsImpl.h"
 #include "nsIURI.h"
+#include "nsIUploadChannel2.h"
 #include "nsNetUtil.h"
 #include "nsProxyRelease.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 #include "ServiceWorkerPrivate.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
+#include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/dom/InternalHeaders.h"
+#include "mozilla/dom/InternalRequest.h"
 #include "mozilla/dom/InternalResponse.h"
 #include "mozilla/dom/PRemoteWorkerControllerChild.h"
 #include "mozilla/dom/ServiceWorkerRegistrationInfo.h"
 #include "mozilla/net/NeckoChannelParams.h"
 
 namespace mozilla {
+
+using ipc::AutoIPCStream;
+using ipc::BackgroundChild;
+using ipc::PBackgroundChild;
+
 namespace dom {
 
 namespace {
 
 bool CSPPermitsResponse(nsILoadInfo* aLoadInfo, InternalResponse* aResponse,
                         const nsACString& aWorkerScriptSpec) {
   AssertIsOnMainThread();
   MOZ_ASSERT(aLoadInfo);
@@ -169,33 +180,219 @@ class SynthesizeResponseWatcher final : 
   nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
   const bool mIsNonSubresourceRequest;
   const FetchEventRespondWithClosure mClosure;
   const nsString mRequestURL;
 };
 
 NS_IMPL_ISUPPORTS(SynthesizeResponseWatcher, nsIInterceptedBodyCallback)
 
+class HeaderFiller final : public nsIHttpHeaderVisitor {
+ public:
+  NS_DECL_ISUPPORTS
+
+  explicit HeaderFiller(HeadersGuardEnum aGuard)
+      : mInternalHeaders(new InternalHeaders(aGuard)) {
+    MOZ_ASSERT(mInternalHeaders);
+  }
+
+  NS_IMETHOD
+  VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
+    ErrorResult result;
+    mInternalHeaders->Append(aHeader, aValue, result);
+
+    if (NS_WARN_IF(result.Failed())) {
+      return result.StealNSResult();
+    }
+
+    return NS_OK;
+  }
+
+  RefPtr<InternalHeaders> Extract() {
+    return RefPtr<InternalHeaders>(std::move(mInternalHeaders));
+  }
+
+ private:
+  ~HeaderFiller() = default;
+
+  RefPtr<InternalHeaders> mInternalHeaders;
+};
+
+NS_IMPL_ISUPPORTS(HeaderFiller, nsIHttpHeaderVisitor)
+
+nsresult GetIPCInternalRequest(nsIInterceptedChannel* aChannel,
+                               IPCInternalRequest* aOutRequest,
+                               UniquePtr<AutoIPCStream>& aAutoStream) {
+  AssertIsOnMainThread();
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = aChannel->GetSecureUpgradedChannelURI(getter_AddRefs(uri));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> uriNoFragment;
+  rv = NS_GetURIWithoutRef(uri, getter_AddRefs(uriNoFragment));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIChannel> underlyingChannel;
+  rv = aChannel->GetChannel(getter_AddRefs(underlyingChannel));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(underlyingChannel);
+  MOZ_ASSERT(httpChannel, "How come we don't have an HTTP channel?");
+
+  nsCOMPtr<nsIHttpChannelInternal> internalChannel =
+      do_QueryInterface(httpChannel);
+  NS_ENSURE_TRUE(internalChannel, NS_ERROR_NOT_AVAILABLE);
+
+  nsCOMPtr<nsICacheInfoChannel> cacheInfoChannel =
+      do_QueryInterface(underlyingChannel);
+
+  nsAutoCString spec;
+  rv = uriNoFragment->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString fragment;
+  rv = uri->GetRef(fragment);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString method;
+  rv = httpChannel->GetRequestMethod(method);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // This is safe due to static_asserts in ServiceWorkerManager.cpp
+  uint32_t cacheModeInt;
+  rv = internalChannel->GetFetchCacheMode(&cacheModeInt);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  RequestCache cacheMode = static_cast<RequestCache>(cacheModeInt);
+
+  RequestMode requestMode =
+      InternalRequest::MapChannelToRequestMode(underlyingChannel);
+
+  // This is safe due to static_asserts in ServiceWorkerManager.cpp
+  uint32_t redirectMode;
+  rv = internalChannel->GetRedirectMode(&redirectMode);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  RequestRedirect requestRedirect = static_cast<RequestRedirect>(redirectMode);
+
+  RequestCredentials requestCredentials =
+      InternalRequest::MapChannelToRequestCredentials(underlyingChannel);
+
+  nsAutoString referrer;
+  ReferrerPolicy referrerPolicy = ReferrerPolicy::_empty;
+
+  nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo();
+  if (referrerInfo) {
+    referrerPolicy = referrerInfo->ReferrerPolicy();
+    Unused << referrerInfo->GetComputedReferrerSpec(referrer);
+  }
+
+  uint32_t loadFlags;
+  rv = underlyingChannel->GetLoadFlags(&loadFlags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsILoadInfo> loadInfo;
+  rv = underlyingChannel->GetLoadInfo(getter_AddRefs(loadInfo));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_STATE(loadInfo);
+
+  nsContentPolicyType contentPolicyType = loadInfo->InternalContentPolicyType();
+
+  nsAutoString integrity;
+  rv = internalChannel->GetIntegrityMetadata(integrity);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  RefPtr<HeaderFiller> headerFiller =
+      MakeRefPtr<HeaderFiller>(HeadersGuardEnum::Request);
+  rv = httpChannel->VisitNonDefaultRequestHeaders(headerFiller);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  RefPtr<InternalHeaders> internalHeaders = headerFiller->Extract();
+
+  ErrorResult result;
+  internalHeaders->SetGuard(HeadersGuardEnum::Immutable, result);
+  if (NS_WARN_IF(result.Failed())) {
+    return result.StealNSResult();
+  }
+
+  nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(httpChannel);
+  nsCOMPtr<nsIInputStream> uploadStream;
+  int64_t uploadStreamContentLength = -1;
+  if (uploadChannel) {
+    rv = uploadChannel->CloneUploadStream(&uploadStreamContentLength,
+                                          getter_AddRefs(uploadStream));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  RefPtr<InternalRequest> internalRequest = new InternalRequest(
+      spec, fragment, method, internalHeaders.forget(), cacheMode, requestMode,
+      requestRedirect, requestCredentials, referrer, referrerPolicy,
+      contentPolicyType, integrity);
+  internalRequest->SetBody(uploadStream, uploadStreamContentLength);
+  internalRequest->SetCreatedByFetchEvent();
+
+  nsAutoCString alternativeDataType;
+  if (cacheInfoChannel &&
+      !cacheInfoChannel->PreferredAlternativeDataTypes().IsEmpty()) {
+    // TODO: the internal request probably needs all the preferred types.
+    alternativeDataType.Assign(
+        cacheInfoChannel->PreferredAlternativeDataTypes()[0].type());
+    internalRequest->SetPreferredAlternativeDataType(alternativeDataType);
+  }
+
+  PBackgroundChild* bgChild = BackgroundChild::GetForCurrentThread();
+
+  if (NS_WARN_IF(!bgChild)) {
+    return NS_ERROR_DOM_INVALID_STATE_ERR;
+  }
+
+  internalRequest->ToIPC(aOutRequest, bgChild, aAutoStream);
+
+  return NS_OK;
+}
+
 }  // anonymous namespace
 
-/* static */ RefPtr<GenericPromise> FetchEventOpChild::Create(
+/* static */ RefPtr<GenericPromise> FetchEventOpChild::SendFetchEvent(
     PRemoteWorkerControllerChild* aManager,
     ServiceWorkerFetchEventOpArgs&& aArgs,
     nsCOMPtr<nsIInterceptedChannel> aInterceptedChannel,
     RefPtr<ServiceWorkerRegistrationInfo> aRegistration,
     RefPtr<KeepAliveToken>&& aKeepAliveToken) {
   AssertIsOnMainThread();
   MOZ_ASSERT(aManager);
   MOZ_ASSERT(aInterceptedChannel);
   MOZ_ASSERT(aKeepAliveToken);
 
   FetchEventOpChild* actor = new FetchEventOpChild(
       std::move(aArgs), std::move(aInterceptedChannel),
       std::move(aRegistration), std::move(aKeepAliveToken));
+
+  // autoStream will contain a pointer into the IPCInternalRequest passed into
+  // GetIPCInternalRequest, so autoStream shouldn't outlive that
+  // IPCInternalRequest or the containing FetchEventOpChild.
+  auto autoStream = MakeUnique<AutoIPCStream>();
+
+  // const_cast-ing the IPCInternalRequest is okay because this is conceptually
+  // part of initializing actor->mArgs, and `autoStream` needs its
+  // IPCStream (physically part of actor->mArgs.internalRequest()) to be in its
+  // final location in memory, so actor->mArgs must be created before this call.
+  nsresult rv = GetIPCInternalRequest(
+      actor->mInterceptedChannel,
+      const_cast<IPCInternalRequest*>(&actor->mArgs.internalRequest()),
+      autoStream);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    // `actor` must be manually delete-d before the actor tree can manage its
+    // lifetime starting with SendPFetchEventOpConstructor.
+    delete actor;
+    return GenericPromise::CreateAndReject(rv, __func__);
+  }
+
   Unused << aManager->SendPFetchEventOpConstructor(actor, actor->mArgs);
+  autoStream->TakeOptionalValue();
+
   return actor->mPromiseHolder.Ensure(__func__);
 }
 
 FetchEventOpChild::~FetchEventOpChild() {
   AssertIsOnMainThread();
   MOZ_ASSERT(mInterceptedChannelHandled);
   MOZ_DIAGNOSTIC_ASSERT(mPromiseHolder.IsEmpty());
 }
--- a/dom/serviceworkers/FetchEventOpChild.h
+++ b/dom/serviceworkers/FetchEventOpChild.h
@@ -25,17 +25,17 @@ class ServiceWorkerRegistrationInfo;
 
 /**
  * FetchEventOpChild represents an in-flight FetchEvent operation.
  */
 class FetchEventOpChild final : public PFetchEventOpChild {
   friend class PFetchEventOpChild;
 
  public:
-  static RefPtr<GenericPromise> Create(
+  static RefPtr<GenericPromise> SendFetchEvent(
       PRemoteWorkerControllerChild* aManager,
       ServiceWorkerFetchEventOpArgs&& aArgs,
       nsCOMPtr<nsIInterceptedChannel> aInterceptedChannel,
       RefPtr<ServiceWorkerRegistrationInfo> aRegistrationInfo,
       RefPtr<KeepAliveToken>&& aKeepAliveToken);
 
   ~FetchEventOpChild();
 
--- a/dom/serviceworkers/ServiceWorkerPrivateImpl.cpp
+++ b/dom/serviceworkers/ServiceWorkerPrivateImpl.cpp
@@ -11,220 +11,49 @@
 #include "MainThreadUtils.h"
 #include "js/ErrorReport.h"
 #include "nsContentUtils.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsICacheInfoChannel.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannel.h"
-#include "nsIHttpChannelInternal.h"
-#include "nsIHttpHeaderVisitor.h"
 #include "nsIInputStream.h"
 #include "nsILoadInfo.h"
 #include "nsINetworkInterceptController.h"
 #include "nsIObserverService.h"
 #include "nsIURI.h"
-#include "nsIUploadChannel2.h"
 #include "nsThreadUtils.h"
 
 #include "ServiceWorkerManager.h"
 #include "ServiceWorkerRegistrationInfo.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/dom/FetchEventOpChild.h"
 #include "mozilla/dom/InternalHeaders.h"
-#include "mozilla/dom/InternalRequest.h"
 #include "mozilla/dom/ReferrerInfo.h"
 #include "mozilla/dom/RemoteWorkerControllerChild.h"
 #include "mozilla/dom/ServiceWorkerBinding.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
 
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 
-namespace {
-
-class HeaderFiller final : public nsIHttpHeaderVisitor {
- public:
-  NS_DECL_ISUPPORTS
-
-  explicit HeaderFiller(HeadersGuardEnum aGuard)
-      : mInternalHeaders(new InternalHeaders(aGuard)) {
-    MOZ_ASSERT(mInternalHeaders);
-  }
-
-  NS_IMETHOD
-  VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
-    ErrorResult result;
-    mInternalHeaders->Append(aHeader, aValue, result);
-
-    if (NS_WARN_IF(result.Failed())) {
-      return result.StealNSResult();
-    }
-
-    return NS_OK;
-  }
-
-  RefPtr<InternalHeaders> Extract() {
-    return RefPtr<InternalHeaders>(std::move(mInternalHeaders));
-  }
-
- private:
-  ~HeaderFiller() = default;
-
-  RefPtr<InternalHeaders> mInternalHeaders;
-};
-
-NS_IMPL_ISUPPORTS(HeaderFiller, nsIHttpHeaderVisitor)
-
-nsresult GetIPCInternalRequest(nsIInterceptedChannel* aChannel,
-                               IPCInternalRequest* aOutRequest,
-                               UniquePtr<AutoIPCStream>& aAutoStream) {
-  AssertIsOnMainThread();
-
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = aChannel->GetSecureUpgradedChannelURI(getter_AddRefs(uri));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIURI> uriNoFragment;
-  rv = NS_GetURIWithoutRef(uri, getter_AddRefs(uriNoFragment));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIChannel> underlyingChannel;
-  rv = aChannel->GetChannel(getter_AddRefs(underlyingChannel));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(underlyingChannel);
-  MOZ_ASSERT(httpChannel, "How come we don't have an HTTP channel?");
-
-  nsCOMPtr<nsIHttpChannelInternal> internalChannel =
-      do_QueryInterface(httpChannel);
-  NS_ENSURE_TRUE(internalChannel, NS_ERROR_NOT_AVAILABLE);
-
-  nsCOMPtr<nsICacheInfoChannel> cacheInfoChannel =
-      do_QueryInterface(underlyingChannel);
-
-  nsAutoCString spec;
-  rv = uriNoFragment->GetSpec(spec);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoCString fragment;
-  rv = uri->GetRef(fragment);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoCString method;
-  rv = httpChannel->GetRequestMethod(method);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // This is safe due to static_asserts in ServiceWorkerManager.cpp
-  uint32_t cacheModeInt;
-  rv = internalChannel->GetFetchCacheMode(&cacheModeInt);
-  MOZ_ASSERT(NS_SUCCEEDED(rv));
-  RequestCache cacheMode = static_cast<RequestCache>(cacheModeInt);
-
-  RequestMode requestMode =
-      InternalRequest::MapChannelToRequestMode(underlyingChannel);
-
-  // This is safe due to static_asserts in ServiceWorkerManager.cpp
-  uint32_t redirectMode;
-  rv = internalChannel->GetRedirectMode(&redirectMode);
-  MOZ_ASSERT(NS_SUCCEEDED(rv));
-  RequestRedirect requestRedirect = static_cast<RequestRedirect>(redirectMode);
-
-  RequestCredentials requestCredentials =
-      InternalRequest::MapChannelToRequestCredentials(underlyingChannel);
-
-  nsAutoString referrer;
-  ReferrerPolicy referrerPolicy = ReferrerPolicy::_empty;
-
-  nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo();
-  if (referrerInfo) {
-    referrerPolicy = referrerInfo->ReferrerPolicy();
-    Unused << referrerInfo->GetComputedReferrerSpec(referrer);
-  }
-
-  uint32_t loadFlags;
-  rv = underlyingChannel->GetLoadFlags(&loadFlags);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsILoadInfo> loadInfo;
-  rv = underlyingChannel->GetLoadInfo(getter_AddRefs(loadInfo));
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_STATE(loadInfo);
-
-  nsContentPolicyType contentPolicyType = loadInfo->InternalContentPolicyType();
-
-  nsAutoString integrity;
-  rv = internalChannel->GetIntegrityMetadata(integrity);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  RefPtr<HeaderFiller> headerFiller =
-      MakeRefPtr<HeaderFiller>(HeadersGuardEnum::Request);
-  rv = httpChannel->VisitNonDefaultRequestHeaders(headerFiller);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  RefPtr<InternalHeaders> internalHeaders = headerFiller->Extract();
-
-  ErrorResult result;
-  internalHeaders->SetGuard(HeadersGuardEnum::Immutable, result);
-  if (NS_WARN_IF(result.Failed())) {
-    return result.StealNSResult();
-  }
-
-  nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(httpChannel);
-  nsCOMPtr<nsIInputStream> uploadStream;
-  int64_t uploadStreamContentLength = -1;
-  if (uploadChannel) {
-    rv = uploadChannel->CloneUploadStream(&uploadStreamContentLength,
-                                          getter_AddRefs(uploadStream));
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  RefPtr<InternalRequest> internalRequest = new InternalRequest(
-      spec, fragment, method, internalHeaders.forget(), cacheMode, requestMode,
-      requestRedirect, requestCredentials, referrer, referrerPolicy,
-      contentPolicyType, integrity);
-  internalRequest->SetBody(uploadStream, uploadStreamContentLength);
-  internalRequest->SetCreatedByFetchEvent();
-
-  nsAutoCString alternativeDataType;
-  if (cacheInfoChannel &&
-      !cacheInfoChannel->PreferredAlternativeDataTypes().IsEmpty()) {
-    // TODO: the internal request probably needs all the preferred types.
-    alternativeDataType.Assign(
-        cacheInfoChannel->PreferredAlternativeDataTypes()[0].type());
-    internalRequest->SetPreferredAlternativeDataType(alternativeDataType);
-  }
-
-  PBackgroundChild* bgChild = BackgroundChild::GetForCurrentThread();
-
-  if (NS_WARN_IF(!bgChild)) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
-  }
-
-  internalRequest->ToIPC(aOutRequest, bgChild, aAutoStream);
-
-  return NS_OK;
-}
-
-}  // anonymous namespace
-
 ServiceWorkerPrivateImpl::RAIIActorPtrHolder::RAIIActorPtrHolder(
     already_AddRefed<RemoteWorkerControllerChild> aActor)
     : mActor(aActor) {
   AssertIsOnMainThread();
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mActor->Manager());
 }
 
@@ -714,35 +543,31 @@ nsresult ServiceWorkerPrivateImpl::Pendi
   return mOwner->SendPushEventInternal(std::move(mRegistration),
                                        std::move(mArgs));
 }
 
 ServiceWorkerPrivateImpl::PendingFetchEvent::PendingFetchEvent(
     ServiceWorkerPrivateImpl* aOwner,
     RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
     ServiceWorkerFetchEventOpArgs&& aArgs,
-    nsCOMPtr<nsIInterceptedChannel>&& aChannel,
-    UniquePtr<AutoIPCStream>&& aAutoStream)
+    nsCOMPtr<nsIInterceptedChannel>&& aChannel)
     : PendingFunctionalEvent(aOwner, std::move(aRegistration)),
       mArgs(std::move(aArgs)),
-      mChannel(std::move(aChannel)),
-      mAutoStream(std::move(aAutoStream)) {
+      mChannel(std::move(aChannel)) {
   AssertIsOnMainThread();
   MOZ_ASSERT(mChannel);
-  MOZ_ASSERT(mAutoStream);
 }
 
 nsresult ServiceWorkerPrivateImpl::PendingFetchEvent::Send() {
   AssertIsOnMainThread();
   MOZ_ASSERT(mOwner->mOuter);
   MOZ_ASSERT(mOwner->mOuter->mInfo);
 
   return mOwner->SendFetchEventInternal(std::move(mRegistration),
-                                        std::move(mArgs), std::move(mChannel),
-                                        std::move(mAutoStream));
+                                        std::move(mArgs), std::move(mChannel));
 }
 
 ServiceWorkerPrivateImpl::PendingFetchEvent::~PendingFetchEvent() {
   AssertIsOnMainThread();
 
   if (NS_WARN_IF(mChannel)) {
     mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
   }
@@ -764,55 +589,46 @@ nsresult ServiceWorkerPrivateImpl::SendF
 
   nsCOMPtr<nsIChannel> channel;
   nsresult rv = aChannel->GetChannel(getter_AddRefs(channel));
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  IPCInternalRequest internalRequest;
-  UniquePtr<AutoIPCStream> autoStream = MakeUnique<AutoIPCStream>();
-  rv = GetIPCInternalRequest(aChannel, &internalRequest, autoStream);
-
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   scopeExit.release();
 
   MOZ_ASSERT(mOuter->mInfo);
 
+  // FetchEventOpChild will fill in the IPCInternalRequest.
   ServiceWorkerFetchEventOpArgs args(
-      mOuter->mInfo->ScriptSpec(), internalRequest, nsString(aClientId),
+      mOuter->mInfo->ScriptSpec(), IPCInternalRequest(), nsString(aClientId),
       nsString(aResultingClientId), aIsReload,
       nsContentUtils::IsNonSubresourceRequest(channel));
 
   if (mOuter->mInfo->State() == ServiceWorkerState::Activating) {
     UniquePtr<PendingFunctionalEvent> pendingEvent =
         MakeUnique<PendingFetchEvent>(this, std::move(aRegistration),
-                                      std::move(args), std::move(aChannel),
-                                      std::move(autoStream));
+                                      std::move(args), std::move(aChannel));
 
     mPendingFunctionalEvents.AppendElement(std::move(pendingEvent));
 
     return NS_OK;
   }
 
   MOZ_ASSERT(mOuter->mInfo->State() == ServiceWorkerState::Activated);
 
   return SendFetchEventInternal(std::move(aRegistration), std::move(args),
-                                std::move(aChannel), std::move(autoStream));
+                                std::move(aChannel));
 }
 
 nsresult ServiceWorkerPrivateImpl::SendFetchEventInternal(
     RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
     ServiceWorkerFetchEventOpArgs&& aArgs,
-    nsCOMPtr<nsIInterceptedChannel>&& aChannel,
-    UniquePtr<AutoIPCStream>&& aAutoStream) {
+    nsCOMPtr<nsIInterceptedChannel>&& aChannel) {
   AssertIsOnMainThread();
   MOZ_ASSERT(mOuter);
 
   auto scopeExit = MakeScopeExit([&] { Shutdown(); });
 
   if (NS_WARN_IF(!mOuter->mInfo)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
@@ -824,27 +640,25 @@ nsresult ServiceWorkerPrivateImpl::SendF
   }
 
   scopeExit.release();
 
   MOZ_ASSERT(mControllerChild);
 
   RefPtr<RAIIActorPtrHolder> holder = mControllerChild;
 
-  FetchEventOpChild::Create(mControllerChild->get(), std::move(aArgs),
-                            std::move(aChannel), std::move(aRegistration),
-                            mOuter->CreateEventKeepAliveToken())
+  FetchEventOpChild::SendFetchEvent(
+      mControllerChild->get(), std::move(aArgs), std::move(aChannel),
+      std::move(aRegistration), mOuter->CreateEventKeepAliveToken())
       ->Then(GetCurrentThreadSerialEventTarget(), __func__,
              [holder = std::move(holder)](
                  const GenericPromise::ResolveOrRejectValue& aResult) {
                Unused << NS_WARN_IF(aResult.IsReject());
              });
 
-  aAutoStream->TakeOptionalValue();
-
   return NS_OK;
 }
 
 void ServiceWorkerPrivateImpl::TerminateWorker() {
   AssertIsOnMainThread();
   MOZ_ASSERT(mOuter);
 
   mOuter->mIdleWorkerTimer->Cancel();
--- a/dom/serviceworkers/ServiceWorkerPrivateImpl.h
+++ b/dom/serviceworkers/ServiceWorkerPrivateImpl.h
@@ -24,22 +24,16 @@
 
 class nsIInterceptedChannel;
 
 namespace mozilla {
 
 template <typename T>
 class Maybe;
 
-namespace ipc {
-
-class AutoIPCStream;
-
-}  // namespace ipc
-
 namespace dom {
 
 class ClientInfoAndState;
 class LifeCycleEventCallback;
 class RemoteWorkerControllerChild;
 class ServiceWorkerCloneData;
 class ServiceWorkerRegistrationInfo;
 
@@ -121,18 +115,17 @@ class ServiceWorkerPrivateImpl final : p
 
   nsresult SendPushEventInternal(
       RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
       ServiceWorkerPushEventOpArgs&& aArgs);
 
   nsresult SendFetchEventInternal(
       RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
       ServiceWorkerFetchEventOpArgs&& aArgs,
-      nsCOMPtr<nsIInterceptedChannel>&& aChannel,
-      UniquePtr<mozilla::ipc::AutoIPCStream>&& aAutoStream);
+      nsCOMPtr<nsIInterceptedChannel>&& aChannel);
 
   void Shutdown();
 
   RefPtr<GenericNonExclusivePromise> ShutdownInternal();
 
   nsresult ExecServiceWorkerOp(
       ServiceWorkerOpArgs&& aArgs,
       std::function<void(ServiceWorkerOpResult&&)>&& aSuccessCallback,
@@ -165,27 +158,25 @@ class ServiceWorkerPrivateImpl final : p
     ServiceWorkerPushEventOpArgs mArgs;
   };
 
   class PendingFetchEvent final : public PendingFunctionalEvent {
    public:
     PendingFetchEvent(ServiceWorkerPrivateImpl* aOwner,
                       RefPtr<ServiceWorkerRegistrationInfo>&& aRegistration,
                       ServiceWorkerFetchEventOpArgs&& aArgs,
-                      nsCOMPtr<nsIInterceptedChannel>&& aChannel,
-                      UniquePtr<AutoIPCStream>&& aAutoStream);
+                      nsCOMPtr<nsIInterceptedChannel>&& aChannel);
 
     nsresult Send() override;
 
     ~PendingFetchEvent();
 
    private:
     ServiceWorkerFetchEventOpArgs mArgs;
     nsCOMPtr<nsIInterceptedChannel> mChannel;
-    UniquePtr<mozilla::ipc::AutoIPCStream> mAutoStream;
   };
 
   nsTArray<UniquePtr<PendingFunctionalEvent>> mPendingFunctionalEvents;
 
   /**
    * It's possible that there are still in-progress operations when a
    * a termination operation is issued. In this case, it's important to keep
    * the RemoteWorkerControllerChild actor alive until all pending operations