Bug 1402944: Part 4 - Fold start/stop listener into ChannelWrapper. r=mixedpuppy,ehsan draft
authorKris Maglione <maglione.k@gmail.com>
Tue, 26 Sep 2017 13:39:30 -0700
changeset 670803 14027f62bd457ac283cb7ecefc349169ee1c9686
parent 670802 3ab72773f74a7ef2ed6f9351d1490f89b023f21d
child 670804 34bf44fca36716da45103fce33ce26757201d80d
push id81714
push usermaglione.k@gmail.com
push dateTue, 26 Sep 2017 21:30:45 +0000
reviewersmixedpuppy, ehsan
bugs1402944
milestone58.0a1
Bug 1402944: Part 4 - Fold start/stop listener into ChannelWrapper. r=mixedpuppy,ehsan MozReview-Commit-ID: 52zZNjgaCEj
dom/webidl/ChannelWrapper.webidl
toolkit/components/build/nsToolkitCompsModule.cpp
toolkit/components/extensions/webrequest/ChannelWrapper.cpp
toolkit/components/extensions/webrequest/ChannelWrapper.h
toolkit/components/extensions/webrequest/moz.build
toolkit/components/extensions/webrequest/nsIWebRequestListener.idl
toolkit/components/extensions/webrequest/nsWebRequestListener.cpp
toolkit/components/extensions/webrequest/nsWebRequestListener.h
toolkit/modules/addons/WebRequest.jsm
--- a/dom/webidl/ChannelWrapper.webidl
+++ b/dom/webidl/ChannelWrapper.webidl
@@ -164,16 +164,27 @@ interface ChannelWrapper : EventTarget {
   /**
    * Checks the request's current status and dispatches an error event if the
    * request has failed and one has not already been dispatched.
    */
   void errorCheck();
 
 
   /**
+   * Dispatched when the channel begins receiving data.
+   */
+  attribute EventHandler onstart;
+
+  /**
+   * Dispatched when the channel has finished receiving data.
+   */
+  attribute EventHandler onstop;
+
+
+  /**
    * Information about the proxy server which is handling this request, or
    * null if the request is not proxied.
    */
   [Cached, Frozen, GetterThrows, Pure]
   readonly attribute MozProxyInfo? proxyInfo;
 
   /**
    * For HTTP requests, the IP address of the remote server handling the
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -41,18 +41,16 @@
 #include "mozilla/WebRequestService.h"
 
 #if defined(XP_WIN)
 #include "NativeFileWatcherWin.h"
 #else
 #include "NativeFileWatcherNotSupported.h"
 #endif // (XP_WIN)
 
-#include "nsWebRequestListener.h"
-
 #if !defined(MOZ_WIDGET_ANDROID)
 #define MOZ_HAS_TERMINATOR
 #endif
 
 #if defined(MOZ_HAS_TERMINATOR)
 #include "nsTerminator.h"
 #endif
 
@@ -126,18 +124,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(NativeOSF
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NativeFileWatcherService, Init)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(AddonContentPolicy)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AddonPathService, AddonPathService::GetInstance)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AddonManagerStartup, AddonManagerStartup::GetInstance)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ExtensionPolicyService, ExtensionPolicyService::GetInstance)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WebRequestService, WebRequestService::GetInstance)
 
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebRequestListener)
-
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_APPSTARTUP_CID);
 #if defined(MOZ_HAS_PERFSTATS)
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_PERFORMANCESTATSSERVICE_CID);
 #endif // defined (MOZ_HAS_PERFSTATS)
 
 #if defined(MOZ_HAS_TERMINATOR)
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_TERMINATOR_CID);
 #endif
@@ -163,17 +159,16 @@ NS_DEFINE_NAMED_CID(NS_UPDATEPROCESSOR_C
 NS_DEFINE_NAMED_CID(FINALIZATIONWITNESSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NATIVE_OSFILE_INTERNALS_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_ADDONCONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_ADDON_PATH_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_ADDON_MANAGER_STARTUP_CID);
 NS_DEFINE_NAMED_CID(NS_ADDON_POLICY_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_WEBREQUEST_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NATIVE_FILEWATCHER_SERVICE_CID);
-NS_DEFINE_NAMED_CID(NS_WEBREQUESTLISTENER_CID);
 
 static const Module::CIDEntry kToolkitCIDs[] = {
   { &kNS_TOOLKIT_APPSTARTUP_CID, false, nullptr, nsAppStartupConstructor },
 #if defined(MOZ_HAS_TERMINATOR)
   { &kNS_TOOLKIT_TERMINATOR_CID, false, nullptr, nsTerminatorConstructor },
 #endif
 #if defined(MOZ_HAS_PERFSTATS)
   { &kNS_TOOLKIT_PERFORMANCESTATSSERVICE_CID, false, nullptr, nsPerformanceStatsServiceConstructor },
@@ -200,17 +195,16 @@ static const Module::CIDEntry kToolkitCI
   { &kFINALIZATIONWITNESSSERVICE_CID, false, nullptr, FinalizationWitnessServiceConstructor },
   { &kNATIVE_OSFILE_INTERNALS_SERVICE_CID, false, nullptr, NativeOSFileInternalsServiceConstructor },
   { &kNS_ADDONCONTENTPOLICY_CID, false, nullptr, AddonContentPolicyConstructor },
   { &kNS_ADDON_PATH_SERVICE_CID, false, nullptr, AddonPathServiceConstructor },
   { &kNS_ADDON_MANAGER_STARTUP_CID, false, nullptr, AddonManagerStartupConstructor },
   { &kNS_ADDON_POLICY_SERVICE_CID, false, nullptr, ExtensionPolicyServiceConstructor },
   { &kNS_WEBREQUEST_SERVICE_CID, false, nullptr, WebRequestServiceConstructor },
   { &kNATIVE_FILEWATCHER_SERVICE_CID, false, nullptr, NativeFileWatcherServiceConstructor },
-  { &kNS_WEBREQUESTLISTENER_CID, false, nullptr, nsWebRequestListenerConstructor },
   { nullptr }
 };
 
 static const Module::ContractIDEntry kToolkitContracts[] = {
   { NS_APPSTARTUP_CONTRACTID, &kNS_TOOLKIT_APPSTARTUP_CID },
 #if defined(MOZ_HAS_TERMINATOR)
   { NS_TOOLKIT_TERMINATOR_CONTRACTID, &kNS_TOOLKIT_TERMINATOR_CID },
 #endif
@@ -240,17 +234,16 @@ static const Module::ContractIDEntry kTo
   { FINALIZATIONWITNESSSERVICE_CONTRACTID, &kFINALIZATIONWITNESSSERVICE_CID },
   { NATIVE_OSFILE_INTERNALS_SERVICE_CONTRACTID, &kNATIVE_OSFILE_INTERNALS_SERVICE_CID },
   { NS_ADDONCONTENTPOLICY_CONTRACTID, &kNS_ADDONCONTENTPOLICY_CID },
   { NS_ADDONPATHSERVICE_CONTRACTID, &kNS_ADDON_PATH_SERVICE_CID },
   { NS_ADDONMANAGERSTARTUP_CONTRACTID, &kNS_ADDON_MANAGER_STARTUP_CID },
   { NS_ADDON_POLICY_SERVICE_CONTRACTID, &kNS_ADDON_POLICY_SERVICE_CID },
   { NS_WEBREQUESTSERVICE_CONTRACTID, &kNS_WEBREQUEST_SERVICE_CID },
   { NATIVE_FILEWATCHER_SERVICE_CONTRACTID, &kNATIVE_FILEWATCHER_SERVICE_CID },
-  { NS_WEBREQUESTLISTENER_CONTRACTID, &kNS_WEBREQUESTLISTENER_CID },
   { nullptr }
 };
 
 static const mozilla::Module::CategoryEntry kToolkitCategories[] = {
   { "content-policy", NS_ADDONCONTENTPOLICY_CONTRACTID, NS_ADDONCONTENTPOLICY_CONTRACTID },
   { nullptr }
 };
 
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
@@ -24,18 +24,20 @@
 #include "nsIHttpChannelInternal.h"
 #include "nsIHttpHeaderVisitor.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroup.h"
 #include "nsIProxiedChannel.h"
 #include "nsIProxyInfo.h"
+#include "nsITraceableChannel.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsNetUtil.h"
+#include "nsProxyRelease.h"
 #include "nsPrintfCString.h"
 
 using namespace mozilla::dom;
 using namespace JS;
 
 namespace mozilla {
 namespace extensions {
 
@@ -714,16 +716,84 @@ ChannelWrapper::ErrorCheck()
       mFiredErrorEvent = true;
       ChannelWrapperBinding::ClearCachedErrorStringValue(this);
       FireEvent(NS_LITERAL_STRING("error"));
     }
   }
 }
 
 /*****************************************************************************
+ * nsIWebRequestListener
+ *****************************************************************************/
+
+NS_IMPL_ISUPPORTS(ChannelWrapper::RequestListener,
+                  nsIStreamListener,
+                  nsIRequestObserver,
+                  nsIThreadRetargetableStreamListener)
+
+ChannelWrapper::RequestListener::~RequestListener() {
+  NS_ReleaseOnMainThreadSystemGroup("RequestListener::mChannelWrapper",
+                                    mChannelWrapper.forget());
+}
+
+nsresult
+ChannelWrapper::RequestListener::Init()
+{
+  if (nsCOMPtr<nsITraceableChannel> chan = mChannelWrapper->QueryChannel()) {
+    return chan->SetNewListener(this, getter_AddRefs(mOrigStreamListener));
+  }
+  return NS_ERROR_UNEXPECTED;
+}
+
+NS_IMETHODIMP
+ChannelWrapper::RequestListener::OnStartRequest(nsIRequest *request, nsISupports * aCtxt)
+{
+  MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
+
+  mChannelWrapper->ErrorCheck();
+  mChannelWrapper->FireEvent(NS_LITERAL_STRING("start"));
+
+  return mOrigStreamListener->OnStartRequest(request, aCtxt);
+}
+
+NS_IMETHODIMP
+ChannelWrapper::RequestListener::OnStopRequest(nsIRequest *request, nsISupports *aCtxt,
+                                           nsresult aStatus)
+{
+  MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
+
+  mChannelWrapper->ErrorCheck();
+  mChannelWrapper->FireEvent(NS_LITERAL_STRING("stop"));
+
+  return mOrigStreamListener->OnStopRequest(request, aCtxt, aStatus);
+}
+
+NS_IMETHODIMP
+ChannelWrapper::RequestListener::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt,
+                                             nsIInputStream * inStr,
+                                             uint64_t sourceOffset, uint32_t count)
+{
+  MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
+  return mOrigStreamListener->OnDataAvailable(request, aCtxt, inStr, sourceOffset, count);
+}
+
+NS_IMETHODIMP
+ChannelWrapper::RequestListener::CheckListenerChain()
+{
+    MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread!");
+    nsresult rv;
+    nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
+        do_QueryInterface(mOrigStreamListener, &rv);
+    if (retargetableListener) {
+        return retargetableListener->CheckListenerChain();
+    }
+    return rv;
+}
+
+/*****************************************************************************
  * Event dispatching
  *****************************************************************************/
 
 void
 ChannelWrapper::FireEvent(const nsAString& aType)
 {
   EventInit init;
   init.mBubbles = false;
@@ -731,16 +801,41 @@ ChannelWrapper::FireEvent(const nsAStrin
 
   RefPtr<Event> event = Event::Constructor(this, aType, init);
   event->SetTrusted(true);
 
   bool defaultPrevented;
   DispatchEvent(event, &defaultPrevented);
 }
 
+void
+ChannelWrapper::CheckEventListeners()
+{
+  if (!mAddedStreamListener && (HasListenersFor(nsGkAtoms::onerror) ||
+                                HasListenersFor(nsGkAtoms::onstart) ||
+                                HasListenersFor(nsGkAtoms::onstop))) {
+    auto listener = MakeRefPtr<RequestListener>(this);
+    if (!NS_WARN_IF(NS_FAILED(listener->Init()))) {
+      mAddedStreamListener = true;
+    }
+  }
+}
+
+void
+ChannelWrapper::EventListenerAdded(nsIAtom* aType)
+{
+  CheckEventListeners();
+}
+
+void
+ChannelWrapper::EventListenerRemoved(nsIAtom* aType)
+{
+  CheckEventListeners();
+}
+
 /*****************************************************************************
  * Glue
  *****************************************************************************/
 
 JSObject*
 ChannelWrapper::WrapObject(JSContext* aCx, HandleObject aGivenProto)
 {
   return ChannelWrapperBinding::Wrap(aCx, this, aGivenProto);
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.h
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.h
@@ -13,16 +13,18 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannel.h"
+#include "nsIStreamListener.h"
+#include "nsIThreadRetargetableStreamListener.h"
 #include "nsWeakPtr.h"
 #include "nsWrapperCache.h"
 
 #define NS_CHANNELWRAPPER_IID \
 { 0xc06162d2, 0xb803, 0x43b4, \
   { 0xaa, 0x31, 0xcf, 0x69, 0x7f, 0x93, 0x68, 0x1c } }
 
 class nsIDOMElement;
@@ -134,16 +136,18 @@ public:
 
   void GetStatusLine(nsCString& aRetVal) const;
 
   void GetErrorString(nsString& aRetVal) const;
 
   void ErrorCheck();
 
   IMPL_EVENT_HANDLER(error);
+  IMPL_EVENT_HANDLER(start);
+  IMPL_EVENT_HANDLER(stop);
 
 
   already_AddRefed<nsIURI> GetFinalURI(ErrorResult& aRv) const;
 
   void GetFinalURL(nsCString& aRetVal, ErrorResult& aRv) const;
 
 
   already_AddRefed<nsILoadInfo> GetLoadInfo() const
@@ -187,16 +191,22 @@ public:
 
   void GetResponseHeaders(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv) const;
 
   void SetRequestHeader(const nsCString& header, const nsCString& value, ErrorResult& aRv);
 
   void SetResponseHeader(const nsCString& header, const nsCString& value, ErrorResult& aRv);
 
 
+  using EventTarget::EventListenerAdded;
+  using EventTarget::EventListenerRemoved;
+  virtual void EventListenerAdded(nsIAtom* aType) override;
+  virtual void EventListenerRemoved(nsIAtom* aType) override;
+
+
   nsISupports* GetParentObject() const { return mParent; }
 
   JSObject* WrapObject(JSContext* aCx, JS::HandleObject aGivenProto) override;
 
 protected:
   ~ChannelWrapper() = default;
 
 private:
@@ -221,22 +231,55 @@ private:
   uint64_t WindowId(nsILoadInfo* aLoadInfo) const;
 
   static uint64_t GetNextId()
   {
     static uint64_t sNextId = 1;
     return ++sNextId;
   }
 
+  void CheckEventListeners();
+
+  mutable Maybe<URLInfo> mFinalURLInfo;
+  mutable Maybe<URLInfo> mDocumentURLInfo;
+
+  UniquePtr<WebRequestChannelEntry> mChannelEntry;
+
+  // The overridden Content-Type header value.
+  nsCString mContentTypeHdr = VoidCString();
 
   const uint64_t mId = GetNextId();
   nsCOMPtr<nsISupports> mParent;
 
+  bool mAddedStreamListener = false;
   bool mFiredErrorEvent = false;
   bool mSuspended = false;
+
+
+  class RequestListener final : public nsIStreamListener
+                              , public nsIThreadRetargetableStreamListener
+  {
+  public:
+    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_NSIREQUESTOBSERVER
+    NS_DECL_NSISTREAMLISTENER
+    NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
+
+    explicit RequestListener(ChannelWrapper* aWrapper)
+      : mChannelWrapper(aWrapper) {}
+
+    nsresult Init();
+
+  protected:
+    virtual ~RequestListener();
+
+  private:
+    RefPtr<ChannelWrapper> mChannelWrapper;
+    nsCOMPtr<nsIStreamListener> mOrigStreamListener;
+  };
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(ChannelWrapper,
                               NS_CHANNELWRAPPER_IID)
 
 } // namespace extensions
 } // namespace mozilla
 
