Bug 1380186 implement SimpleChannel Parent/Child IPC draft
authorShane Caraveo <scaraveo@mozilla.com>
Wed, 12 Jul 2017 13:46:26 -0700
changeset 607796 8a090485a6aa4b370c5151d01e223d706de87b02
parent 607795 660798bdba861a956edc8f153da43695c112f9c6
child 637151 e83fcb23b9544fef047caaebf5603f77509ad2c8
push id68114
push usermixedpuppy@gmail.com
push dateWed, 12 Jul 2017 21:37:52 +0000
bugs1380186
milestone56.0a1
Bug 1380186 implement SimpleChannel Parent/Child IPC MozReview-Commit-ID: Ck4C1hWFmdE
netwerk/base/SimpleChannel.cpp
netwerk/base/SimpleChannelParent.cpp
netwerk/base/SimpleChannelParent.h
netwerk/base/moz.build
netwerk/ipc/NeckoChild.cpp
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
netwerk/ipc/PSimpleChannel.ipdl
netwerk/ipc/moz.build
toolkit/modules/addons/WebRequest.jsm
--- a/netwerk/base/SimpleChannel.cpp
+++ b/netwerk/base/SimpleChannel.cpp
@@ -1,33 +1,47 @@
 /* -*- 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 "SimpleChannel.h"
+
+#include "nsIChildChannel.h"
+#include "nsNetUtil.h"
+#include "nsIChannel.h"
+#include "nsISupportsImpl.h"
 #include "nsBaseChannel.h"
 #include "nsIInputStream.h"
 #include "nsIRequest.h"
-#include "SimpleChannel.h"
+#include "nsIChildChannel.h"
+#include "nsISupportsImpl.h"
+
+#include "mozilla/Unused.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/net/NeckoChild.h"
+
+#include "mozilla/net/PSimpleChannelChild.h"
 
 namespace mozilla {
 namespace net {
 
 // Like MOZ_TRY, but returns the unwrapped error value rather than a
 // GenericErrorResult on failure.
 #define TRY_VAR(target, expr) \
   do { \
     auto result = (expr); \
     if (result.isErr()) { \
       return result.unwrapErr(); \
     } \
     (target) = result.unwrap(); \
   } while (0)
 
-class SimpleChannel final : public nsBaseChannel
+
+class SimpleChannel : public nsBaseChannel
 {
 public:
   explicit SimpleChannel(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);
 
 protected:
   virtual ~SimpleChannel() {}
 
   virtual nsresult OpenContentStream(bool async, nsIInputStream **streamOut,
@@ -73,20 +87,114 @@ SimpleChannel::BeginAsyncRead(nsIStreamL
   mCallbacks = nullptr;
 
   req.forget(request);
   return NS_OK;
 }
 
 #undef TRY_VAR
 
+class SimpleChannelChild : public SimpleChannel
+                         , public nsIChildChannel
+                         , public PSimpleChannelChild
+{
+public:
+    explicit SimpleChannelChild(UniquePtr<SimpleChannelCallbacks>&& aCallbacks);
+
+    NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_NSICHILDCHANNEL
+
+protected:
+    virtual void ActorDestroy(ActorDestroyReason why) override;
+
+private:
+    ~SimpleChannelChild();
+
+    void AddIPDLReference();
+
+    bool mIPCOpen;
+};
+
+NS_IMPL_ISUPPORTS_INHERITED(SimpleChannelChild, SimpleChannel, nsIChildChannel)
+
+SimpleChannelChild::SimpleChannelChild(UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
+    : SimpleChannel(Move(aCallbacks))
+    , mIPCOpen(false)
+{
+}
+
+SimpleChannelChild::~SimpleChannelChild()
+{
+}
+
+NS_IMETHODIMP
+SimpleChannelChild::ConnectParent(uint32_t aId)
+{
+    mozilla::dom::ContentChild* cc =
+        static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
+    if (cc->IsShuttingDown()) {
+        return NS_ERROR_FAILURE;
+    }
+
+    if (!gNeckoChild->SendPSimpleChannelConstructor(this, aId)) {
+        return NS_ERROR_FAILURE;
+    }
+
+    // IPC now has a ref to us.
+    AddIPDLReference();
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelChild::CompleteRedirectSetup(nsIStreamListener *aListener,
+                                        nsISupports *aContext)
+{
+    nsresult rv;
+    if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
+        MOZ_ASSERT(!aContext, "aContext should be null!");
+        rv = AsyncOpen2(aListener);
+    }
+    else {
+        rv = AsyncOpen(aListener, aContext);
+    }
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+    }
+
+    if (mIPCOpen) {
+        Unused << Send__delete__(this);
+    }
+    return NS_OK;
+}
+
+void
+SimpleChannelChild::AddIPDLReference()
+{
+    AddRef();
+    mIPCOpen = true;
+}
+
+void
+SimpleChannelChild::ActorDestroy(ActorDestroyReason why)
+{
+    MOZ_ASSERT(mIPCOpen);
+    mIPCOpen = false;
+    Release();
+}
+
+
 already_AddRefed<nsIChannel>
 NS_NewSimpleChannelInternal(nsIURI* aURI, nsILoadInfo* aLoadInfo, UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
 {
-  RefPtr<SimpleChannel> chan = new SimpleChannel(Move(aCallbacks));
+  RefPtr<SimpleChannel> chan;
+  if (IsNeckoChild()) {
+      chan = new mozilla::net::SimpleChannelChild(Move(aCallbacks));
+  } else {
+      chan = new SimpleChannel(Move(aCallbacks));
+  }
 
   chan->SetURI(aURI);
 
   MOZ_ALWAYS_SUCCEEDS(chan->SetLoadInfo(aLoadInfo));
 
   return chan.forget();
 }
 
new file mode 100644
--- /dev/null
+++ b/netwerk/base/SimpleChannelParent.cpp
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 sw=4 sts=4 et tw=80: */
+/* 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 "SimpleChannelParent.h"
+#include "mozilla/Assertions.h"
+#include "nsNetUtil.h"
+#include "nsIChannel.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS(SimpleChannelParent, nsIParentChannel, nsIStreamListener)
+
+SimpleChannelParent::~SimpleChannelParent()
+{
+}
+
+bool
+SimpleChannelParent::Init(const uint32_t &channelId)
+{
+    nsCOMPtr<nsIChannel> channel;
+    MOZ_ALWAYS_SUCCEEDS(
+        NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel)));
+
+    return true;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::SetParentListener(HttpChannelParentListener* aListener)
+{
+    // Nothing to do.
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::NotifyTrackingProtectionDisabled()
+{
+    // Nothing to do.
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::NotifyTrackingResource()
+{
+    // Nothing to do.
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
+                                            const nsACString& aProvider,
+                                            const nsACString& aPrefix)
+{
+  // nothing to do
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::Delete()
+{
+    // Nothing to do.
+    return NS_OK;
+}
+
+void
+SimpleChannelParent::ActorDestroy(ActorDestroyReason why)
+{
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::OnStartRequest(nsIRequest *aRequest,
+                                  nsISupports *aContext)
+{
+    // We don't have a way to prevent nsBaseChannel from calling AsyncOpen on
+    // the created nsSimpleChannel. We don't have anywhere to send the data in the
+    // parent, so abort the binding.
+    return NS_BINDING_ABORTED;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::OnStopRequest(nsIRequest *aRequest,
+                                 nsISupports *aContext,
+                                 nsresult aStatusCode)
+{
+    // See above.
+    MOZ_ASSERT(NS_FAILED(aStatusCode));
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelParent::OnDataAvailable(nsIRequest *aRequest,
+                                   nsISupports *aContext,
+                                   nsIInputStream *aInputStream,
+                                   uint64_t aOffset,
+                                   uint32_t aCount)
+{
+    // See above.
+    MOZ_CRASH("Should never be called");
+}
+
+} // namespace net
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/base/SimpleChannelParent.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 sw=4 sts=4 et tw=80: */
+/* 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 NS_SIMPLECHANNELPARENT_H
+#define NS_SIMPLECHANNELPARENT_H
+
+#include "nsIParentChannel.h"
+#include "nsISupportsImpl.h"
+
+#include "mozilla/net/PSimpleChannelParent.h"
+
+namespace mozilla {
+namespace net {
+
+// In order to support HTTP redirects to data:, we need to implement the HTTP
+// redirection API, which requires a class that implements nsIParentChannel
+// and which calls NS_LinkRedirectChannels.
+class SimpleChannelParent : public nsIParentChannel
+                        , public PSimpleChannelParent
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIPARENTCHANNEL
+    NS_DECL_NSIREQUESTOBSERVER
+    NS_DECL_NSISTREAMLISTENER
+
+    MOZ_MUST_USE bool Init(const uint32_t& aArgs);
+
+private:
+    ~SimpleChannelParent();
+
+    virtual void ActorDestroy(ActorDestroyReason why) override;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif /* NS_SIMPLECHANNELPARENT_H */
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -174,16 +174,17 @@ EXPORTS.mozilla.net += [
     'CaptivePortalService.h',
     'ChannelDiverterChild.h',
     'ChannelDiverterParent.h',
     'Dashboard.h',
     'DashboardTypes.h',
     'MemoryDownloader.h',
     'Predictor.h',
     'ReferrerPolicy.h',
+    'SimpleChannelParent.h',
     'TCPFastOpen.h',
 ]
 
 UNIFIED_SOURCES += [
     'ArrayBufferInputStream.cpp',
     'BackgroundFileSaver.cpp',
     'CaptivePortalService.cpp',
     'ChannelDiverterChild.cpp',
@@ -244,16 +245,17 @@ UNIFIED_SOURCES += [
     'nsURLParsers.cpp',
     'PollableEvent.cpp',
     'Predictor.cpp',
     'ProxyAutoConfig.cpp',
     'RedirectChannelRegistrar.cpp',
     'RequestContextService.cpp',
     'SimpleBuffer.cpp',
     'SimpleChannel.cpp',
+    'SimpleChannelParent.cpp',
     'StreamingProtocolService.cpp',
     'TCPFastOpenLayer.cpp',
     'ThrottleQueue.cpp',
     'Tickler.cpp',
     'TLSServerSocket.cpp',
 ]
 
 if CONFIG['MOZ_RUST_URLPARSE']:
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -256,16 +256,30 @@ NeckoChild::AllocPFileChannelChild(const
 
 bool
 NeckoChild::DeallocPFileChannelChild(PFileChannelChild* child)
 {
   // NB: See FileChannelChild::ActorDestroy.
   return true;
 }
 
+PSimpleChannelChild*
+NeckoChild::AllocPSimpleChannelChild(const uint32_t& channelId)
+{
+  MOZ_ASSERT_UNREACHABLE("Should never get here");
+  return nullptr;
+}
+
+bool
+NeckoChild::DeallocPSimpleChannelChild(PSimpleChannelChild* child)
+{
+  // NB: See SimpleChannelChild::ActorDestroy.
+  return true;
+}
+
 PRtspControllerChild*
 NeckoChild::AllocPRtspControllerChild()
 {
   NS_NOTREACHED("AllocPRtspController should not be called");
   return nullptr;
 }
 
 bool
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -66,16 +66,18 @@ protected:
                                                   const OriginAttributes& aOriginAttributes,
                                                   const uint32_t& aFlags,
                                                   const nsCString& aNetworkInterface) override;
   virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) override;
   virtual PDataChannelChild* AllocPDataChannelChild(const uint32_t& channelId) override;
   virtual bool DeallocPDataChannelChild(PDataChannelChild* child) override;
   virtual PFileChannelChild* AllocPFileChannelChild(const uint32_t& channelId) override;
   virtual bool DeallocPFileChannelChild(PFileChannelChild* child) override;
