Bug 1380186 implement SimpleChannel Parent/Child IPC, r?mayhemer,kmag draft
authorShane Caraveo <scaraveo@mozilla.com>
Thu, 27 Jul 2017 13:34:54 -0700
changeset 617058 3d8936a316d61e2f6f3bcc343d0e9079f09d54e6
parent 617057 ac9c82f83709cc7b34eb2f5ddbca43da5b5ab51b
child 639683 7ec98ec56764a3457815952f1182ea2be833ba69
push id70908
push usermixedpuppy@gmail.com
push dateThu, 27 Jul 2017 20:36:13 +0000
reviewersmayhemer, kmag
bugs1380186
milestone56.0a1
Bug 1380186 implement SimpleChannel Parent/Child IPC, r?mayhemer,kmag MozReview-Commit-ID: 8zgF2MLwdu2
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,44 @@
 /* -*- 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 "nsBaseChannel.h"
+#include "nsIChannel.h"
+#include "nsIChildChannel.h"
 #include "nsIInputStream.h"
 #include "nsIRequest.h"
-#include "SimpleChannel.h"
+#include "nsISupportsImpl.h"
+#include "nsNetUtil.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 +84,106 @@ SimpleChannel::BeginAsyncRead(nsIStreamL
   mCallbacks = nullptr;
 
   req.forget(request);
   return NS_OK;
 }
 
 #undef TRY_VAR
 
+class SimpleChannelChild final : 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:
+  virtual ~SimpleChannelChild() = default;
+
+  void AddIPDLReference();
+
+  RefPtr<SimpleChannelChild> mIPDLRef;
+};
+
+NS_IMPL_ISUPPORTS_INHERITED(SimpleChannelChild, SimpleChannel, nsIChildChannel)
+
+SimpleChannelChild::SimpleChannelChild(UniquePtr<SimpleChannelCallbacks>&& aCallbacks)
+  : SimpleChannel(Move(aCallbacks))
+  , mIPDLRef(nullptr)
+{
+}
+
+NS_IMETHODIMP
+SimpleChannelChild::ConnectParent(uint32_t aId)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  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.
+  mIPDLRef = this;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+SimpleChannelChild::CompleteRedirectSetup(nsIStreamListener* aListener,
+                                          nsISupports* aContext)
+{
+  if (mIPDLRef) {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  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 (mIPDLRef) {
+    Unused << Send__delete__(this);
+  }
+  return NS_OK;
+}
+
+void
+SimpleChannelChild::ActorDestroy(ActorDestroyReason why)
+{
+  MOZ_ASSERT(mIPDLRef);
+  mIPDLRef = nullptr;
+}
+
+
 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 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,101 @@
+/* -*- 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)
+
+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 aWhy)
+{
+}
+
+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, 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() = default;
+
+  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,39 @@ 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(actor).downcast<SimpleChannelParent>();
+  return true;
+}
+
+mozilla::ipc::IPCResult
+NeckoParent::RecvPSimpleChannelConstructor(PSimpleChannelParent* actor,
+                                           const uint32_t& channelId)
+{
+  SimpleChannelParent* p = static_cast<SimpleChannelParent*>(actor);
+  MOZ_ALWAYS_TRUE(p->Init(channelId));
+  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
@@ -50,16 +50,22 @@ function extractFromChannel(channel, key
   return null;
 }
 
 function getData(channel) {
   const key = "mozilla.webRequest.data";
   return extractFromChannel(channel, key) || attachToChannel(channel, key, {});
 }
 
+function getFinalChannelURI(channel) {
+  let {loadInfo} = channel;
+  // resultPrincipalURI may be null, but originalURI never will be.
+  return (loadInfo && loadInfo.resultPrincipalURI) || channel.originalURI;
+}
+
 var RequestId = {
   count: 1,
   create(channel = null) {
     let id = (this.count++).toString();
     if (channel) {
       getData(channel).requestId = id;
     }
     return id;
@@ -748,19 +754,20 @@ HttpObserverManager = {
       data.suspended = true;
       return true;
     }
   },
 
   getRequestData(channel, loadContext, policyType, extraData) {
     let {loadInfo} = channel;
 
+    let URI = getFinalChannelURI(channel);
     let data = {
       requestId: RequestId.get(channel),
-      url: channel.URI.spec,
+      url: URI.spec,
       method: channel.requestMethod,
       browser: loadContext && loadContext.topFrameElement,
       type: WebRequestCommon.typeForPolicyType(policyType),
       fromCache: getData(channel).fromCache,
       // Defaults for a top level request
       windowId: 0,
       parentWindowId: -1,
     };
@@ -826,17 +833,20 @@ HttpObserverManager = {
     }
 
     return Object.assign(data, extraData);
   },
 
   canModify(channel) {
     let {isHostPermitted} = AddonManagerPermissions;
 
-    if (isHostPermitted(channel.URI.host)) {
+    // Bug 1334550 introduced the possibility of having a JAR uri here,
+    // use the result uri if possible in that case.
+    let URI = getFinalChannelURI(channel);
+    if (URI && isHostPermitted(URI.host)) {
       return false;
     }
 
     let {loadInfo} = channel;
     if (loadInfo && loadInfo.loadingPrincipal) {
       let {loadingPrincipal} = loadInfo;
 
       return loadingPrincipal.URI && !isHostPermitted(loadingPrincipal.URI.host);
@@ -867,17 +877,17 @@ HttpObserverManager = {
       let policyType = (loadInfo ? loadInfo.externalContentPolicyType
                                  : Ci.nsIContentPolicy.TYPE_OTHER);
 
       let includeStatus = (["headersReceived", "authRequired", "onRedirect", "onStart", "onStop"].includes(kind) &&
                            channel instanceof Ci.nsIHttpChannel);
 
       let canModify = this.canModify(channel);
       let commonData = null;
-      let uri = channel.URI;
+      let uri = getFinalChannelURI(channel);
       let requestBody;
       for (let [callback, opts] of this.listeners[kind].entries()) {
         if (!this.shouldRunListener(policyType, uri, opts.filter)) {
           continue;
         }
 
         if (!commonData) {
           commonData = this.getRequestData(channel, loadContext, policyType, extraData);
@@ -1050,18 +1060,20 @@ 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, this will provide a moz-ext rather than jar or file
+    // uri on redirects.
     this.runChannelListener(oldChannel, this.getLoadContext(oldChannel),
-                            "onRedirect", {redirectUrl: newChannel.URI.spec});
+                            "onRedirect", {redirectUrl: newChannel.originalURI.spec});
   },
 
   onStartRequest(channel, loadContext) {
     this.runChannelListener(channel, loadContext, "onStart");
   },
 
   onStopRequest(channel, loadContext) {
     this.runChannelListener(channel, loadContext, "onStop");