Bug 1300464 - Propagate redirecting channel's security information to new HTTP channels when intercepted channels are redirected. r=mayhemer a=gchang
authorJosh Matthews <josh@joshmatthews.net>
Fri, 16 Sep 2016 13:38:07 -0400
changeset 358014 835338db2670383843a0a4daf6aa47bbe46cc22a
parent 358013 8d07760d48b7796553814c336a25317ea57b0f21
child 358015 eab6700676c1f377e51cd18db028e477517053d0
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer, gchang
bugs1300464
milestone51.0a2
Bug 1300464 - Propagate redirecting channel's security information to new HTTP channels when intercepted channels are redirected. r=mayhemer a=gchang
dom/workers/test/serviceworkers/fetch/hsts/realindex.html
dom/workers/test/serviceworkers/test_hsts_upgrade_intercept.html
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
--- a/dom/workers/test/serviceworkers/fetch/hsts/realindex.html
+++ b/dom/workers/test/serviceworkers/fetch/hsts/realindex.html
@@ -1,4 +1,8 @@
 <!DOCTYPE html>
 <script>
-  window.parent.postMessage({status: "protocol", data: location.protocol}, "*");
+  var securityInfoPresent = !!SpecialPowers.wrap(document).docShell.currentDocumentChannel.securityInfo;
+  window.parent.postMessage({status: "protocol",
+                             data: location.protocol,
+                             securityInfoPresent: securityInfoPresent},
+                            "*");
 </script>
--- a/dom/workers/test/serviceworkers/test_hsts_upgrade_intercept.html
+++ b/dom/workers/test/serviceworkers/test_hsts_upgrade_intercept.html
@@ -24,16 +24,17 @@
     iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/register.html";
     window.onmessage = function(e) {
       if (e.data.status == "ok") {
         ok(e.data.result, e.data.message);
       } else if (e.data.status == "registrationdone") {
         iframe.src = "http://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/index.html";
       } else if (e.data.status == "protocol") {
         is(e.data.data, "https:", "Correct protocol expected");
+        ok(e.data.securityInfoPresent, "Security info present on intercepted value");
         switch (++framesLoaded) {
         case 1:
           iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/embedder.html";
           break;
         case 2:
           iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/image.html";
           break;
         }
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -1312,25 +1312,42 @@ HttpChannelChild::BeginNonIPCRedirect(ns
 
   nsCOMPtr<nsIChannel> newChannel;
   nsresult rv = SetupRedirect(responseURI,
                               responseHead,
                               nsIChannelEventSink::REDIRECT_INTERNAL,
                               getter_AddRefs(newChannel));
 
   if (NS_SUCCEEDED(rv)) {
+    // Ensure that the new channel shares the original channel's security information,
+    // since it won't be provided via IPC. In particular, if the target of this redirect
+    // is a synthesized response that has its own security info, the pre-redirect channel
+    // has already received it and it must be propagated to the post-redirect channel.
+    nsCOMPtr<nsIHttpChannelChild> channelChild = do_QueryInterface(newChannel);
+    if (channelChild) {
+      HttpChannelChild* httpChannelChild = static_cast<HttpChannelChild*>(channelChild.get());
+      httpChannelChild->OverrideSecurityInfoForNonIPCRedirect(mSecurityInfo);
+    }
+
     rv = gHttpHandler->AsyncOnChannelRedirect(this,
                                               newChannel,
                                               nsIChannelEventSink::REDIRECT_INTERNAL);
   }
 
   if (NS_FAILED(rv))
     OnRedirectVerifyCallback(rv);
 }
 
+void
+HttpChannelChild::OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo)
+{
+  mResponseCouldBeSynthesized = true;
+  OverrideSecurityInfo(securityInfo);
+}
+
 class Redirect3Event : public ChannelEvent
 {
  public:
   explicit Redirect3Event(HttpChannelChild* child) : mChild(child) {}
   void Run() { mChild->Redirect3Complete(); }
  private:
   HttpChannelChild* mChild;
 };
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -293,16 +293,19 @@ private:
                          const nsHttpResponseHead* responseHead,
                          const uint32_t& redirectFlags,
                          nsIChannel** outChannel);
 
   // Perform a redirection without communicating with the parent process at all.
   void BeginNonIPCRedirect(nsIURI* responseURI,
                            const nsHttpResponseHead* responseHead);
 
+  // Override the default security info pointer during a non-IPC redirection.
+  void OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo);
+
   friend class AssociateApplicationCacheEvent;
   friend class StartRequestEvent;
   friend class StopRequestEvent;
   friend class TransportAndDataEvent;
   friend class MaybeDivertOnDataHttpEvent;
   friend class MaybeDivertOnStopHttpEvent;
   friend class ProgressEvent;
   friend class StatusEvent;