--- a/toolkit/components/extensions/webrequest/moz.build
+++ b/toolkit/components/extensions/webrequest/moz.build
@@ -1,39 +1,33 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'mozIWebRequestService.idl',
-    'nsIWebRequestListener.idl',
 ]
 
 XPIDL_MODULE = 'webextensions'
 
 UNIFIED_SOURCES += [
     'ChannelWrapper.cpp',
-    'nsWebRequestListener.cpp',
     'StreamFilter.cpp',
     'StreamFilterChild.cpp',
     'StreamFilterEvents.cpp',
     'StreamFilterParent.cpp',
     'WebRequestService.cpp',
 ]
 
 IPDL_SOURCES += [
     'PStreamFilter.ipdl',
 ]
 
-EXPORTS += [
-    'nsWebRequestListener.h',
-]
-
 EXPORTS.mozilla += [
     'WebRequestService.h',
 ]
 
 EXPORTS.mozilla.extensions += [
     'ChannelWrapper.h',
     'StreamFilter.h',
     'StreamFilterBase.h',
deleted file mode 100644
--- a/toolkit/components/extensions/webrequest/nsIWebRequestListener.idl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIStreamListener.idl"
-#include "nsITraceableChannel.idl"
-
-/* nsIWebRequestListener is a nsIThreadRetargetableStreamListener that handles
- * forwarding of nsIRequestObserver for JS consumers. nsIWebRequestListener
- * is not cycle collected, JS consumers should not keep a reference to this.
- */
-
-[scriptable, uuid(699a50bb-1f18-2844-b9ea-9f216f62cb18)]
-interface nsIWebRequestListener : nsISupports
-{
-  void init(in nsIStreamListener aStreamListener,
-            in nsITraceableChannel aTraceableChannel);
-};
-
-%{C++
-/* ebea9901-e135-b546-82e2-052666992dbb */
-#define NS_WEBREQUESTLISTENER_CID                   \
- {0xebea9901, 0xe135, 0xb546,                       \
- {0x82, 0xe2, 0x05, 0x26, 0x66, 0x99, 0x2d, 0xbb} }
-#define NS_WEBREQUESTLISTENER_CONTRACTID "@mozilla.org/webextensions/webRequestListener;1"
-%}
\ No newline at end of file
deleted file mode 100644
--- a/toolkit/components/extensions/webrequest/nsWebRequestListener.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/ModuleUtils.h"
-#include "nsWebRequestListener.h"
-
-#ifdef DEBUG
-#include "MainThreadUtils.h"
-#endif
-
-using namespace mozilla;
-
-NS_IMPL_ISUPPORTS(nsWebRequestListener,
-                  nsIWebRequestListener,
-                  nsIStreamListener,
-                  nsIRequestObserver,
-                  nsIThreadRetargetableStreamListener)
-
-NS_IMETHODIMP
-nsWebRequestListener::Init(nsIStreamListener *aStreamListener, nsITraceableChannel *aTraceableChannel)
-{
-  MOZ_ASSERT(aStreamListener, "Should have aStreamListener");
-  MOZ_ASSERT(aTraceableChannel, "Should have aTraceableChannel");
-  mTargetStreamListener = aStreamListener;
-  return aTraceableChannel->SetNewListener(this, getter_AddRefs(mOrigStreamListener));
-}
-
-NS_IMETHODIMP
-nsWebRequestListener::OnStartRequest(nsIRequest *request, nsISupports * aCtxt)
-{
-  MOZ_ASSERT(mTargetStreamListener, "Should have mTargetStreamListener");
-  MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
-
-  mTargetStreamListener->OnStartRequest(request, aCtxt);
-
-  return mOrigStreamListener->OnStartRequest(request, aCtxt);
-}
-
-NS_IMETHODIMP
-nsWebRequestListener::OnStopRequest(nsIRequest *request, nsISupports *aCtxt,
-                                           nsresult aStatus)
-{
-  MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
-  MOZ_ASSERT(mTargetStreamListener, "Should have mTargetStreamListener");
-
-  mOrigStreamListener->OnStopRequest(request, aCtxt, aStatus);
-
-  return mTargetStreamListener->OnStopRequest(request, aCtxt, aStatus);
-}
-
-NS_IMETHODIMP
-nsWebRequestListener::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt,
-                                             nsIInputStream * inStr,
-                                             uint64_t sourceOffset, uint32_t count)
-{
-  MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
-  return mOrigStreamListener->OnDataAvailable(request, aCtxt, inStr, sourceOffset, count);
-}
-
-NS_IMETHODIMP
-nsWebRequestListener::CheckListenerChain()
-{
-    MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread!");
-    nsresult rv;
-    nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
-        do_QueryInterface(mOrigStreamListener, &rv);
-    if (retargetableListener) {
-        return retargetableListener->CheckListenerChain();
-    }
-    return rv;
-}
deleted file mode 100644
--- a/toolkit/components/extensions/webrequest/nsWebRequestListener.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsWebRequestListener_h__
-#define nsWebRequestListener_h__
-
-#include "nsCOMPtr.h"
-#include "nsIWebRequestListener.h"
-#include "nsIRequestObserver.h"
-#include "nsIStreamListener.h"
-#include "nsITraceableChannel.h"
-#include "nsIThreadRetargetableStreamListener.h"
-#include "nsProxyRelease.h"
-#include "mozilla/Attributes.h"
-
-class nsWebRequestListener final : public nsIWebRequestListener
-                                 , public nsIStreamListener
-                                 , public nsIThreadRetargetableStreamListener
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIWEBREQUESTLISTENER
-  NS_DECL_NSIREQUESTOBSERVER
-  NS_DECL_NSISTREAMLISTENER
-  NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
-
-  nsWebRequestListener() {}
-
-private:
-  ~nsWebRequestListener() {
-    NS_ReleaseOnMainThreadSystemGroup("nsWebRequestListener::mTargetStreamListener",
-                                      mTargetStreamListener.forget());
-  }
-  nsCOMPtr<nsIStreamListener> mOrigStreamListener;
-  nsCOMPtr<nsIStreamListener> mTargetStreamListener;
-};
-
-#endif // nsWebRequestListener_h__
-
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -28,19 +28,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/WebRequestUpload.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "webReqService",
                                    "@mozilla.org/addons/webrequest-service;1",
                                    "mozIWebRequestService");
 
 XPCOMUtils.defineLazyGetter(this, "ExtensionError", () => ExtensionUtils.ExtensionError);
 