+  virtual PSimpleChannelChild* AllocPSimpleChannelChild(const uint32_t& channelId) override;
+  virtual bool DeallocPSimpleChannelChild(PSimpleChannelChild* child) override;
   virtual PRtspControllerChild* AllocPRtspControllerChild() override;
   virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) override;
   virtual PRtspChannelChild*
     AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs)
                            override;
   virtual bool DeallocPRtspChannelChild(PRtspChannelChild*) override;
   virtual PChannelDiverterChild*
   AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) override;
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/net/HttpChannelParent.h"
 #include "mozilla/net/CookieServiceParent.h"
 #include "mozilla/net/WyciwygChannelParent.h"
 #include "mozilla/net/FTPChannelParent.h"
 #include "mozilla/net/WebSocketChannelParent.h"
 #include "mozilla/net/WebSocketEventListenerParent.h"
 #include "mozilla/net/DataChannelParent.h"
+#include "mozilla/net/SimpleChannelParent.h"
 #include "mozilla/net/AltDataOutputStreamParent.h"
 #include "mozilla/Unused.h"
 #include "mozilla/net/FileChannelParent.h"
 #ifdef NECKO_PROTOCOL_rtsp
 #include "mozilla/net/RtspControllerParent.h"
 #include "mozilla/net/RtspChannelParent.h"
 #endif
 #include "mozilla/net/DNSRequestParent.h"
