Backed out changeset 00312b136937 (bug 968273) for causing regressions
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 28 Jun 2016 10:03:25 +0200
changeset 302762 d87b76177b2f5cf0839d73becebb614ab8a9ef7f
parent 302761 2ab57664bf7cafdd64e136e341527c275fc8c3aa
child 302763 cf243ad179e9929358583f4b8e6f8ce709f85eb6
push id19791
push usercbook@mozilla.com
push dateTue, 28 Jun 2016 14:15:17 +0000
treeherderfx-team@e774866bf8a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs968273
milestone50.0a1
backs out00312b13693766054d261b987391f7bb6b0fe9a5
Backed out changeset 00312b136937 (bug 968273) for causing regressions
browser/components/sessionstore/SessionHistory.jsm
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsDocShellLoadInfo.cpp
docshell/base/nsDocShellLoadInfo.h
docshell/base/nsIDocShell.idl
docshell/base/nsIDocShellLoadInfo.idl
docshell/shistory/nsISHEntry.idl
docshell/shistory/nsSHEntry.cpp
docshell/shistory/nsSHEntry.h
docshell/shistory/nsSHistory.cpp
docshell/test/bug968273_new.html
docshell/test/bug968273_redirect.html
docshell/test/bug968273_redirect.html^headers^
docshell/test/file_bug968273.html
docshell/test/mochitest.ini
docshell/test/test_bug968273.html
mobile/android/components/SessionStore.js
--- a/browser/components/sessionstore/SessionHistory.jsm
+++ b/browser/components/sessionstore/SessionHistory.jsm
@@ -140,16 +140,20 @@ var SessionHistoryInternal = {
       entry.referrer = shEntry.referrerURI.spec;
       entry.referrerPolicy = shEntry.referrerPolicy;
     }
 
     if (shEntry.originalURI) {
       entry.originalURI = shEntry.originalURI.spec;
     }
 
+    if (shEntry.loadReplace) {
+      entry.loadReplace = shEntry.loadReplace;
+    }
+
     if (shEntry.srcdocData)
       entry.srcdocData = shEntry.srcdocData;
 
     if (shEntry.isSrcdocEntry)
       entry.isSrcdocEntry = shEntry.isSrcdocEntry;
 
     if (shEntry.baseURI)
       entry.baseURI = shEntry.baseURI.spec;