-let WebRequestListener = Components.Constructor("@mozilla.org/webextensions/webRequestListener;1",
-                                                "nsIWebRequestListener", "init");
-
 function runLater(job) {
   Services.tm.dispatchToMainThread(job);
 }
 
 function parseFilter(filter) {
   if (!filter) {
     filter = {};
   }
@@ -301,34 +298,16 @@ var ContentPolicyManager = {
 
     this.policyData.delete(id);
     this.idMap.delete(callback);
     this.policies.delete(id);
   },
 };
 ContentPolicyManager.init();
 
-function StartStopListener(manager, channel) {
-  this.manager = manager;
-  new WebRequestListener(this, channel.channel);
-}
-
-StartStopListener.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequestObserver,
-                                         Ci.nsIStreamListener]),
-
-  onStartRequest: function(request, context) {
-    this.manager.onStartRequest(ChannelWrapper.get(request));
-  },
-
-  onStopRequest(request, context, statusCode) {
-    this.manager.onStopRequest(ChannelWrapper.get(request));
-  },
-};
-
 var ChannelEventSink = {
   _classDescription: "WebRequest channel event sink",
   _classID: Components.ID("115062f8-92f1-11e5-8b7f-080027b0f7ec"),
   _contractID: "@mozilla.org/webrequest/channel-event-sink;1",
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannelEventSink,
                                          Ci.nsIFactory]),
 