@@ -525,16 +526,40 @@ NeckoParent::RecvPDataChannelConstructor
                                          const uint32_t& channelId)
 {
   DataChannelParent* p = static_cast<DataChannelParent*>(actor);
   DebugOnly<bool> rv = p->Init(channelId);
   MOZ_ASSERT(rv);
   return IPC_OK();
 }
 
+PSimpleChannelParent*
+NeckoParent::AllocPSimpleChannelParent(const uint32_t &channelId)
+{
+  RefPtr<SimpleChannelParent> p = new SimpleChannelParent();
+  return p.forget().take();
+}
+
+bool
+NeckoParent::DeallocPSimpleChannelParent(PSimpleChannelParent* actor)
+{
+  RefPtr<SimpleChannelParent> p = dont_AddRef(static_cast<SimpleChannelParent*>(actor));
+  return true;
+}
+
+mozilla::ipc::IPCResult
+NeckoParent::RecvPSimpleChannelConstructor(PSimpleChannelParent* actor,
+                                         const uint32_t& channelId)
+{
+  SimpleChannelParent* p = static_cast<SimpleChannelParent*>(actor);
+  DebugOnly<bool> rv = p->Init(channelId);
+  MOZ_ASSERT(rv);
+  return IPC_OK();
+}
+
 PFileChannelParent*
 NeckoParent::AllocPFileChannelParent(const uint32_t &channelId)
 {
   RefPtr<FileChannelParent> p = new FileChannelParent();
   return p.forget().take();
 }
 
 bool
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -177,16 +177,23 @@ protected:
 
   virtual PDataChannelParent*
     AllocPDataChannelParent(const uint32_t& channelId) override;
   virtual bool DeallocPDataChannelParent(PDataChannelParent* parent) override;
 
   virtual mozilla::ipc::IPCResult RecvPDataChannelConstructor(PDataChannelParent* aActor,
                                                               const uint32_t& channelId) override;
 
