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,