@@ -306,16 +310,19 @@ var SessionHistoryInternal = {
       shEntry.contentType = entry.contentType;
     if (entry.referrer) {
       shEntry.referrerURI = Utils.makeURI(entry.referrer);
       shEntry.referrerPolicy = entry.referrerPolicy;
     }
     if (entry.originalURI) {
       shEntry.originalURI = Utils.makeURI(entry.originalURI);
     }
+    if (entry.loadReplace) {
+      shEntry.loadReplace = entry.loadReplace;
+    }
     if (entry.isSrcdocEntry)
       shEntry.srcdocData = entry.srcdocData;
     if (entry.baseURI)
       shEntry.baseURI = Utils.makeURI(entry.baseURI);
 
     if (entry.cacheKey) {
       var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
                      createInstance(Ci.nsISupportsPRUint32);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1250,16 +1250,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
   }
 
   if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> referrer;
   nsCOMPtr<nsIURI> originalURI;
+  bool loadReplace = false;
   nsCOMPtr<nsIInputStream> postStream;
   nsCOMPtr<nsIInputStream> headersStream;
   nsCOMPtr<nsISupports> owner;
   bool inheritOwner = false;
   bool ownerIsExplicit = false;
   bool sendReferrer = true;
   uint32_t referrerPolicy = mozilla::net::RP_Default;
   bool isSrcdoc = false;
@@ -1277,16 +1278,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
       mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
     StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
   }
 
   // Extract the info from the DocShellLoadInfo struct...
   if (aLoadInfo) {
     aLoadInfo->GetReferrer(getter_AddRefs(referrer));
     aLoadInfo->GetOriginalURI(getter_AddRefs(originalURI));
+    aLoadInfo->GetLoadReplace(&loadReplace);
     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
     aLoadInfo->GetLoadType(&lt);
     // Get the appropriate loadType from nsIDocShellLoadInfo type
     loadType = ConvertDocShellLoadInfoToLoadType(lt);
 
     aLoadInfo->GetOwner(getter_AddRefs(owner));
     aLoadInfo->GetInheritOwner(&inheritOwner);
     aLoadInfo->GetOwnerIsExplicit(&ownerIsExplicit);
@@ -1536,16 +1538,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
   }
 
   if (isSrcdoc) {
     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
   }
 
   return InternalLoad(aURI,
                       originalURI,
+                      loadReplace,
                       referrer,
                       referrerPolicy,
                       owner,
                       flags,
                       target.get(),
                       nullptr,      // No type hint
                       NullString(), // No forced download
                       postStream,
@@ -5310,17 +5313,17 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
   // end of the URL, so append it last.
   errorPageUrl.AppendLiteral("&d=");
   errorPageUrl.AppendASCII(escapedDescription.get());
 
   nsCOMPtr<nsIURI> errorPageURI;
   rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return InternalLoad(errorPageURI, nullptr, nullptr,
+  return InternalLoad(errorPageURI, nullptr, false, nullptr,
                       mozilla::net::RP_Default,
                       nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
                       nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
                       nullptr, true, NullString(), this, nullptr, nullptr,
                       nullptr);
 }
 
 NS_IMETHODIMP
@@ -5362,36 +5365,41 @@ nsDocShell::Reload(uint32_t aReloadFlags
 
     // Do not inherit owner from document
     uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
     nsAutoString srcdoc;
     nsIPrincipal* principal = nullptr;
     nsAutoString contentTypeHint;
     nsCOMPtr<nsIURI> baseURI;
     nsCOMPtr<nsIURI> originalURI;
+    bool loadReplace = false;
     if (doc) {
       principal = doc->NodePrincipal();
       doc->GetContentType(contentTypeHint);
 
       if (doc->IsSrcdocDocument()) {
         doc->GetSrcdocData(srcdoc);
         flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
         baseURI = doc->GetBaseURI();
       }
       nsCOMPtr<nsIChannel> chan = doc->GetChannel();
       if (chan) {
+        uint32_t loadFlags;
+        chan->GetLoadFlags(&loadFlags);
+        loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
         nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
         if (httpChan) {
           httpChan->GetOriginalURI(getter_AddRefs(originalURI));
         }
       }
     }
 
     rv = InternalLoad(mCurrentURI,
                       originalURI,
+                      loadReplace,
                       mReferrerURI,
                       mReferrerPolicy,
                       principal,
                       flags,
                       nullptr,         // No window target
                       NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
                       NullString(),    // No forced download
                       nullptr,         // No post data
@@ -9532,28 +9540,29 @@ nsDocShell::CopyFavicon(nsIURI* aOldURI,
   }
 #endif
 }
 
 class InternalLoadEvent : public Runnable
 {
 public:
   InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
-                    nsIURI* aOriginalURI,
+                    nsIURI* aOriginalURI, bool aLoadReplace,
                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
                     nsISupports* aOwner, uint32_t aFlags,
                     const char* aTypeHint, nsIInputStream* aPostData,
                     nsIInputStream* aHeadersData, uint32_t aLoadType,
                     nsISHEntry* aSHEntry, bool aFirstParty,
                     const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
                     nsIURI* aBaseURI)
     : mSrcdoc(aSrcdoc)
     , mDocShell(aDocShell)
     , mURI(aURI)
     , mOriginalURI(aOriginalURI)
+    , mLoadReplace(aLoadReplace)
     , mReferrer(aReferrer)
     , mReferrerPolicy(aReferrerPolicy)
     , mOwner(aOwner)
     , mPostData(aPostData)
     , mHeadersData(aHeadersData)
     , mSHEntry(aSHEntry)
     , mFlags(aFlags)
     , mLoadType(aLoadType)
@@ -9566,16 +9575,17 @@ public:
       mTypeHint = aTypeHint;
     }
   }
 
   NS_IMETHOD
   Run()
   {
     return mDocShell->InternalLoad(mURI, mOriginalURI,
+                                   mLoadReplace,
                                    mReferrer,
                                    mReferrerPolicy,
                                    mOwner, mFlags,
                                    nullptr, mTypeHint.get(),
                                    NullString(), mPostData, mHeadersData,
                                    mLoadType, mSHEntry, mFirstParty,
                                    mSrcdoc, mSourceDocShell, mBaseURI,
                                    nullptr, nullptr);
@@ -9585,16 +9595,17 @@ private:
   // Use IDL strings so .get() returns null by default
   nsXPIDLString mWindowTarget;
   nsXPIDLCString mTypeHint;
   nsString mSrcdoc;
 
   RefPtr<nsDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIURI> mOriginalURI;
+  bool mLoadReplace;
   nsCOMPtr<nsIURI> mReferrer;
   uint32_t mReferrerPolicy;
   nsCOMPtr<nsISupports> mOwner;
   nsCOMPtr<nsIInputStream> mPostData;
   nsCOMPtr<nsIInputStream> mHeadersData;
   nsCOMPtr<nsISHEntry> mSHEntry;
   uint32_t mFlags;
   uint32_t mLoadType;
@@ -9651,16 +9662,17 @@ nsDocShell::IsAboutNewtab(nsIURI* aURI)
     return false;
   }
   return module.Equals("newtab");
 }
 
 NS_IMETHODIMP
 nsDocShell::InternalLoad(nsIURI* aURI,
                          nsIURI* aOriginalURI,
+                         bool aLoadReplace,
                          nsIURI* aReferrer,
                          uint32_t aReferrerPolicy,
                          nsISupports* aOwner,
                          uint32_t aFlags,
                          const char16_t* aWindowTarget,
                          const char* aTypeHint,
                          const nsAString& aFileName,
                          nsIInputStream* aPostData,
@@ -9914,16 +9926,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
 
     //
     // Transfer the load to the target DocShell...  Pass nullptr as the
     // window target name from to prevent recursive retargeting!
     //
     if (NS_SUCCEEDED(rv) && targetDocShell) {
       rv = targetDocShell->InternalLoad(aURI,
                                         aOriginalURI,
+                                        aLoadReplace,
                                         aReferrer,
                                         aReferrerPolicy,
                                         owner,
                                         aFlags,
                                         nullptr,         // No window target
                                         aTypeHint,
                                         NullString(),    // No forced download
                                         aPostData,
@@ -9994,17 +10007,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
       // the unload event also a replace load, so we don't
       // create extra history entries.
       if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
         mLoadType = LOAD_NORMAL_REPLACE;
       }
 
       // Do this asynchronously
       nsCOMPtr<nsIRunnable> ev =
-        new InternalLoadEvent(this, aURI, aOriginalURI,
+        new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
                               aReferrer, aReferrerPolicy, aOwner, aFlags,
                               aTypeHint, aPostData, aHeadersData,
                               aLoadType, aSHEntry, aFirstParty, aSrcdoc,
                               aSourceDocShell, aBaseURI);
       return NS_DispatchToCurrentThread(ev);
     }
 
     // Just ignore this load attempt
@@ -10511,20 +10524,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
   }
 
   net::PredictorLearn(aURI, nullptr,
                       nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, this);
   net::PredictorPredict(aURI, nullptr,
                         nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
 
   nsCOMPtr<nsIRequest> req;
-  // At this point we will open a new channel to load data. If aOriginalURI
-  // is present, we load aOriginalURI instead of aURI because we want to load
-  // all redirects again.
-  rv = DoURILoad(aOriginalURI ? aOriginalURI : aURI, aReferrer,
+  rv = DoURILoad(aURI, aOriginalURI, aLoadReplace, aReferrer,
                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
                  aReferrerPolicy,
                  owner, aTypeHint, aFileName, aPostData, aHeadersData,
                  aFirstParty, aDocShell, getter_AddRefs(req),
                  (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
                  (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
                  (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
                  srcdoc, aBaseURI, contentType);
@@ -10591,16 +10601,18 @@ nsDocShell::GetInheritedPrincipal(bool a
     return docPrincipal;
   }
 
   return nullptr;
 }
 
 nsresult
 nsDocShell::DoURILoad(nsIURI* aURI,
+                      nsIURI* aOriginalURI,
+                      bool aLoadReplace,
                       nsIURI* aReferrerURI,
                       bool aSendReferrer,
                       uint32_t aReferrerPolicy,
                       nsISupports* aOwner,
                       const char* aTypeHint,
                       const nsAString& aFileName,
                       nsIInputStream* aPostData,
                       nsIInputStream* aHeadersData,
@@ -10866,17 +10878,27 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   }
 
   // Make sure to give the caller a channel if we managed to create one
   // This is important for correct error page/session history interaction
   if (aRequest) {
     NS_ADDREF(*aRequest = channel);
   }
 
-  channel->SetOriginalURI(aURI);
+  if (aOriginalURI) {
+    channel->SetOriginalURI(aOriginalURI);
+    if (aLoadReplace) {
+      uint32_t loadFlags;
+      channel->GetLoadFlags(&loadFlags);
+      NS_ENSURE_SUCCESS(rv, rv);
+      channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
+    }
+  } else {
+    channel->SetOriginalURI(aURI);
+  }
 
   if (aTypeHint && *aTypeHint) {
     channel->SetContentType(nsDependentCString(aTypeHint));
     mContentTypeHint = aTypeHint;
   } else {
     mContentTypeHint.Truncate();
   }
 
@@ -11003,18 +11025,18 @@ nsDocShell::DoURILoad(nsIURI* aURI,
       rv = AddHeadersToChannel(aHeadersData, httpChannel);
     }
     // Set the referrer explicitly
     if (aReferrerURI && aSendReferrer) {
       // Referrer is currenly only set for link clicks here.
       httpChannel->SetReferrerWithPolicy(aReferrerURI, aReferrerPolicy);
     }
     // set Content-Signature enforcing bit if aOriginalURI == about:newtab
-    if (httpChannel) {
-      if (IsAboutNewtab(aURI)) {
+    if (aOriginalURI && httpChannel) {
+      if (IsAboutNewtab(aOriginalURI)) {
         nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->GetLoadInfo();
         if (loadInfo) {
           loadInfo->SetVerifySignedContent(true);
         }
       }
     }
   }
 
@@ -11868,16 +11890,17 @@ nsDocShell::AddState(JS::Handle<JS::Valu
     // AddToSessionHistory may not modify mOSHE.  In case it doesn't,
     // we'll just set mOSHE here.
     mOSHE = newSHEntry;
 
   } else {
     newSHEntry = mOSHE;
     newSHEntry->SetURI(newURI);
     newSHEntry->SetOriginalURI(newURI);
+    newSHEntry->SetLoadReplace(false);
   }
 
   // Step 4: Modify new/original session history entry and clear its POST
   // data, if there is any.
   newSHEntry->SetStateData(scContainer);
   newSHEntry->SetPostData(nullptr);
 
   // If this push/replaceState changed the document's current URI and the new
@@ -12078,16 +12101,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
     if (!entry) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // Get the post data & referrer
   nsCOMPtr<nsIInputStream> inputStream;
   nsCOMPtr<nsIURI> originalURI;
+  bool loadReplace = false;
   nsCOMPtr<nsIURI> referrerURI;
   uint32_t referrerPolicy = mozilla::net::RP_Default;
   nsCOMPtr<nsISupports> cacheKey;
   nsCOMPtr<nsISupports> owner = aOwner;
   bool expired = false;
   bool discardLayoutState = false;
   nsCOMPtr<nsICacheInfoChannel> cacheChannel;
   if (aChannel) {
@@ -12108,16 +12132,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
     if (httpChannel) {
       nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
       if (uploadChannel) {
         uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
       }
       httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
       uint32_t loadFlags;
       aChannel->GetLoadFlags(&loadFlags);
+      loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
       httpChannel->GetReferrer(getter_AddRefs(referrerURI));
       httpChannel->GetReferrerPolicy(&referrerPolicy);
 
       discardLayoutState = ShouldDiscardLayoutState(httpChannel);
     }
     aChannel->GetOwner(getter_AddRefs(owner));
     if (!owner) {
       nsCOMPtr<nsILoadInfo> loadInfo;
@@ -12151,16 +12176,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
                 nullptr,           // LayoutHistory state
                 cacheKey,          // CacheKey
                 mContentTypeHint,  // Content-type
                 owner,             // Channel or provided owner
                 mHistoryID,
                 mDynamicallyCreated);
 
   entry->SetOriginalURI(originalURI);
+  entry->SetLoadReplace(loadReplace);
   entry->SetReferrerURI(referrerURI);
   entry->SetReferrerPolicy(referrerPolicy);
   nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
   if (inStrmChan) {
     bool isSrcdocChannel;
     inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
     if (isSrcdocChannel) {
       nsAutoString srcdoc;
@@ -12250,27 +12276,30 @@ nsresult
 nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
 {
   if (!IsNavigationAllowed()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> uri;
   nsCOMPtr<nsIURI> originalURI;
+  bool loadReplace = false;
   nsCOMPtr<nsIInputStream> postData;
   nsCOMPtr<nsIURI> referrerURI;
   uint32_t referrerPolicy;
   nsAutoCString contentType;
   nsCOMPtr<nsISupports> owner;
 
   NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
 
   NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(aEntry->GetOriginalURI(getter_AddRefs(originalURI)),
                     NS_ERROR_FAILURE);
+  NS_ENSURE_SUCCESS(aEntry->GetLoadReplace(&loadReplace),
+                    NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
                     NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy),
                     NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
                     NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE);
   NS_ENSURE_SUCCESS(aEntry->GetOwner(getter_AddRefs(owner)), NS_ERROR_FAILURE);
@@ -12341,16 +12370,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
   }
 
   // Passing nullptr as aSourceDocShell gives the same behaviour as before
   // aSourceDocShell was introduced. According to spec we should be passing
   // the source browsing context that was used when the history entry was
   // first created. bug 947716 has been created to address this issue.
   rv = InternalLoad(uri,
                     originalURI,
+                    loadReplace,
                     referrerURI,
                     referrerPolicy,
                     owner,
                     flags,
                     nullptr,            // No window target
                     contentType.get(),  // Type hint
                     NullString(),       // No forced file download
                     postData,           // Post data stream
@@ -13842,16 +13872,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
   nsCOMPtr<nsIURI> clonedURI;
   aURI->Clone(getter_AddRefs(clonedURI));
   if (!clonedURI) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv = InternalLoad(clonedURI,                 // New URI
                              nullptr,                   // Original URI
+                             false,                     // LoadReplace
                              referer,                   // Referer URI
                              refererPolicy,             // Referer policy
                              aContent->NodePrincipal(), // Owner is our node's
                                                         // principal
                              flags,
                              target.get(),              // Window target
                              NS_LossyConvertUTF16toASCII(typeHint).get(),
                              aFileName,                 // Download as file
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -348,17 +348,22 @@ protected:
   // at the parent.
   nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
 
   // Actually open a channel and perform a URI load. Note: whatever owner is
   // passed to this function will be set on the channel. Callers who wish to
   // not have an owner on the channel should just pass null.
   // If aSrcdoc is not void, the load will be considered as a srcdoc load,
   // and the contents of aSrcdoc will be loaded instead of aURI.
+  // aOriginalURI will be set as the originalURI on the channel that does the
+  // load. If aOriginalURI is null, aURI will be set as the originalURI.
+  // If aLoadReplace is true, OLOAD_REPLACE flag will be set to the nsIChannel.
   nsresult DoURILoad(nsIURI* aURI,
+                     nsIURI* aOriginalURI,
+                     bool aLoadReplace,
                      nsIURI* aReferrer,
                      bool aSendReferrer,
                      uint32_t aReferrerPolicy,
                      nsISupports* aOwner,
                      const char* aTypeHint,
                      const nsAString& aFileName,
                      nsIInputStream* aPostData,
                      nsIInputStream* aHeadersData,
--- a/docshell/base/nsDocShellLoadInfo.cpp
+++ b/docshell/base/nsDocShellLoadInfo.cpp
@@ -7,17 +7,18 @@
 #include "nsDocShellLoadInfo.h"
 #include "nsISHEntry.h"
 #include "nsIInputStream.h"
 #include "nsIURI.h"
 #include "nsIDocShell.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 nsDocShellLoadInfo::nsDocShellLoadInfo()
-  : mInheritOwner(false)
+  : mLoadReplace(false)
+  , mInheritOwner(false)
   , mOwnerIsExplicit(false)
   , mSendReferrer(true)
   , mReferrerPolicy(mozilla::net::RP_Default)
   , mLoadType(nsIDocShellLoadInfo::loadNormal)
   , mIsSrcdocLoad(false)
 {
 }
 
@@ -63,16 +64,30 @@ nsDocShellLoadInfo::GetOriginalURI(nsIUR
 NS_IMETHODIMP
 nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI)
 {
   mOriginalURI = aOriginalURI;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocShellLoadInfo::GetLoadReplace(bool* aLoadReplace)
+{
+  *aLoadReplace = mLoadReplace;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShellLoadInfo::SetLoadReplace(bool aLoadReplace)
+{
+  mLoadReplace = aLoadReplace;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShellLoadInfo::GetOwner(nsISupports** aOwner)
 {
   NS_ENSURE_ARG_POINTER(aOwner);
 
   *aOwner = mOwner;
   NS_IF_ADDREF(*aOwner);
   return NS_OK;
 }
--- a/docshell/base/nsDocShellLoadInfo.h
+++ b/docshell/base/nsDocShellLoadInfo.h
@@ -29,16 +29,17 @@ public:
 
 protected:
   virtual ~nsDocShellLoadInfo();
 
 protected:
   nsCOMPtr<nsIURI> mReferrer;
   nsCOMPtr<nsIURI> mOriginalURI;
   nsCOMPtr<nsISupports> mOwner;
+  bool mLoadReplace;
   bool mInheritOwner;
   bool mOwnerIsExplicit;
   bool mSendReferrer;
   nsDocShellInfoReferrerPolicy mReferrerPolicy;
   nsDocShellInfoLoadType mLoadType;
   nsCOMPtr<nsISHEntry> mSHEntry;
   nsString mTarget;
   nsCOMPtr<nsIInputStream> mPostDataStream;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -121,21 +121,22 @@ interface nsIDocShell : nsIDocShellTreeI
   // NB: 0x80 is available.
 
   /**
    * Loads the given URI.  This method is identical to loadURI(...) except
    * that its parameter list is broken out instead of being packaged inside
    * of an nsIDocShellLoadInfo object...
    *
    * @param aURI            - The URI to load.
-   * @param aOriginalURI    - If aOriginalURI is present and this function ends
-   *                          up actually loading data from network or cache,
-   *                          but not from bfcache, (e.g. in case of a reload)
-   *                          aOriginalURI will be loaded instead of aURI.
-   *                          Thereby we will load all redirects again.
+   * @param aOriginalURI    - The URI to set as the originalURI on the channel
+   *                          that does the load. If null, aURI will be set as
+   *                          the originalURI.
+   * @param aLoadReplace    - If set LOAD_REPLACE flag will be set on the
+   *                          channel. aOriginalURI is null, this argument is
+   *                          ignored.
    * @param aReferrer       - Referring URI
    * @param aReferrerPolicy - Referrer policy
    * @param aOwner          - Owner (security principal)
    * @param aInheritOwner   - Flag indicating whether the owner of the current
    *                          document should be inherited if aOwner is null.
    * @param aStopActiveDoc  - Flag indicating whether loading the current
    *                          document should be stopped.
    * @param aWindowTarget   - Window target for the load.
@@ -153,16 +154,17 @@ interface nsIDocShell : nsIDocShellTreeI
    *                          of aURI.
    * @param aSourceDocShell - The source browsing context for the navigation.
    * @param aBaseURI        - The base URI to be used for the load.  Set in
    *                          srcdoc loads as it cannot otherwise be inferred
    *                          in certain situations such as view-source.
    */
   [noscript]void internalLoad(in nsIURI aURI,
                               in nsIURI aOriginalURI,
+                              in boolean aLoadReplace,
                               in nsIURI aReferrer,
                               in unsigned long aReferrerPolicy,
                               in nsISupports aOwner,
                               in uint32_t aFlags,
                               in wstring aWindowTarget,
                               in string aTypeHint,
                               in AString aFileName,
                               in nsIInputStream aPostDataStream,
--- a/docshell/base/nsIDocShellLoadInfo.idl
+++ b/docshell/base/nsIDocShellLoadInfo.idl
@@ -25,16 +25,21 @@ interface nsIDocShellLoadInfo : nsISuppo
     /** This is the referrer for the load. */
     attribute nsIURI referrer;
 
     /**
      * The originalURI to be passed to nsIDocShell.internalLoad. May be null.
      */
     attribute nsIURI originalURI;
 
+    /**
+     * loadReplace flag to be passed to nsIDocShell.internalLoad.
+     */
+    attribute boolean loadReplace;
+
     /** The owner of the load, that is, the entity responsible for 
      *  causing the load to occur. This should be a nsIPrincipal typically.
      */
     attribute nsISupports owner;
 
     /** If this attribute is true and no owner is specified, copy
      *  the owner from the referring document.
      */
--- a/docshell/shistory/nsISHEntry.idl
+++ b/docshell/shistory/nsISHEntry.idl
@@ -43,16 +43,21 @@ interface nsISHEntry : nsISupports
     /**
      * A readonly property that returns the original URI of the current entry.
      * If an entry is the result of a redirect this attribute holds original
      * URI. The object returned is of type nsIURI
      */
     attribute nsIURI originalURI;
 
     /**
+     *  This flag remembers whether channel has LOAD_REPLACE set.
+     */
+    attribute boolean loadReplace;
+
+    /**
      * A readonly property that returns the title
      * of the current entry.  The object returned
      * is a encoded string
      */
     readonly attribute wstring title;
 
     /**
      * A readonly property that returns a boolean
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -19,32 +19,34 @@
 #include <algorithm>
 
 namespace dom = mozilla::dom;
 
 static uint32_t gEntryID = 0;
 
 nsSHEntry::nsSHEntry()
   : mShared(new nsSHEntryShared())
+  , mLoadReplace(false)
   , mReferrerPolicy(mozilla::net::RP_Default)
   , mLoadType(0)
   , mID(gEntryID++)
   , mScrollPositionX(0)
   , mScrollPositionY(0)
   , mParent(nullptr)
   , mURIWasModified(false)
   , mIsSrcdocEntry(false)
   , mScrollRestorationIsManual(false)
 {
 }
 
 nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
   : mShared(aOther.mShared)
   , mURI(aOther.mURI)
   , mOriginalURI(aOther.mOriginalURI)
+  , mLoadReplace(aOther.mLoadReplace)
   , mReferrerURI(aOther.mReferrerURI)
   , mReferrerPolicy(aOther.mReferrerPolicy)
   , mTitle(aOther.mTitle)
   , mPostData(aOther.mPostData)
   , mLoadType(0)         // XXX why not copy?
   , mID(aOther.mID)
   , mScrollPositionX(0)  // XXX why not copy?
   , mScrollPositionY(0)  // XXX why not copy?
@@ -131,16 +133,30 @@ nsSHEntry::GetOriginalURI(nsIURI** aOrig
 NS_IMETHODIMP
 nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
 {
   mOriginalURI = aOriginalURI;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSHEntry::GetLoadReplace(bool* aLoadReplace)
+{
+  *aLoadReplace = mLoadReplace;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSHEntry::SetLoadReplace(bool aLoadReplace)
+{
+  mLoadReplace = aLoadReplace;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSHEntry::GetReferrerURI(nsIURI** aReferrerURI)
 {
   *aReferrerURI = mReferrerURI;
   NS_IF_ADDREF(*aReferrerURI);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/docshell/shistory/nsSHEntry.h
+++ b/docshell/shistory/nsSHEntry.h
@@ -44,16 +44,17 @@ private:
 
   // We share the state in here with other SHEntries which correspond to the
   // same document.
   RefPtr<nsSHEntryShared> mShared;
 
   // See nsSHEntry.idl for comments on these members.
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIURI> mOriginalURI;
+  bool mLoadReplace;
   nsCOMPtr<nsIURI> mReferrerURI;
   uint32_t mReferrerPolicy;
   nsString mTitle;
   nsCOMPtr<nsIInputStream> mPostData;
   uint32_t mLoadType;
   uint32_t mID;
   int32_t mScrollPositionX;
   int32_t mScrollPositionY;
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -1768,16 +1768,20 @@ nsSHistory::InitiateLoad(nsISHEntry* aFr
 
   loadInfo->SetLoadType(aLoadType);
   loadInfo->SetSHEntry(aFrameEntry);
 
   nsCOMPtr<nsIURI> originalURI;
   aFrameEntry->GetOriginalURI(getter_AddRefs(originalURI));
   loadInfo->SetOriginalURI(originalURI);
 
+  bool loadReplace;
+  aFrameEntry->GetLoadReplace(&loadReplace);
+  loadInfo->SetLoadReplace(loadReplace);
+
   nsCOMPtr<nsIURI> nextURI;
   aFrameEntry->GetURI(getter_AddRefs(nextURI));
   // Time   to initiate a document load
   return aFrameDS->LoadURI(nextURI, loadInfo,
                            nsIWebNavigation::LOAD_FLAGS_NONE, false);
 
 }
 
deleted file mode 100644
--- a/docshell/test/bug968273_new.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body>This is bug968273_new.html.</body></html>
deleted file mode 100644
--- a/docshell/test/bug968273_redirect.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<html><body>This document is redirected to bug968273_new.html.</body></html>
deleted file mode 100644
--- a/docshell/test/bug968273_redirect.html^headers^
+++ /dev/null
@@ -1,2 +0,0 @@
-HTTP 302 Moved Temporarily
-Location: bug968273_new.html
deleted file mode 100644
--- a/docshell/test/file_bug968273.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=968273
-
-If a load has redirects, reloading the page will load the page starting with the original
-URI and do the redirects again.
--->
-<head>
-  <title>Test for Bug 968273</title>
-<script>
-  var SimpleTest = opener.SimpleTest;
-  var ok = opener.ok;
-  var is = opener.is;
-  var doOneReload = true;
-
-  function onLoadCheckFrame() {
-    ok(frames[0].performance, 'Window.performance should be defined');
-    ok(frames[0].performance.navigation, 'Window.performance.navigation should be defined');
-    // do this with a timeout to see the visuals of the navigations.
-    setTimeout("checkFrame();", 200);
-  }
-
-  function checkFrame() {
-    is(frames[0].performance.navigation.redirectCount, 1, "Expected rediect");
-    if (doOneReload == true) {
-      doOneReload = false;
-      // do a reload and check that a redirect is preformed again.
-      frames[0].location.reload();
-    } else {
-      SimpleTest.finish();
-    }
-  }
-
-</script>
-</head>
-<body>
-<div id="frames">
-<iframe name="child0" onload="onLoadCheckFrame();" src="bug968273_redirect.html"></iframe>
-</div>
-</body>
-</html>
--- a/docshell/test/mochitest.ini
+++ b/docshell/test/mochitest.ini
@@ -6,19 +6,16 @@ support-files =
   bug404548-subframe.html
   bug413310-post.sjs
   bug413310-subframe.html
   bug529119-window.html
   bug570341_recordevents.html
   bug668513_redirect.html
   bug668513_redirect.html^headers^
   bug691547_frame.html
-  bug968273_new.html
-  bug968273_redirect.html
-  bug968273_redirect.html^headers^
   file_anchor_scroll_after_document_open.html
   file_bug385434_1.html
   file_bug385434_2.html
   file_bug385434_3.html
   file_bug475636.sjs
   file_bug509055.html
   file_bug540462.html
   file_bug580069_1.html
@@ -30,17 +27,16 @@ support-files =
   file_bug653741.html
   file_bug660404
   file_bug660404^headers^
   file_bug662170.html
   file_bug669671.sjs
   file_bug680257.html
   file_bug703855.html
   file_bug728939.html
-  file_bug968273.html
   file_pushState_after_document_open.html
   historyframes.html
 
 [test_anchor_scroll_after_document_open.html]
 [test_bfcache_plus_hash.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug123696.html]
 [test_bug369814.html]
@@ -107,10 +103,8 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_framedhistoryframes.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #Bug 931116, b2g desktop specific, initial triage, and also bug 784321
 support-files = file_framedhistoryframes.html
 [test_pushState_after_document_open.html]
 [test_windowedhistoryframes.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug1121701.html]
 skip-if = (buildapp == 'b2g' || buildapp == 'mulet')
-[test_bug968273.html]
-skip-if = toolkit == 'android' # The same reason test_bug668513.html is disabled. performance.redirectcount check false on load but it is correct on reload. 
deleted file mode 100644
--- a/docshell/test/test_bug968273.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=968273
-
-If a load has redirects, reloading the page will load the page starting with the original
-URI and do the redirects again.
--->
-<head>
-  <title>Test for Bug 968273</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968273">Mozilla Bug 968273</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-
-<script type='application/javascript'>
-if (navigator.platform.startsWith("Linux")) {
-    SimpleTest.expectAssertions(0, 1);
-}
-
-SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout("We need do this with a timeout to see the visuals of" +
-                               " the performance.navigation");
-window.open("file_bug968273.html");
-</script>
-</pre>
-</body>
-</html>
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -1030,16 +1030,20 @@ SessionStore.prototype = {
     if (aEntry.referrerURI) {
       entry.referrer = aEntry.referrerURI.spec;
     }
 
     if (aEntry.originalURI) {
       entry.originalURI = aEntry.originalURI.spec;
     }
 
+    if (aEntry.loadReplace) {
+      entry.loadReplace = aEntry.loadReplace;
+    }
+
     if (aEntry.contentType) {
       entry.contentType = aEntry.contentType;
     }
 
     if (aEntry.scrollRestorationIsManual) {
       entry.scrollRestorationIsManual = true;
     } else {
       let x = {}, y = {};
@@ -1118,16 +1122,20 @@ SessionStore.prototype = {
     if (aEntry.referrer) {
       shEntry.referrerURI = Services.io.newURI(aEntry.referrer, null, null);
     }
 
     if (aEntry.originalURI) {
       shEntry.originalURI =  Services.io.newURI(aEntry.originalURI, null, null);
     }
 
+    if (aEntry.loadReplace) {
+      shEntry.loadReplace = aEntry.loadReplace;
+    }
+
     if (aEntry.cacheKey) {
       let cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].createInstance(Ci.nsISupportsPRUint32);
       cacheKey.data = aEntry.cacheKey;
       shEntry.cacheKey = cacheKey;
     }
 
     if (aEntry.ID) {
       // get a new unique ID for this frame (since the one from the last