+  virtual PSimpleChannelParent*
+    AllocPSimpleChannelParent(const uint32_t& channelId) override;
+  virtual bool DeallocPSimpleChannelParent(PSimpleChannelParent* parent) override;
+
+  virtual mozilla::ipc::IPCResult RecvPSimpleChannelConstructor(PSimpleChannelParent* aActor,
+                                                              const uint32_t& channelId) override;
+
   virtual PFileChannelParent*
     AllocPFileChannelParent(const uint32_t& channelId) override;
   virtual bool DeallocPFileChannelParent(PFileChannelParent* parent) override;
 
   virtual mozilla::ipc::IPCResult RecvPFileChannelConstructor(PFileChannelParent* aActor,
                                                               const uint32_t& channelId) override;
 
   virtual PRtspControllerParent* AllocPRtspControllerParent() override;
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -15,16 +15,17 @@ include protocol PWebSocket;
 include protocol PWebSocketEventListener;
 include protocol PTCPSocket;
 include protocol PTCPServerSocket;
 include protocol PUDPSocket;
 include protocol PDNSRequest;
 include protocol PChannelDiverter;
 include protocol PFileDescriptorSet;
 include protocol PDataChannel;
+include protocol PSimpleChannel;
 include protocol PTransportProvider;
 include protocol PChildToParentStream; //FIXME: bug #792908
 include protocol PParentToChildStream; //FIXME: bug #792908
 include protocol PStunAddrsRequest;
 include protocol PFileChannel;
 
 include protocol PRtspController;
 include protocol PRtspChannel;
@@ -51,16 +52,17 @@ nested(upto inside_cpow) sync protocol P
   manages PFTPChannel;
   manages PWebSocket;
   manages PWebSocketEventListener;
   manages PTCPSocket;
   manages PTCPServerSocket;
   manages PUDPSocket;
   manages PDNSRequest;
   manages PDataChannel;
