Backed out 6 changesets (bug 1416879) for bc permafailures on windows on browser_multie10s_update.js r=backout a=backout
authorBrindusan Cristian <cbrindusan@mozilla.com>
Sun, 07 Jan 2018 11:55:44 +0200
changeset 449904 ed0571d18d1f713a445b7982e85f456d0d265417
parent 449903 5e7188cf8ed415d8e6b6a9a02272a97b1e52b360
child 449905 43c5e818bbce767105b839e4d6a512ccc058ae5b
child 449908 27cfea3e33fa88cad23be821396b5d83904ca747
child 449923 09fd5222143090f90058efc287857c4a553fd3c2
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout, backout
bugs1416879
milestone59.0a1
backs out840a6e04bcea7d87e362adf14a37b7c17e20f043
994dc643a2ab62f03fef780a58971b476a4b6f4a
8e4fd74e7f5e69df7363bdb560f79dde347ce082
5453b8a58f0c2c28dc7c407c531c266972bff423
d156f6b687e1cd8717bf813ab1b944e87b67ed5d
714d3942fb10a96e60e14c475e24e640b9ddd8cc
first release with
nightly linux32
ed0571d18d1f / 59.0a1 / 20180107100322 / files
nightly linux64
ed0571d18d1f / 59.0a1 / 20180107100322 / files
nightly mac
ed0571d18d1f / 59.0a1 / 20180107100322 / files
nightly win32
ed0571d18d1f / 59.0a1 / 20180107100322 / files
nightly win64
ed0571d18d1f / 59.0a1 / 20180107100322 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 1416879) for bc permafailures on windows on browser_multie10s_update.js r=backout a=backout Backed out changeset 840a6e04bcea (bug 1416879) Backed out changeset 994dc643a2ab (bug 1416879) Backed out changeset 8e4fd74e7f5e (bug 1416879) Backed out changeset 5453b8a58f0c (bug 1416879) Backed out changeset d156f6b687e1 (bug 1416879) Backed out changeset 714d3942fb10 (bug 1416879)
dom/fetch/FetchDriver.cpp
dom/fetch/FetchStreamReader.cpp
dom/fetch/FetchStreamReader.h
dom/workers/test/serviceworkers/browser.ini
dom/workers/test/serviceworkers/browser_download_canceled.js
dom/workers/test/serviceworkers/download_canceled/page_download_canceled.html
dom/workers/test/serviceworkers/download_canceled/server-stream-download.sjs
dom/workers/test/serviceworkers/download_canceled/sw_download_canceled.js
netwerk/base/ADivertableParentChannel.h
netwerk/protocol/ftp/FTPChannelParent.cpp
netwerk/protocol/ftp/FTPChannelParent.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/InterceptedHttpChannel.cpp
netwerk/protocol/http/InterceptedHttpChannel.h
netwerk/protocol/http/PHttpChannel.ipdl
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -1082,47 +1082,35 @@ FetchDriver::OnDataAvailable(nsIRequest*
           mMainThreadEventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
   }
 
-  // Needs to be initialized to 0 because in some cases nsStringInputStream may
-  // not write to aRead.
-  uint32_t aRead = 0;
+  uint32_t aRead;
   MOZ_ASSERT(mResponse);
   MOZ_ASSERT(mPipeOutputStream);
 
   // From "Main Fetch" step 19: SRI-part2.
   // Note: Avoid checking the hidden opaque body.
-  nsresult rv;
   if (mResponse->Type() != ResponseType::Opaque &&
       ShouldCheckSRI(mRequest, mResponse)) {
     MOZ_ASSERT(mSRIDataVerifier);
 
     SRIVerifierAndOutputHolder holder(mSRIDataVerifier, mPipeOutputStream);
-    rv = aInputStream->ReadSegments(CopySegmentToStreamAndSRI,
-                                    &holder, aCount, &aRead);
-  } else {
-    rv = aInputStream->ReadSegments(NS_CopySegmentToStream,
-                                    mPipeOutputStream,
-                                    aCount, &aRead);
+    nsresult rv = aInputStream->ReadSegments(CopySegmentToStreamAndSRI,
+                                             &holder, aCount, &aRead);
+    return rv;
   }
 
-  // If no data was read, it's possible the output stream is closed but the
-  // ReadSegments call followed its contract of returning NS_OK despite write
-  // errors.  Unfortunately, nsIOutputStream has an ill-conceived contract when
-  // taken together with ReadSegments' contract, because the pipe will just
-  // NS_OK if we try and invoke its Write* functions ourselves with a 0 count.
-  // So we must just assume the pipe is broken.
-  if (aRead == 0 && aCount != 0) {
-    return NS_BASE_STREAM_CLOSED;
-  }
+  nsresult rv = aInputStream->ReadSegments(NS_CopySegmentToStream,
+                                           mPipeOutputStream,
+                                           aCount, &aRead);
   return rv;
 }
 
 NS_IMETHODIMP
 FetchDriver::OnStopRequest(nsIRequest* aRequest,
                            nsISupports* aContext,
                            nsresult aStatusCode)
 {
--- a/dom/fetch/FetchStreamReader.cpp
+++ b/dom/fetch/FetchStreamReader.cpp
@@ -29,20 +29,17 @@ public:
     , mReader(aReader)
     , mWasNotified(false)
   {}
 
   bool Notify(Status aStatus) override
   {
     if (!mWasNotified) {
       mWasNotified = true;
-      // The WorkerPrivate does have a context available, and we could pass it
-      // here to trigger cancellation of the reader, but the author of this
-      // comment chickened out.
-      mReader->CloseAndRelease(nullptr, NS_ERROR_DOM_INVALID_STATE_ERR);
+      mReader->CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR);
     }
 
     return true;
   }
 
 private:
   RefPtr<FetchStreamReader> mReader;
   bool mWasNotified;
