diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp
index c9950719f75..be4f97a90e4 100644
--- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp
+++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp
@@ -4418,7 +4418,7 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
if (reefer) {
if (millis == -1) millis = 0;
rv = reefer->RefreshURI(uri, millis,
- PR_FALSE);
+ PR_FALSE, PR_TRUE);
if (NS_FAILED(rv)) return rv;
}
}
diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp
index 37c2ee75d2b..feeb51e4c44 100644
--- a/mozilla/docshell/base/nsDocShell.cpp
+++ b/mozilla/docshell/base/nsDocShell.cpp
@@ -2464,7 +2464,7 @@ NS_IMETHODIMP nsDocShell::ReportScriptError(nsIScriptError *errorObject)
// nsDocShell::nsIRefreshURI
//*****************************************************************************
-NS_IMETHODIMP nsDocShell::RefreshURI(nsIURI *aURI, PRInt32 aDelay, PRBool aRepeat)
+NS_IMETHODIMP nsDocShell::RefreshURI(nsIURI *aURI, PRInt32 aDelay, PRBool aRepeat, PRBool aMetaRefresh)
{
NS_ENSURE_ARG(aURI);
@@ -2477,6 +2477,7 @@ NS_IMETHODIMP nsDocShell::RefreshURI(nsIURI *aURI, PRInt32 aDelay, PRBool aRepea
refreshTimer->mURI = aURI;
refreshTimer->mDelay = aDelay;
refreshTimer->mRepeat = aRepeat;
+ refreshTimer->mMetaRefresh = aMetaRefresh;
if (!mRefreshURIList)
{
@@ -3906,7 +3907,7 @@ nsDocShell::SetupRefreshURI(nsIChannel * aChannel)
NS_NewURI(getter_AddRefs(uri), uriAttrib, baseURI);
}
- RefreshURI (uri, millis, PR_FALSE);
+ RefreshURI (uri, millis, PR_FALSE, PR_TRUE);
}
}
@@ -4486,7 +4487,7 @@ PRBool nsDocShell::IsFrame()
//*** nsRefreshTimer: Object Management
//*****************************************************************************
-nsRefreshTimer::nsRefreshTimer() : mRepeat(PR_FALSE), mDelay(0)
+nsRefreshTimer::nsRefreshTimer() : mRepeat(PR_FALSE), mDelay(0), mMetaRefresh(PR_FALSE)
{
NS_INIT_REFCNT();
}
@@ -4515,13 +4516,31 @@ NS_IMETHODIMP_(void) nsRefreshTimer::Notify(nsITimer *aTimer)
{
NS_ASSERTION(mDocShell, "DocShell is somehow null");
- if(mDocShell)
+ if(mDocShell && aTimer)
{
- nsCOMPtr loadInfo;
- mDocShell->CreateLoadInfo (getter_AddRefs (loadInfo));
-
+ // Get the delay count
+ PRUint32 delay;
+ delay = aTimer->GetDelay();
+ // Get the current uri from the docshell.
+ nsCOMPtr webNav(do_QueryInterface(mDocShell));
+ nsCOMPtr currURI;
+ if (webNav) {
+ webNav->GetCurrentURI(getter_AddRefs(currURI));
+ }
+ nsCOMPtr loadInfo;
+ mDocShell->CreateLoadInfo (getter_AddRefs (loadInfo));
+ /* Check if this refresh causes a redirection
+ * to another site within the threshold time we
+ * have in mind(15000 ms as defined by REFRESH_REDIRECT_TIMER).
+ * If so, pass a REPLACE flag to LoadURI().
+ */
+ PRBool equalUri = PR_FALSE;
+ if (NS_SUCCEEDED(mURI->Equals(currURI, &equalUri)) && (delay <= REFRESH_REDIRECT_TIMER) && (!equalUri) && mMetaRefresh) {
+ loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
+ }
+ else
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
- mDocShell->LoadURI(mURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE);
+ mDocShell->LoadURI(mURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE);
}
/*
diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h
index 1fcee615fda..493487652b7 100644
--- a/mozilla/docshell/base/nsDocShell.h
+++ b/mozilla/docshell/base/nsDocShell.h
@@ -52,6 +52,8 @@
#include "nsString.h"
#define SH_IN_FRAMES 1
+// Threshold value in ms for META refresh based redirects
+#define REFRESH_REDIRECT_TIMER 15000
// Interfaces Needed
#include "nsIDocumentCharsetInfo.h"
@@ -113,6 +115,7 @@ public:
nsCOMPtr mURI;
PRBool mRepeat;
PRInt32 mDelay;
+ PRBool mMetaRefresh;
protected:
virtual ~nsRefreshTimer();
diff --git a/mozilla/dom/src/base/nsLocation.cpp b/mozilla/dom/src/base/nsLocation.cpp
index 6eaac31afee..d9ac65ddd2e 100644
--- a/mozilla/dom/src/base/nsLocation.cpp
+++ b/mozilla/dom/src/base/nsLocation.cpp
@@ -420,8 +420,23 @@ LocationImpl::SetHrefWithBase(const nsAReadableString& aHref,
if(NS_FAILED(rv))
return rv;
-
- if (aReplace) {
+
+ // Check if docshell is currently loading a document.
+ // If so, this request from JS is probably part of a onload
+ // handler or a simple script tag with a
+ // location.href="new location" for redirection.
+ // In such a case, request a replace load, so that
+ // the new url will replace the existing url in SH.
+ // NOTE: this will not be the case if a event handler had a
+ // location.href in it or a JS timer went off well after
+ // the current document is loaded. In such cases, we will
+ // append the new url to SH.
+ // This solution is tricky. Hopefully it isn't going to bite
+ // anywhere else. This is part of solution for bug # 39938
+ PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
+ mDocShell->GetBusyFlags(&busyFlags);
+
+ if (aReplace || (busyFlags & nsIDocShell::BUSY_FLAGS_BUSY)) {
loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
}
diff --git a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp
index c9950719f75..be4f97a90e4 100644
--- a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp
+++ b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp
@@ -4418,7 +4418,7 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
if (reefer) {
if (millis == -1) millis = 0;
rv = reefer->RefreshURI(uri, millis,
- PR_FALSE);
+ PR_FALSE, PR_TRUE);
if (NS_FAILED(rv)) return rv;
}
}
diff --git a/mozilla/webshell/public/nsIRefreshURI.idl b/mozilla/webshell/public/nsIRefreshURI.idl
index 0150bf93266..a00ea621cea 100644
--- a/mozilla/webshell/public/nsIRefreshURI.idl
+++ b/mozilla/webshell/public/nsIRefreshURI.idl
@@ -31,8 +31,9 @@ interface nsIRefreshURI : nsISupports {
* @param uri The uri to refresh.
* @param millis The number of milliseconds to wait.
* @param repeat Do you want the uri to be repeatedly refreshed every millis milliseconds.
+ * @param flag to check if this is for a META refresh
*/
- void refreshURI(in nsIURI aURI, in long aMillis, in boolean aRepeat);
+ void refreshURI(in nsIURI aURI, in long aMillis, in boolean aRepeat, in boolean aMetaRefresh);
/**
* Checks the passed in channel to see if there is a refresh header, if there is,