+  manages PSimpleChannel;
   manages PFileChannel;
   manages PRtspController;
   manages PRtspChannel;
   manages PChannelDiverter;
   manages PTransportProvider;
   manages PAltDataOutputStream;
   manages PStunAddrsRequest;
 
@@ -99,17 +101,17 @@ parent:
   async CancelHTMLDNSPrefetch(nsString hostname, OriginAttributes originAttributes,
                               uint16_t flags, nsresult reason);
 
   /**
    * channelId is used to establish a connection between redirect channels in
    * the parent and the child when we're redirecting to a data: URI.
    */
   async PDataChannel(uint32_t channelId);
-
+  async PSimpleChannel(uint32_t channelId);
   async PFileChannel(uint32_t channelId);
 
   async PRtspController();
   async PRtspChannel(RtspChannelConnectArgs args);
   async PChannelDiverter(ChannelDiverterArgs channel);
 
   /**
    * These are called from the child with the results of the auth prompt.
new file mode 100644
--- /dev/null
+++ b/netwerk/ipc/PSimpleChannel.ipdl
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+
+/* 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 protocol PNecko;
+include URIParams;
+
+namespace mozilla {
+namespace net {
+
+async protocol PSimpleChannel
+{
+  manager PNecko;
+
+parent:
+  // Note: channels are opened during construction, so no open method here:
+  // see PNecko.ipdl
+  async __delete__();
+};
+
+} // namespace net
+} // namespace mozilla
--- a/netwerk/ipc/moz.build
+++ b/netwerk/ipc/moz.build
@@ -24,16 +24,17 @@ UNIFIED_SOURCES += [
 IPDL_SOURCES = [
     'NeckoChannelParams.ipdlh',
     'PChannelDiverter.ipdl',
     'PDataChannel.ipdl',
     'PFileChannel.ipdl',
     'PNecko.ipdl',
     'PRtspChannel.ipdl',
     'PRtspController.ipdl',
+    'PSimpleChannel.ipdl',
 ]
 
 # needed so --disable-webrtc builds work (yes, a bit messy)
 if not CONFIG['MOZ_WEBRTC']:
   IPDL_SOURCES += [
       '../../media/mtransport/ipc/PStunAddrsRequest.ipdl',
   ]
   EXPORTS.mozilla.net += [
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -826,17 +826,23 @@ HttpObserverManager = {
     }
 
     return Object.assign(data, extraData);
   },
 
   canModify(channel) {
     let {isHostPermitted} = AddonManagerPermissions;
 
-    if (isHostPermitted(channel.URI.host)) {
+    try {
+      // Bug 1334550 introduced the possibility of having a JAR uri here,
+      // break out if that is the case.
+      channel.QueryInterface(Ci.nsIJARChannel);
+      return false;
+    } catch (e) {}
+    if (channel.URI && isHostPermitted(channel.URI.host)) {
       return false;
     }
 
     let {loadInfo} = channel;
     if (loadInfo && loadInfo.loadingPrincipal) {
       let {loadingPrincipal} = loadInfo;
 
       return loadingPrincipal.URI && !isHostPermitted(loadingPrincipal.URI.host);
@@ -1050,18 +1056,21 @@ HttpObserverManager = {
 
     if (!channelData.hasAuthRequestor && this.shouldHookListener(this.listeners.authRequired, channel)) {
       channel.notificationCallbacks = new AuthRequestor(channel, this);
       channelData.hasAuthRequestor = true;
     }
   },
 
   onChannelReplaced(oldChannel, newChannel) {
+    // We want originalURI if available, this will provide a moz-ext rather than
+    // jar or file uri on redirects.
+    let uri = newChannel.originalURI || newChannel.URI;
     this.runChannelListener(oldChannel, this.getLoadContext(oldChannel),
-                            "onRedirect", {redirectUrl: newChannel.URI.spec});
+                            "onRedirect", {redirectUrl: uri.spec});
   },
 
   onStartRequest(channel, loadContext) {
     this.runChannelListener(channel, loadContext, "onStart");
   },
 
   onStopRequest(channel, loadContext) {
     this.runChannelListener(channel, loadContext, "onStop");