@@ -122,53 +119,31 @@ FetchStreamReader::FetchStreamReader(nsI
   , mBufferOffset(0)
   , mStreamClosed(false)
 {
   MOZ_ASSERT(aGlobal);
 }
 
 FetchStreamReader::~FetchStreamReader()
 {
-  CloseAndRelease(nullptr, NS_BASE_STREAM_CLOSED);
+  CloseAndRelease(NS_BASE_STREAM_CLOSED);
 }
 
-// If a context is provided, an attempt will be made to cancel the reader.  The
-// only situation where we don't expect to have a context is when closure is
-// being triggered from the destructor or the WorkerHolder is notifying.  If
-// we're at the destructor, it's far too late to cancel anything.  And if the
-// WorkerHolder is being notified, the global is going away, so there's also
-// no need to do further JS work.
 void
-FetchStreamReader::CloseAndRelease(JSContext* aCx, nsresult aStatus)
+FetchStreamReader::CloseAndRelease(nsresult aStatus)
 {
   NS_ASSERT_OWNINGTHREAD(FetchStreamReader);
 
   if (mStreamClosed) {
     // Already closed.
     return;
   }
 
   RefPtr<FetchStreamReader> kungFuDeathGrip = this;
 
-  if (aCx) {
-    MOZ_ASSERT(mReader);
-
-    RefPtr<DOMException> error = DOMException::Create(aStatus);
-
-    JS::Rooted<JS::Value> errorValue(aCx);
-    if (ToJSValue(aCx, error, &errorValue)) {
-      JS::Rooted<JSObject*> reader(aCx, mReader);
-      // It's currently safe to cancel an already closed reader because, per the
-      // comments in ReadableStream::cancel() conveying the spec, step 2 of
-      // 3.4.3 that specified ReadableStreamCancel is: If stream.[[state]] is
-      // "closed", return a new promise resolved with undefined.
-      JS::ReadableStreamReaderCancel(aCx, reader, errorValue);
-    }
-  }
-
   mStreamClosed = true;
 
   mGlobal = nullptr;
 
   mPipeOut->CloseWithStatus(aStatus);
   mPipeOut = nullptr;
 
   mWorkerHolder = nullptr;
@@ -186,17 +161,17 @@ FetchStreamReader::StartConsuming(JSCont
   MOZ_DIAGNOSTIC_ASSERT(!mReader);
   MOZ_DIAGNOSTIC_ASSERT(aStream);
 
   JS::Rooted<JSObject*> reader(aCx,
                                JS::ReadableStreamGetReader(aCx, aStream,
                                                            JS::ReadableStreamReaderMode::Default));
   if (!reader) {
     aRv.StealExceptionFromJSContext(aCx);
-    CloseAndRelease(aCx, NS_ERROR_DOM_INVALID_STATE_ERR);
+    CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   mReader = reader;
   aReader.set(reader);
 
   aRv = mPipeOut->AsyncWait(this, 0, 0, mOwningEventTarget);
   if (NS_WARN_IF(aRv.Failed())) {
@@ -226,24 +201,24 @@ FetchStreamReader::OnOutputStreamReady(n
   AutoEntryScript aes(mGlobal, "ReadableStreamReader.read", !mWorkerHolder);
 
   JS::Rooted<JSObject*> reader(aes.cx(), mReader);
   JS::Rooted<JSObject*> promise(aes.cx(),
                                 JS::ReadableStreamDefaultReaderRead(aes.cx(),
                                                                     reader));
   if (NS_WARN_IF(!promise)) {
     // Let's close the stream.
-    CloseAndRelease(aes.cx(), NS_ERROR_DOM_INVALID_STATE_ERR);
+    CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR);
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<Promise> domPromise = Promise::CreateFromExisting(mGlobal, promise);
   if (NS_WARN_IF(!domPromise)) {
     // Let's close the stream.
-    CloseAndRelease(aes.cx(), NS_ERROR_DOM_INVALID_STATE_ERR);
+    CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR);
     return NS_ERROR_FAILURE;
   }
 
   // Let's wait.
   domPromise->AppendNativeHandler(this);
   return NS_OK;
 }
 
@@ -260,31 +235,31 @@ FetchStreamReader::ResolvedCallback(JSCo
 
   // We don't want to play with JS api, let's WebIDL bindings doing it for us.
   // FetchReadableStreamReadDataDone is a dictionary with just a boolean, if the
   // parsing succeeded, we can proceed with the parsing of the "value", which it
   // must be a Uint8Array.
   FetchReadableStreamReadDataDone valueDone;
   if (!valueDone.Init(aCx, aValue)) {
     JS_ClearPendingException(aCx);
-    CloseAndRelease(aCx, NS_ERROR_DOM_INVALID_STATE_ERR);
+    CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   if (valueDone.mDone) {
     // Stream is completed.
-    CloseAndRelease(aCx, NS_BASE_STREAM_CLOSED);
+    CloseAndRelease(NS_BASE_STREAM_CLOSED);
     return;
   }
 
   UniquePtr<FetchReadableStreamReadDataArray> value(
     new FetchReadableStreamReadDataArray);
   if (!value->Init(aCx, aValue) || !value->mValue.WasPassed()) {
     JS_ClearPendingException(aCx);
-    CloseAndRelease(aCx, NS_ERROR_DOM_INVALID_STATE_ERR);
+    CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   Uint8Array& array = value->mValue.Value();
   array.ComputeLengthAndData();
   uint32_t len = array.Length();
 
   if (len == 0) {
@@ -294,22 +269,17 @@ FetchStreamReader::ResolvedCallback(JSCo
   }
 
   MOZ_DIAGNOSTIC_ASSERT(!mBuffer);
   mBuffer = Move(value);
 
   mBufferOffset = 0;
   mBufferRemaining = len;
 
-  nsresult rv = WriteBuffer();
-  if (NS_FAILED(rv)) {
-    // DOMException only understands errors from domerr.msg, so we normalize to
-    // identifying an abort if the write fails.
-    CloseAndRelease(aCx, NS_ERROR_DOM_ABORT_ERR);
-  }
+  WriteBuffer();
 }
 
 nsresult
 FetchStreamReader::WriteBuffer()
 {
   MOZ_ASSERT(mBuffer);
   MOZ_ASSERT(mBuffer->mValue.WasPassed());
 
@@ -321,43 +291,45 @@ FetchStreamReader::WriteBuffer()
     nsresult rv =
       mPipeOut->Write(data + mBufferOffset, mBufferRemaining, &written);
 
     if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
       break;
     }
 
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      CloseAndRelease(rv);
       return rv;
     }
 
     MOZ_ASSERT(written <= mBufferRemaining);
     mBufferRemaining -= written;
     mBufferOffset += written;
 
     if (mBufferRemaining == 0) {
       mBuffer = nullptr;
       break;
     }
   }
 
   nsresult rv = mPipeOut->AsyncWait(this, 0, 0, mOwningEventTarget);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    CloseAndRelease(rv);
     return rv;
   }
 
   return NS_OK;
 }
 
 void
 FetchStreamReader::RejectedCallback(JSContext* aCx,
                                     JS::Handle<JS::Value> aValue)
 {
   ReportErrorToConsole(aCx, aValue);
-  CloseAndRelease(aCx, NS_ERROR_FAILURE);
+  CloseAndRelease(NS_ERROR_FAILURE);
 }
 
 void
 FetchStreamReader::ReportErrorToConsole(JSContext* aCx,
                                         JS::Handle<JS::Value> aValue)
 {
   nsCString sourceSpec;
   uint32_t line = 0;
--- a/dom/fetch/FetchStreamReader.h
+++ b/dom/fetch/FetchStreamReader.h
@@ -35,22 +35,18 @@ public:
          nsIInputStream** aInputStream);
 
   void
   ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
 
   void
   RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
 
-  // Idempotently close the output stream and null out all state. If aCx is
-  // provided, the reader will also be canceled.  aStatus must be a DOM error
-  // as understood by DOMException because it will be provided as the
-  // cancellation reason.
   void
-  CloseAndRelease(JSContext* aCx, nsresult aStatus);
+  CloseAndRelease(nsresult aStatus);
 
   void
   StartConsuming(JSContext* aCx,
                  JS::HandleObject aStream,
                  JS::MutableHandle<JSObject*> aReader,
                  ErrorResult& aRv);
 
 private:
--- a/dom/workers/test/serviceworkers/browser.ini
+++ b/dom/workers/test/serviceworkers/browser.ini
@@ -1,25 +1,20 @@
 [DEFAULT]
 support-files =
   browser_base_force_refresh.html
   browser_cached_force_refresh.html
   download/window.html
   download/worker.js
-  download_canceled/page_download_canceled.html
-  download_canceled/server-stream-download.sjs
-  download_canceled/sw_download_canceled.js
   fetch.js
   file_multie10s_update.html
   file_userContextId_openWindow.js
   force_refresh_browser_worker.js
   empty.html
   server_multie10s_update.sjs
-  utils.js
 
 [browser_devtools_serviceworker_interception.js]
 [browser_force_refresh.js]
 [browser_download.js]
-[browser_download_canceled.js]
 [browser_multie10s_update.js]
 skip-if = !e10s || os != "win" # Bug 1404914
 [browser_userContextId_openWindow.js]
 skip-if = !e10s
deleted file mode 100644
--- a/dom/workers/test/serviceworkers/browser_download_canceled.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/*
- * Test cancellation of a download in order to test edge-cases related to
- * channel diversion.  Channel diversion occurs in cases of file (and PSM cert)
- * downloads where we realize in the child that we really want to consume the
- * channel data in the parent.  For data "sourced" by the parent, like network
- * data, data streaming to the child is suspended and the parent waits for the
- * child to send back the data it already received, then the channel is resumed.
- * For data generated by the child, such as (the current, to be mooted by
- * parent-intercept) child-side intercept, the data (currently) stream is
- * continually pumped up to the parent.
- *
- * In particular, we want to reproduce the circumstances of Bug 1418795 where
- * the child-side input-stream pump attempts to send data to the parent process
- * but the parent has canceled the channel and so the IPC Actor has been torn
- * down.  Diversion begins once the nsURILoader receives the OnStartRequest
- * notification with the headers, so there are two ways to produce
- */
-
-Cu.import('resource://gre/modules/Services.jsm');
-const { Downloads } = Cu.import("resource://gre/modules/Downloads.jsm", {});
-
-/**
- * Clear the downloads list so other tests don't see our byproducts.
- */
-async function clearDownloads() {
-  const downloads = await Downloads.getList(Downloads.ALL);
-  downloads.removeFinished();
-}
-
-/**
- * Returns a Promise that will be resolved once the download dialog shows up and
- * we have clicked the given button.
- *
- * Derived from browser/components/downloads/test/browser/head.js's
- * self-contained promiseAlertDialogOpen helper, but modified to work on the
- * download dialog instead of commonDialog.xul.
- */
-function promiseClickDownloadDialogButton(buttonAction) {
-  return new Promise(resolve => {
-    Services.ww.registerNotification(function onOpen(win, topic, data) {
-      if (topic === "domwindowopened" && win instanceof Ci.nsIDOMWindow) {
-        // The test listens for the "load" event which guarantees that the alert
-        // class has already been added (it is added when "DOMContentLoaded" is
-        // fired).
-        win.addEventListener("load", function() {
-          info(`found window of type: ${win.document.documentURI}`);
-          if (win.document.documentURI ===
-                "chrome://mozapps/content/downloads/unknownContentType.xul") {
-            Services.ww.unregisterNotification(onOpen);
-
-            // nsHelperAppDlg.js currently uses an eval-based setTimeout(0) to
-            // invoke its postShowCallback that results in a misleading error to
-            // the console if we close the dialog before it gets a chance to
-            // run.  Just a setTimeout is not sufficient because it appears we
-            // get our "load" listener before the document's, so we use
-            // executeSoon to defer until after its load handler runs, then
-            // use setTimeout(0) to end up after its eval.
-            executeSoon(function() {
-              setTimeout(function() {
-                const button = win.document.documentElement.getButton(buttonAction);
-                button.disabled = false;
-                info(`clicking ${buttonAction} button`);
-                button.click();
-                resolve();
-              }, 0);
-            });
-          }
-        }, {once: true});
-      }
-    });
-  });
-}
-
-async function performCanceledDownload(tab, path) {
-  // Start waiting for the download dialog before triggering the download.
-  info("watching for download popup");
-  const cancelDownload = promiseClickDownloadDialogButton("cancel");
-
-  // Trigger the download.
-  info(`triggering download of "${path}"`);
-  await ContentTask.spawn(
-    tab.linkedBrowser,
-    path,
-    function(path) {
-      // Put a Promise in place that we can wait on for stream closure.
-      content.wrappedJSObject.trackStreamClosure(path);
-      // Create the link and trigger the download.
-      const link = content.document.createElement('a');
-      link.href = path;
-      link.download = path;
-      content.document.body.appendChild(link);
-      link.click();
-    });
-
-  // Wait for the cancelation to have been triggered.
-  info("waiting for download popup");
-  await cancelDownload;
-  ok(true, "canceled download");
-
-  // Wait for confirmation that the stream stopped.
-  info(`wait for the ${path} stream to close.`);
-  const why = await ContentTask.spawn(
-    tab.linkedBrowser,
-    path,
-    function(path) {
-      return content.wrappedJSObject.streamClosed[path].promise;
-    });
-  is(why.why, "canceled", "Ensure the stream canceled instead of timing out.");
-  // Note that for the "sw-stream-download" case, we end up with a bogus
-  // reason of "'close' may only be called on a stream in the 'readable' state."
-  // Since we aren't actually invoking close(), I'm assuming this is an
-  // implementation bug that will be corrected in the web platform tests.
-  info(`Cancellation reason: ${why.message} after ${why.ticks} ticks`);
-}
-
-const gTestRoot = getRootDirectory(gTestPath)
-  .replace("chrome://mochitests/content/", "http://mochi.test:8888/");
-
-
-const PAGE_URL = `${gTestRoot}download_canceled/page_download_canceled.html`;
-
-add_task(async function interruptedDownloads() {
-  await SpecialPowers.pushPrefEnv({'set': [
-    ['dom.serviceWorkers.enabled', true],
-    ['dom.serviceWorkers.exemptFromPerDomainMax', true],
-    ['dom.serviceWorkers.testing.enabled', true],
-    ["javascript.options.streams", true],
-    ["dom.streams.enabled", true],
-  ]});
-
-  // Open the tab
-  const tab = await BrowserTestUtils.openNewForegroundTab({
-    gBrowser,
-    opening: PAGE_URL
-  });
-
-  // Wait for it to become controlled.  Check that it was a promise that
-  // resolved as expected rather than undefined by checking the return value.
-  const controlled = await ContentTask.spawn(
-    tab.linkedBrowser,
-    null,
-    function() {
-      // This is a promise set up by the page during load, and we are post-load.
-      return content.wrappedJSObject.controlled;
-    });
-  is(controlled, "controlled", "page became controlled");
-
-  // Download a pass-through fetch stream.
-  await performCanceledDownload(tab, "sw-passthrough-download");
-
-  // Download a SW-generated stream
-  await performCanceledDownload(tab, "sw-stream-download");
-
-  // Cleanup
-  await ContentTask.spawn(
-    tab.linkedBrowser,
-    null,
-    function() {
-      return content.wrappedJSObject.registration.unregister();
-    });
-  await BrowserTestUtils.removeTab(tab);
-  await clearDownloads();
-});
\ No newline at end of file
deleted file mode 100644
--- a/dom/workers/test/serviceworkers/download_canceled/page_download_canceled.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!--
-  Any copyright is dedicated to the Public Domain.
-  http://creativecommons.org/publicdomain/zero/1.0/
--->
-<!DOCTYPE HTML>
-<html>
-<head>
-  <meta charset="utf-8">
-</head>
-<body>
-
-<script src="../utils.js"></script>
-<script type="text/javascript">
-function wait_until_controlled() {
-  return new Promise(function(resolve) {
-    if (navigator.serviceWorker.controller) {
-      return resolve('controlled');
-    }
-    navigator.serviceWorker.addEventListener('controllerchange', function onController() {
-      if (navigator.serviceWorker.controller) {
-        navigator.serviceWorker.removeEventListener('controllerchange', onController);
-        return resolve('controlled');
-      }
-    });
-  });
-}
-addEventListener('load', async function(event) {
-  window.controlled = wait_until_controlled();
-  window.registration =
-    await navigator.serviceWorker.register('sw_download_canceled.js');
-  let sw = registration.installing || registration.waiting ||
-           registration.active;
-  await waitForState(sw, 'activated');
-  sw.postMessage('claim');
-});
-
-// Place to hold promises for stream closures reported by the SW.
-window.streamClosed = {};
-
-// The ServiceWorker will postMessage to this BroadcastChannel when the streams
-// are closed.  (Alternately, the SW could have used the clients API to post at
-// us, but the mechanism by which that operates would be different when this
-// test is uplifted, and it's desirable to avoid timing changes.)
-//
-// The browser test will use this promise to wait on stream shutdown.
-window.swStreamChannel = new BroadcastChannel("stream-closed");
-function trackStreamClosure(path) {
-  let resolve;
-  const promise = new Promise(r => { resolve = r });
-  window.streamClosed[path] = { promise, resolve };
-}
-window.swStreamChannel.onmessage = ({ data }) => {
-  window.streamClosed[data.what].resolve(data);
-};
-</script>
-
-</body>
-</html>
deleted file mode 100644
--- a/dom/workers/test/serviceworkers/download_canceled/server-stream-download.sjs
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/Timer.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-
-// stolen from file_blocked_script.sjs
-function setGlobalState(data, key)
-{
-  x = { data: data, QueryInterface: function(iid) { return this } };
-  x.wrappedJSObject = x;
-  setObjectState(key, x);
-}
-
-function getGlobalState(key)
-{
-  var data;
-  getObjectState(key, function(x) {
-    data = x && x.wrappedJSObject.data;
-  });
-  return data;
-}
-
-/*
- * We want to let the sw_download_canceled.js service worker know when the
- * stream was canceled.  To this end, we let it issue a monitor request which we
- * fulfill when the stream has been canceled.  In order to coordinate between
- * multiple requests, we use the getObjectState/setObjectState mechanism that
- * httpd.js exposes to let data be shared and/or persist between requests.  We
- * handle both possible orderings of the requests because we currently don't
- * try and impose an ordering between the two requests as issued by the SW, and
- * file_blocked_script.sjs encourages us to do this, but we probably could order
- * them.
- */
-const MONITOR_KEY = "stream-monitor";
-function completeMonitorResponse(response, data) {
-  response.write(JSON.stringify(data));
-  response.finish();
-}
-function handleMonitorRequest(request, response) {
-  response.setHeader("Content-Type", "application/json");
-  response.setStatusLine(request.httpVersion, 200, "Found");
-
-  response.processAsync();
-  // Necessary to cause the headers to be flushed; that or touching the
-  // bodyOutputStream getter.
-  response.write("");
-  dump("server-stream-download.js: monitor headers issued\n");
-
-  const alreadyCompleted = getGlobalState(MONITOR_KEY);
-  if (alreadyCompleted) {
-    completeMonitorResponse(response, alreadyCompleted);
-    setGlobalState(null, MONITOR_KEY);
-  } else {
-    setGlobalState(response, MONITOR_KEY);
-  }
-}
-
-const MAX_TICK_COUNT = 3000;
-const TICK_INTERVAL = 2;
-function handleStreamRequest(request, response) {
-  const name = "server-stream-download";
-
-  // Create some payload to send.
-  let strChunk =
-    'Static routes are the future of ServiceWorkers! So say we all!\n';
-  while (strChunk.length < 1024) {
-    strChunk += strChunk;
-  }
-
-  response.setHeader("Content-Disposition", `attachment; filename="${name}"`);
-  response.setHeader("Content-Type", `application/octet-stream; name="${name}"`);
-  response.setHeader("Content-Length", `${strChunk.length * MAX_TICK_COUNT}`);
-  response.setStatusLine(request.httpVersion, 200, "Found");
-
-  response.processAsync();
-  response.write(strChunk);
-  dump("server-stream-download.js: stream headers + first payload issued\n");
-
-  let count = 0;
-  let intervalId;
-  function closeStream(why, message) {
-    dump("server-stream-download.js: closing stream: " + why + "\n");
-    clearInterval(intervalId);
-    response.finish();
-
-    const data = { why, message };
-    const monitorResponse = getGlobalState(MONITOR_KEY);
-    if (monitorResponse) {
-      completeMonitorResponse(monitorResponse, data);
-      setGlobalState(null, MONITOR_KEY);
-    } else {
-      setGlobalState(data, MONITOR_KEY);
-    }
-  }
-  function tick() {
-    try {
-      // bound worst-case behavior.
-      if (count++ > MAX_TICK_COUNT) {
-        closeStream("timeout", "timeout");
-        return;
-      }
-      response.write(strChunk);
-    } catch(e) {
-      closeStream("canceled", e.message);
-    }
-  }
-  intervalId = setInterval(tick, TICK_INTERVAL);
-}
-
-Components.utils.importGlobalProperties(["URLSearchParams"]);
-function handleRequest(request, response) {
-  dump("server-stream-download.js: processing request for " + request.path +
-       "?" + request.queryString + "\n");
-  const query = new URLSearchParams(request.queryString);
-  if (query.has("monitor")) {
-    handleMonitorRequest(request, response);
-  } else {
-    handleStreamRequest(request, response);
-  }
-}
\ No newline at end of file
deleted file mode 100644
--- a/dom/workers/test/serviceworkers/download_canceled/sw_download_canceled.js
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// This file is derived from :bkelly's https://glitch.com/edit/#!/html-sw-stream
-
-addEventListener("install", evt => {
-  evt.waitUntil(self.skipWaiting());
-});
-
-// Create a BroadcastChannel to notify when we have closed our streams.
-const channel = new BroadcastChannel("stream-closed");
-
-const MAX_TICK_COUNT = 3000;
-const TICK_INTERVAL = 4;
-/**
- * Generate a continuous stream of data at a sufficiently high frequency that a
- * there"s a good chance of racing channel cancellation.
- */
-function handleStream(evt, filename) {
-  // Create some payload to send.
-  const encoder = new TextEncoder();
-  let strChunk =
-    "Static routes are the future of ServiceWorkers! So say we all!\n";
-  while (strChunk.length < 1024) {
-    strChunk += strChunk;
-  }
-  const dataChunk = encoder.encode(strChunk);
-
-  evt.waitUntil(new Promise(resolve => {
-    let body = new ReadableStream({
-      start: controller => {
-        const closeStream = (why) => {
-          console.log("closing stream: " + JSON.stringify(why) + "\n");
-          clearInterval(intervalId);
-          resolve();
-          // In event of error, the controller will automatically have closed.
-          if (why.why != "canceled") {
-            try {
-              controller.close();
-            } catch(ex) {
-              // If we thought we should cancel but experienced a problem,
-              // that's a different kind of failure and we need to report it.
-              // (If we didn't catch the exception here, we'd end up erroneously
-              // in the tick() method's canceled handler.)
-              channel.postMessage({
-                what: filename,
-                why: "close-failure",
-                message: ex.message,
-                ticks: why.ticks
-              });
-              return;
-            }
-          }
-          // Post prior to performing any attempt to close...
-          channel.postMessage(why);
-        };
-
-        controller.enqueue(dataChunk);
-        let count = 0;
-        let intervalId;
-        function tick() {
-          try {
-            // bound worst-case behavior.
-            if (count++ > MAX_TICK_COUNT) {
-              closeStream({
-                what: filename, why: "timeout", message: "timeout", ticks: count
-              });
-              return;
-            }
-            controller.enqueue(dataChunk);
-          } catch(e) {
-            closeStream({
-              what: filename, why: "canceled", message: e.message, ticks: count
-            });
-          }
-        }
-        // Alternately, streams' pull mechanism could be used here, but this
-        // test doesn't so much want to saturate the stream as to make sure the
-        // data is at least flowing a little bit.  (Also, the author had some
-        // concern about slowing down the test by overwhelming the event loop
-        // and concern that we might not have sufficent back-pressure plumbed
-        // through and an infinite pipe might make bad things happen.)
-        intervalId = setInterval(tick, TICK_INTERVAL);
-        tick();
-      },
-    });
-    evt.respondWith(new Response(body, {
-      headers: {
-        "Content-Disposition": `attachment; filename="${filename}"`,
-        "Content-Type": "application/octet-stream"
-      }
-    }));
-  }));
-}
-
-/**
- * Use an .sjs to generate a similar stream of data to the above, passing the
- * response through directly.  Because we're handing off the response but also
- * want to be able to report when cancellation occurs, we create a second,
- * overlapping long-poll style fetch that will not finish resolving until the
- * .sjs experiences closure of its socket and terminates the payload stream.
- */
-function handlePassThrough(evt, filename) {
-  evt.waitUntil((async () => {
-    console.log("issuing monitor fetch request");
-    const response = await fetch("server-stream-download.sjs?monitor");
-    console.log("monitor headers received, awaiting body");
-    const data = await response.json();
-    console.log("passthrough monitor fetch completed, notifying.");
-    channel.postMessage({
-      what: filename,
-      why: data.why,
-      message: data.message
-    });
-  })());
-  evt.respondWith(fetch("server-stream-download.sjs").then(response => {
-    console.log("server-stream-download.sjs Response received, propagating");
-    return response;
-  }));
-}
-
-addEventListener("fetch", evt => {
-  console.log(`SW processing fetch of ${evt.request.url}`);
-  if (evt.request.url.indexOf("sw-stream-download") >= 0) {
-    return handleStream(evt, "sw-stream-download");
-  }
-  if (evt.request.url.indexOf("sw-passthrough-download") >= 0) {
-    return handlePassThrough(evt, "sw-passthrough-download");
-  }
-})
-
-addEventListener("message", evt => {
-  if (evt.data === "claim") {
-    evt.waitUntil(clients.claim());
-  }
-});
--- a/netwerk/base/ADivertableParentChannel.h
+++ b/netwerk/base/ADivertableParentChannel.h
@@ -32,29 +32,14 @@ public:
   virtual nsresult SuspendForDiversion() = 0;
 
   // While messages are diverted back from the child to the parent calls to
   // suspend/resume the channel must also suspend/resume the message diversion.
   // These two functions will be called by nsHttpChannel and nsFtpChannel
   // Suspend()/Resume() functions.
   virtual nsresult SuspendMessageDiversion() = 0;
   virtual nsresult ResumeMessageDiversion() = 0;
-
-  // Cancel an ongoing diversion by using IPC to invoke Cancel() in the child.
-  // This is necessary because most of the channel's state machine is suspended
-  // during diversion, so an explicit action must be taken to interrupt the
-  // diversion process so cancellation can be fully processed.
-  //
-  // Historically, diversions were assumed to be shortlived, where it was merely
-  // a question of diverting some small amount of network traffic back to the
-  // parent.  However, Service Worker child interception made it possible for
-  // the data to entirely be sourced from the child, which makes diversion
-  // potentially long-lived.  Especially when large files are involved.
-  //
-  // This mechanism is expected to be removed when ServiceWorkers move from
-  // child intercept to parent intercept (in the short to medium term).
-  virtual nsresult CancelDiversion() = 0;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif
--- a/netwerk/protocol/ftp/FTPChannelParent.cpp
+++ b/netwerk/protocol/ftp/FTPChannelParent.cpp
@@ -732,25 +732,16 @@ FTPChannelParent::SuspendMessageDiversio
 nsresult
 FTPChannelParent::ResumeMessageDiversion()
 {
   // This only need to resumes message queue.
   mEventQ->Resume();
   return NS_OK;
 }
 
-nsresult
-FTPChannelParent::CancelDiversion()
-{
-  // Only HTTP channels can have child-process-sourced-data that's long-lived
-  // so this isn't currently relevant for FTP channels and there is nothing to
-  // do.
-  return NS_OK;
-}
-
 void
 FTPChannelParent::DivertTo(nsIStreamListener *aListener)
 {
   MOZ_ASSERT(aListener);
   if (NS_WARN_IF(!mDivertingFromChild)) {
     MOZ_ASSERT(mDivertingFromChild,
                "Cannot DivertTo new listener if diverting is not set!");
     return;
--- a/netwerk/protocol/ftp/FTPChannelParent.h
+++ b/netwerk/protocol/ftp/FTPChannelParent.h
@@ -49,18 +49,16 @@ public:
 
   bool Init(const FTPChannelCreationArgs& aOpenArgs);
 
   // ADivertableParentChannel functions.
   void DivertTo(nsIStreamListener *aListener) override;
   nsresult SuspendForDiversion() override;
   nsresult SuspendMessageDiversion() override;
   nsresult ResumeMessageDiversion() override;
-  nsresult CancelDiversion() override;
-
 
   // Calls OnStartRequest for "DivertTo" listener, then notifies child channel
   // that it should divert OnDataAvailable and OnStopRequest calls to this
   // parent channel.
   void StartDiversion();
 
   // Handles calling OnStart/Stop if there are errors during diversion.
   // Called asynchronously from FailDiversion.
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -610,16 +610,18 @@ HttpChannelChild::OnStartRequest(const n
   //
   // gHttpHandler->OnExamineResponse(this);
 
   mTracingEnabled = false;
 
   DoOnStartRequest(this, mListenerContext);
 }
 
+namespace {
+
 class SyntheticDiversionListener final : public nsIStreamListener
 {
   RefPtr<HttpChannelChild> mChannel;
 
   ~SyntheticDiversionListener()
   {
   }
 
@@ -636,49 +638,43 @@ public:
     MOZ_ASSERT_UNREACHABLE("SyntheticDiversionListener should never see OnStartRequest");
     return NS_OK;
   }
 
   NS_IMETHOD
   OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
                 nsresult aStatus) override
   {
-    if (mChannel->mIPCOpen) {
-      mChannel->SendDivertOnStopRequest(aStatus);
-      mChannel->SendDivertComplete();
-    }
+    mChannel->SendDivertOnStopRequest(aStatus);
     return NS_OK;
   }
 
   NS_IMETHOD
   OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
                   nsIInputStream* aInputStream, uint64_t aOffset,
                   uint32_t aCount) override
   {
-    if (!mChannel->mIPCOpen) {
-      aRequest->Cancel(NS_ERROR_ABORT);
-      return NS_ERROR_ABORT;
-    }
-
     nsAutoCString data;
     nsresult rv = NS_ConsumeStream(aInputStream, aCount, data);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aRequest->Cancel(rv);
       return rv;
     }
 
     mChannel->SendDivertOnDataAvailable(data, aOffset, aCount);
     return NS_OK;
   }
 
   NS_DECL_ISUPPORTS
 };
 
 NS_IMPL_ISUPPORTS(SyntheticDiversionListener, nsIStreamListener);
 
+} // anonymous namespace
+
 void
 HttpChannelChild::DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
 {
   LOG(("HttpChannelChild::DoOnStartRequest [this=%p]\n", this));
 
   // In theory mListener should not be null, but in practice sometimes it is.
   MOZ_ASSERT(mListener);
   if (!mListener) {
@@ -1881,21 +1877,17 @@ HttpChannelChild::FlushedForDiversion()
   LOG(("HttpChannelChild::FlushedForDiversion [this=%p]\n", this));
   MOZ_RELEASE_ASSERT(mDivertingToParent);
 
   // Once this is set, it should not be unset before HttpChannelChild is taken
   // down. After it is set, no OnStart/OnData/OnStop callbacks should be
   // received from the parent channel, nor dequeued from the ChannelEventQueue.
   mFlushedForDiversion = true;
 
-  // If we're synthesized, it's up to the SyntheticDiversionListener to invoke
-  // SendDivertComplete after it has sent the DivertOnStopRequestMessage.
-  if (!mSynthesizedResponse) {
-    SendDivertComplete();
-  }
+  SendDivertComplete();
 }
 
 void
 HttpChannelChild::ProcessSetClassifierMatchedInfo(const nsCString& aList,
                                                   const nsCString& aProvider,
                                                   const nsCString& aFullHash)
 {
   LOG(("HttpChannelChild::ProcessSetClassifierMatchedInfo [this=%p]\n", this));
@@ -3870,31 +3862,16 @@ HttpChannelChild::RecvSetPriority(const 
 
 mozilla::ipc::IPCResult
 HttpChannelChild::RecvAttachStreamFilter(Endpoint<extensions::PStreamFilterParent>&& aEndpoint)
 {
   extensions::StreamFilterParent::Attach(this, Move(aEndpoint));
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult
-HttpChannelChild::RecvCancelDiversion()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  // This method is a very special case for cancellation of a diverted
-  // intercepted channel.  Normally we would go through the mEventQ in order to
-  // serialize event execution in the face of sync XHR and now background
-  // channels.  However, similar to how CancelOnMainThread describes, Cancel()
-  // pre-empts everything.  (And frankly, we want this stack frame on the stack
-  // if a crash happens.)
-  Cancel(NS_ERROR_ABORT);
-  return IPC_OK();
-}
-
 void
 HttpChannelChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // OnStartRequest might be dropped if IPDL is destroyed abnormally
   // and BackgroundChild might have pending IPC messages.
   // Clean up BackgroundChild at this time to prevent memleak.
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -42,17 +42,16 @@ class nsInputStreamPump;
 class nsIInterceptedBodyCallback;
 
 namespace mozilla {
 namespace net {
 
 class HttpBackgroundChannelChild;
 class InterceptedChannelContent;
 class InterceptStreamListener;
-class SyntheticDiversionListener;
 
 class HttpChannelChild final : public PHttpChannelChild
                              , public HttpBaseChannel
                              , public HttpAsyncAborter<HttpChannelChild>
                              , public nsICacheInfoChannel
                              , public nsIProxiedChannel
                              , public nsIApplicationCacheChannel
                              , public nsIAsyncVerifyRedirectCallback
@@ -164,18 +163,16 @@ protected:
 
   mozilla::ipc::IPCResult RecvIssueDeprecationWarning(const uint32_t& warning,
                                                       const bool& asError) override;
 
   mozilla::ipc::IPCResult RecvSetPriority(const int16_t& aPriority) override;
 
   mozilla::ipc::IPCResult RecvAttachStreamFilter(Endpoint<extensions::PStreamFilterParent>&& aEndpoint) override;
 
-  mozilla::ipc::IPCResult RecvCancelDiversion() override;
-
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   MOZ_MUST_USE bool
   GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr);
   virtual void DoNotifyListenerCleanup() override;
 
   NS_IMETHOD GetResponseSynthesized(bool* aSynthesized) override;
 
@@ -470,17 +467,16 @@ private:
   friend class Redirect1Event;
   friend class Redirect3Event;
   friend class DeleteSelfEvent;
   friend class HttpFlushedForDiversionEvent;
   friend class CancelEvent;
   friend class HttpAsyncAborter<HttpChannelChild>;
   friend class InterceptStreamListener;
   friend class InterceptedChannelContent;
-  friend class SyntheticDiversionListener;
   friend class HttpBackgroundChannelChild;
   friend class NeckoTargetChannelEvent<HttpChannelChild>;
 };
 
 // A stream listener interposed between the nsInputStreamPump used for intercepted channels
 // and this channel's original listener. This is only used to ensure the original listener
 // sees the channel as the request object, and to synthesize OnStatus and OnProgress notifications.
 class InterceptStreamListener : public nsIStreamListener
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -2006,26 +2006,16 @@ nsresult
 HttpChannelParent::ResumeMessageDiversion()
 {
   LOG(("HttpChannelParent::SuspendMessageDiversion [this=%p]", this));
   // This only needs to resumes message queue.
   mEventQ->Resume();
   return NS_OK;
 }
 
-nsresult
-HttpChannelParent::CancelDiversion()
-{
-  LOG(("HttpChannelParent::CancelDiversion [this=%p]", this));
-  if (!mIPCClosed) {
-    Unused << SendCancelDiversion();
-  }
-  return NS_OK;
-}
-
 /* private, supporting function for ADivertableParentChannel */
 nsresult
 HttpChannelParent::ResumeForDiversion()
 {
   LOG(("HttpChannelParent::ResumeForDiversion [this=%p]\n", this));
   MOZ_ASSERT(mChannel);
   if (NS_WARN_IF(!mDivertingFromChild)) {
     MOZ_ASSERT(mDivertingFromChild,
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -78,17 +78,16 @@ public:
 
   MOZ_MUST_USE bool Init(const HttpChannelCreationArgs& aOpenArgs);
 
   // ADivertableParentChannel functions.
   void DivertTo(nsIStreamListener *aListener) override;
   MOZ_MUST_USE nsresult SuspendForDiversion() override;
   MOZ_MUST_USE nsresult SuspendMessageDiversion() override;
   MOZ_MUST_USE nsresult ResumeMessageDiversion() override;
-  MOZ_MUST_USE nsresult CancelDiversion() override;
 
   // Calls OnStartRequest for "DivertTo" listener, then notifies child channel
   // that it should divert OnDataAvailable and OnStopRequest calls to this
   // parent channel.
   void StartDiversion();
 
   // Handles calling OnStart/Stop if there are errors during diversion.
   // Called asynchronously from FailDiversion.
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
@@ -27,17 +27,16 @@ InterceptedHttpChannel::InterceptedHttpC
                                                const TimeStamp& aAsyncOpenTimestamp)
   : HttpAsyncAborter<InterceptedHttpChannel>(this)
   , mProgress(0)
   , mProgressReported(0)
   , mSynthesizedStreamLength(-1)
   , mResumeStartPos(0)
   , mSynthesizedOrReset(Invalid)
   , mCallingStatusAndProgress(false)
-  , mDiverting(false)
 {
   // Pre-set the creation and AsyncOpen times based on the original channel
   // we are intercepting.  We don't want our extra internal redirect to mask
   // any time spent processing the channel.
   mChannelCreationTime = aCreationTime;
   mChannelCreationTimestamp = aCreationTimestamp;
   mAsyncOpenTime = aAsyncOpenTimestamp;
 }
@@ -496,25 +495,16 @@ InterceptedHttpChannel::Cancel(nsresult 
   }
   mCanceled = true;
 
   MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(aStatus));
   if (NS_SUCCEEDED(mStatus)) {
     mStatus = aStatus;
   }
 
-  // Everything is suspended during diversion until it completes.  Since the
-  // intercepted channel could be a long-running stream, we need to request that
-  // cancellation be triggered in the child, completing the diversion and
-  // allowing cancellation to run to completion.
-  if (mDiverting) {
-    Unused << mParentChannel->CancelDiversion();
-    // (We want the pump to be canceled as well, so don't directly return.)
-  }
-
   if (mPump) {
     return mPump->Cancel(mStatus);
   }
 
   return AsyncAbort(mStatus);
 }
 
 NS_IMETHODIMP
@@ -1118,30 +1108,28 @@ InterceptedHttpChannel::OnDataAvailable(
                                     aOffset, aCount);
 }
 
 NS_IMETHODIMP
 InterceptedHttpChannel::MessageDiversionStarted(ADivertableParentChannel* aParentChannel)
 {
   MOZ_ASSERT(!mParentChannel);
   mParentChannel = aParentChannel;
-  mDiverting = true;
   uint32_t suspendCount = mSuspendCount;
   while(suspendCount--) {
     mParentChannel->SuspendMessageDiversion();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptedHttpChannel::MessageDiversionStop()
 {
   MOZ_ASSERT(mParentChannel);
   mParentChannel = nullptr;
-  mDiverting = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptedHttpChannel::SuspendInternal()
 {
   ++mSuspendCount;
   if (mPump) {
--- a/netwerk/protocol/http/InterceptedHttpChannel.h
+++ b/netwerk/protocol/http/InterceptedHttpChannel.h
@@ -89,17 +89,16 @@ private:
   nsCString mResumeEntityId;
   nsString mStatusHost;
   enum {
     Invalid = 0,
     Synthesized,
     Reset
   } mSynthesizedOrReset;
   Atomic<bool> mCallingStatusAndProgress;
-  bool mDiverting;
 
   InterceptedHttpChannel(PRTime aCreationTime,
                          const TimeStamp& aCreationTimestamp,
                          const TimeStamp& aAsyncOpenTimestamp);
   ~InterceptedHttpChannel() = default;
 
   virtual void
   ReleaseListeners() override;
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -145,19 +145,16 @@ child:
 
   // When CORS blocks the request in the parent process, it doesn't have the
   // correct window ID, so send the message to the child for logging to the web
   // console.
   async LogBlockedCORSRequest(nsString message);
 
   async AttachStreamFilter(Endpoint<PStreamFilterParent> aEndpoint);
 
-  // See ADivertableParentChannel::CancelDiversion
-  async CancelDiversion();
-
 both:
   // After receiving this message, the parent also calls
   // SendFinishInterceptedRedirect, and makes sure not to send any more messages
   // after that. When receiving this message, the child will call
   // Send__delete__() and complete the steps required to finish the redirect.
   async FinishInterceptedRedirect();
 
   async SetPriority(int16_t priority);