Bug 1164397 - Part 4: Add infromation about whether a channel was redirected to ChannelInfo; r=jdm
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 02 Jun 2015 18:01:26 -0400
changeset 247523 435358bf7c12a323aef04b0605753ec586e1bfe6
parent 247522 24d7d4dfab29e291aed2da8b904b981bc3ac9031
child 247524 095f8f54dcd2a26b9302677d61337f4341a857bb
push id28870
push usercbook@mozilla.com
push dateMon, 08 Jun 2015 09:58:36 +0000
treeherdermozilla-central@4700d1cdf489 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs1164397
milestone41.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 1164397 - Part 4: Add infromation about whether a channel was redirected to ChannelInfo; r=jdm
dom/fetch/ChannelInfo.cpp
dom/fetch/ChannelInfo.h
dom/fetch/ChannelInfo.ipdlh
--- a/dom/fetch/ChannelInfo.cpp
+++ b/dom/fetch/ChannelInfo.cpp
@@ -8,40 +8,58 @@
 #include "nsCOMPtr.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannel.h"
 #include "nsSerializationHelper.h"
 #include "mozilla/net/HttpBaseChannel.h"
 #include "mozilla/ipc/ChannelInfo.h"
 #include "nsIJARChannel.h"
 #include "nsJARChannel.h"
+#include "nsNetUtil.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 void
 ChannelInfo::InitFromChannel(nsIChannel* aChannel)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
 
   nsCOMPtr<nsISupports> securityInfo;
   aChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
   if (securityInfo) {
     SetSecurityInfo(securityInfo);
   }
 
+  nsLoadFlags loadFlags = 0;
+  aChannel->GetLoadFlags(&loadFlags);
+  mRedirected = (loadFlags & nsIChannel::LOAD_REPLACE);
+  if (mRedirected) {
+    // Save the spec and not the nsIURI object itself, since those objects are
+    // not thread-safe, and releasing them somewhere other than the main thread
+    // is not possible.
+    nsCOMPtr<nsIURI> redirectedURI;
+    aChannel->GetURI(getter_AddRefs(redirectedURI));
+    if (redirectedURI) {
+      redirectedURI->GetSpec(mRedirectedURISpec);
+    }
+  }
+
   mInited = true;
 }
 
 void
 ChannelInfo::InitFromIPCChannelInfo(const ipc::IPCChannelInfo& aChannelInfo)
 {
   MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
 
   mSecurityInfo = aChannelInfo.securityInfo();
+  mRedirectedURISpec = aChannelInfo.redirectedURI();
+  mRedirected = aChannelInfo.redirected();
 
   mInited = true;
 }
 
 void
 ChannelInfo::SetSecurityInfo(nsISupports* aSecurityInfo)
 {
   MOZ_ASSERT(mSecurityInfo.IsEmpty(), "security info should only be set once");
@@ -51,53 +69,83 @@ ChannelInfo::SetSecurityInfo(nsISupports
     return;
   }
   NS_SerializeToString(serializable, mSecurityInfo);
 }
 
 nsresult
 ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mInited);
 
+  // These pointers may be null at this point.  They must be checked before
+  // being dereferenced.
+  nsCOMPtr<nsIHttpChannel> httpChannel =
+    do_QueryInterface(aChannel);
+  nsCOMPtr<nsIJARChannel> jarChannel =
+    do_QueryInterface(aChannel);
+
   if (!mSecurityInfo.IsEmpty()) {
     nsCOMPtr<nsISupports> infoObj;
     nsresult rv = NS_DeserializeObject(mSecurityInfo, getter_AddRefs(infoObj));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
-    nsCOMPtr<nsIHttpChannel> httpChannel =
-      do_QueryInterface(aChannel);
     if (httpChannel) {
       net::HttpBaseChannel* httpBaseChannel =
         static_cast<net::HttpBaseChannel*>(httpChannel.get());
       rv = httpBaseChannel->OverrideSecurityInfo(infoObj);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     } else {
-      nsCOMPtr<nsIJARChannel> jarChannel =
-        do_QueryInterface(aChannel);
       if (NS_WARN_IF(!jarChannel)) {
         return NS_ERROR_FAILURE;
       }
       static_cast<nsJARChannel*>(jarChannel.get())->
         OverrideSecurityInfo(infoObj);
     }
   }
 
