Bug 1380186 implement SimpleChannel Parent/Child IPC, r=kmag,mayhemer
authorShane Caraveo <scaraveo@mozilla.com>
Thu, 27 Jul 2017 13:34:54 -0700
changeset 371509 21996e01ca43e5505f0d7c2c8a3b0f742da429c6
parent 371508 73f48b4bd6018f6f4c6dea264299861c9bc9a664
child 371510 4d932d0c9a761a09461383776590670207a2dcfb
push id32249
push usercbook@mozilla.com
push dateFri, 28 Jul 2017 13:23:04 +0000
treeherdermozilla-central@09a412e3cc3b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag, mayhemer
bugs1380186
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1380186 implement SimpleChannel Parent/Child IPC, r=kmag,mayhemer 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");