@@ -527,16 +506,22 @@ HttpObserverManager = {
 
   getWrapper(nativeChannel) {
     let wrapper = ChannelWrapper.get(nativeChannel);
     if (!wrapper._addedListeners) {
       /* eslint-disable mozilla/balanced-listeners */
       if (this.listeners.onError.size) {
         wrapper.addEventListener("error", this);
       }
+      if (this.listeners.onStart.size) {
+        wrapper.addEventListener("start", this);
+      }
+      if (this.listeners.onStop.size) {
+        wrapper.addEventListener("stop", this);
+      }
       /* eslint-enable mozilla/balanced-listeners */
 
       wrapper._addedListeners = true;
     }
     return wrapper;
   },
 
   get activityDistributor() {
@@ -651,23 +636,16 @@ HttpObserverManager = {
   observeActivity(nativeChannel, activityType, activitySubtype /* , aTimestamp, aExtraSizeData, aExtraStringData */) {
     // Sometimes we get a NullHttpChannel, which implements
     // nsIHttpChannel but not nsIChannel.
     if (!(nativeChannel instanceof Ci.nsIChannel)) {
       return;
     }
     let channel = this.getWrapper(nativeChannel);
 
-    // StartStopListener has to be activated early in the request to catch
-    // SSL connection issues which do not get reported via nsIHttpActivityObserver.
-    if (activityType == nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION &&
-        activitySubtype == nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_HEADER) {
-      this.attachStartStopListener(channel);
-    }
-
     let lastActivity = channel.lastActivity || 0;
     if (activitySubtype === nsIHttpActivityObserver.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE &&
         lastActivity && lastActivity !== this.GOOD_LAST_ACTIVITY) {
       // Make a trip through the event loop to make sure errors have a
       // chance to be processed before we fall back to a generic error
       // string.
       Services.tm.dispatchToMainThread(() => {
         channel.errorCheck();
@@ -760,16 +738,23 @@ HttpObserverManager = {
 
   handleEvent(event) {
     let channel = event.currentTarget;
     switch (event.type) {
       case "error":
         this.runChannelListener(
           channel, "onError", {error: channel.errorString});
         break;
+      case "start":
+        this.destroyFilters(channel);
+        this.runChannelListener(channel, "onStart");
+        break;
+      case "stop":
+        this.runChannelListener(channel, "onStop");
+        break;
     }
   },
 
   runChannelListener(channel, kind, extraData = null) {
     let handlerResults = [];
     let requestHeaders;
     let responseHeaders;
 
@@ -909,35 +894,17 @@ HttpObserverManager = {
     for (let opts of listener.values()) {
       if (this.shouldRunListener(channel.type, channel.finalURI, opts.filter)) {
         return true;
       }
     }
     return false;
   },
 
-  attachStartStopListener(channel) {
-    // Check whether we've already added a listener to this channel,
-    // so we don't wind up chaining multiple listeners.
-    if (!this.needTracing || channel.hasListener ||
-        !(channel.channel instanceof Ci.nsITraceableChannel)) {
-      return;
-    }
-
-    // skip redirections, https://bugzilla.mozilla.org/show_bug.cgi?id=728901#c8
-    let {statusCode} = channel;
-    if (statusCode < 300 || statusCode >= 400) {
-      new StartStopListener(this, channel);
-      channel.hasListener = true;
-    }
-  },
-
   examine(channel, topic, data) {
-    this.attachStartStopListener(channel);
-
     if (this.listeners.headersReceived.size) {
       this.runChannelListener(channel, "headersReceived");
     }
 
     if (!channel.hasAuthRequestor && this.shouldHookListener(this.listeners.authRequired, channel)) {
       channel.channel.notificationCallbacks = new AuthRequestor(channel.channel, this);
       channel.hasAuthRequestor = true;
     }
@@ -947,25 +914,16 @@ HttpObserverManager = {
     let channel = this.getWrapper(oldChannel);
 
     // We want originalURI, this will provide a moz-ext rather than jar or file
     // uri on redirects.
     this.destroyFilters(channel);
     this.runChannelListener(channel, "onRedirect", {redirectUrl: newChannel.originalURI.spec});
     channel.channel = newChannel;
   },
-
-  onStartRequest(channel) {
-    this.destroyFilters(channel);
-    this.runChannelListener(channel, "onStart");
-  },
-
-  onStopRequest(channel) {
-    this.runChannelListener(channel, "onStop");
-  },
 };
 
 var onBeforeRequest = {
   allowedOptions: ["blocking", "requestBody"],
 
   addListener(callback, filter = null, options = null, optionsObject = null) {
     let opts = parseExtra(options, this.allowedOptions);
     opts.filter = parseFilter(filter);