+  if (mRedirected) {
+    nsLoadFlags flags = 0;
+    aChannel->GetLoadFlags(&flags);
+    flags |= nsIChannel::LOAD_REPLACE;
+    aChannel->SetLoadFlags(flags);
+
+    nsCOMPtr<nsIURI> redirectedURI;
+    nsresult rv = NS_NewURI(getter_AddRefs(redirectedURI),
+                            mRedirectedURISpec);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    if (httpChannel) {
+      net::HttpBaseChannel* httpBaseChannel =
+        static_cast<net::HttpBaseChannel*>(httpChannel.get());
+      httpBaseChannel->OverrideURI(redirectedURI);
+    } else {
+      if (NS_WARN_IF(!jarChannel)) {
+        return NS_ERROR_FAILURE;
+      }
+      static_cast<nsJARChannel*>(jarChannel.get())->OverrideURI(redirectedURI);
+    }
+  }
+
   return NS_OK;
 }
 
 ipc::IPCChannelInfo
 ChannelInfo::AsIPCChannelInfo() const
 {
   // This may be called when mInited is false, for example if we try to store
   // a synthesized Response object into the Cache.  Uninitialized and empty
   // ChannelInfo objects are indistinguishable at the IPC level, so this is
   // fine.
 
   IPCChannelInfo ipcInfo;
 
   ipcInfo.securityInfo() = mSecurityInfo;
+  ipcInfo.redirectedURI() = mRedirectedURISpec;
+  ipcInfo.redirected() = mRedirected;
 
   return ipcInfo;
 }
--- a/dom/fetch/ChannelInfo.h
+++ b/dom/fetch/ChannelInfo.h
@@ -3,18 +3,20 @@
 /* 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 mozilla_dom_ChannelInfo_h
 #define mozilla_dom_ChannelInfo_h
 
 #include "nsString.h"
+#include "nsCOMPtr.h"
 
 class nsIChannel;
+class nsIURI;
 
 namespace mozilla {
 namespace ipc {
 class IPCChannelInfo;
 } // namespace ipc
 
 namespace dom {
 
@@ -37,30 +39,35 @@ namespace dom {
 // initialized.  There are assertions ensuring these invariants.
 class ChannelInfo final
 {
 public:
   typedef mozilla::ipc::IPCChannelInfo IPCChannelInfo;
 
   ChannelInfo()
     : mInited(false)
+    , mRedirected(false)
   {
   }
 
   ChannelInfo(const ChannelInfo& aRHS)
     : mSecurityInfo(aRHS.mSecurityInfo)
+    , mRedirectedURISpec(aRHS.mRedirectedURISpec)
     , mInited(aRHS.mInited)
+    , mRedirected(aRHS.mRedirected)
   {
   }
 
   ChannelInfo&
   operator=(const ChannelInfo& aRHS)
   {
     mSecurityInfo = aRHS.mSecurityInfo;
+    mRedirectedURISpec = aRHS.mRedirectedURISpec;
     mInited = aRHS.mInited;
+    mRedirected = aRHS.mRedirected;
     return *this;
   }
 
   void InitFromChannel(nsIChannel* aChannel);
   void InitFromIPCChannelInfo(const IPCChannelInfo& aChannelInfo);
 
   // This restores every possible information stored from a previous channel
   // object on a new one.
@@ -73,15 +80,17 @@ public:
 
   IPCChannelInfo AsIPCChannelInfo() const;
 
 private:
   void SetSecurityInfo(nsISupports* aSecurityInfo);
 
 private:
   nsCString mSecurityInfo;
+  nsCString mRedirectedURISpec;
   bool mInited;
+  bool mRedirected;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ChannelInfo_h
--- a/dom/fetch/ChannelInfo.ipdlh
+++ b/dom/fetch/ChannelInfo.ipdlh
@@ -3,12 +3,14 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 namespace mozilla {
 namespace ipc {
 
 struct IPCChannelInfo
 {
   nsCString securityInfo;
+  nsCString redirectedURI;
+  bool redirected;
 };
 
 } // namespace ipc
 } // namespace mozilla