diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index b65c60985de..dc7ddfa13b7 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -1,6 +1,5 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: ft=cpp tw=78 sw=4 et ts=4 sts=4 cin - * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -552,6 +551,7 @@ nsDocShell::ConvertLoadTypeToDocShellLoadInfo(PRUint32 aLoadType) docShellLoadType = nsIDocShellLoadInfo::loadRefresh; break; case LOAD_BYPASS_HISTORY: + case LOAD_ERROR_PAGE: docShellLoadType = nsIDocShellLoadInfo::loadBypassHistory; break; case LOAD_STOP_CONTENT: @@ -664,6 +664,7 @@ nsDocShell::LoadURI(nsIURI * aURI, shEntry = nsnull; } else if ((parentLoadType == LOAD_BYPASS_HISTORY) || + (parentLoadType == LOAD_ERROR_PAGE) || (shEntry && ((parentLoadType & LOAD_CMD_HISTORY) || (parentLoadType == LOAD_RELOAD_NORMAL) || @@ -1334,13 +1335,19 @@ NS_IMETHODIMP nsDocShell::SetCurrentURI(nsIURI *aURI) { SetCurrentURI(aURI, nsnull); - return NS_OK; } void nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest) { + // We don't want to send a location change when we're displaying an error + // page, and we don't want to change our idea of "current URI" either + if (mLoadType == LOAD_ERROR_PAGE) { + return; + } + + mCurrentURI = aURI; //This assignment addrefs PRBool isRoot = PR_FALSE; // Is this the root docshell PRBool isSubFrame = PR_FALSE; // Is this a subframe navigation? @@ -2784,7 +2791,9 @@ nsDocShell::LoadURI(const PRUnichar * aURI, } NS_IMETHODIMP -nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, const PRUnichar *aURL) +nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, + const PRUnichar *aURL, + nsIChannel* aFailedChannel) { // Get prompt and string bundle servcies nsCOMPtr prompter; @@ -2942,7 +2951,8 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, const PRUnichar *aUR NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE); if (mUseErrorPages) { // Display an error page - LoadErrorPage(aURI, aURL, error.get(), messageStr.get()); + LoadErrorPage(aURI, aURL, error.get(), messageStr.get(), + aFailedChannel); } else { @@ -2955,15 +2965,41 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, const PRUnichar *aUR NS_IMETHODIMP -nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL, const PRUnichar *aErrorType, const PRUnichar *aDescription) +nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL, + const PRUnichar *aErrorType, + const PRUnichar *aDescription, + nsIChannel* aFailedChannel) { +#ifdef PR_LOGGING + if (PR_LOG_TEST(gDocShellLog, PR_LOG_DEBUG)) { + nsCAutoString spec; + aURI->GetSpec(spec); + + nsCAutoString chanName; + aFailedChannel->GetName(chanName); + + PR_LOG(gDocShellLog, PR_LOG_DEBUG, + ("nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n", this, + spec.get(), NS_ConvertUTF16toUTF8(aURL).get(), chanName.get())); + } +#endif + // Create an shistory entry for the old load, if we have a channel + if (aFailedChannel) { + mURIResultedInDocument = PR_TRUE; + OnLoadingSite(aFailedChannel); + mOSHE = mLSHE; + } + nsAutoString url; if (aURI) { + // Set our current URI + SetCurrentURI(aURI); + nsCAutoString uri; nsresult rv = aURI->GetSpec(uri); NS_ENSURE_SUCCESS(rv, rv); - url.AssignWithConversion(uri.get()); + CopyUTF8toUTF16(uri, url); } else if (aURL) { @@ -2976,29 +3012,30 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL, const PRUnichar * // Create a URL to pass all the error information through to the page. - char *escapedUrl = nsEscape(NS_ConvertUCS2toUTF8(url.get()).get(), url_Path); - char *escapedError = nsEscape(NS_ConvertUCS2toUTF8(aErrorType).get(), url_Path); - char *escapedDescription = nsEscape(NS_ConvertUCS2toUTF8(aDescription).get(), url_Path); + char *escapedUrl = nsEscape(NS_ConvertUTF16toUTF8(url.get()).get(), url_Path); + char *escapedError = nsEscape(NS_ConvertUTF16toUTF8(aErrorType).get(), url_Path); + char *escapedDescription = nsEscape(NS_ConvertUTF16toUTF8(aDescription).get(), url_Path); - nsAutoString errorType(aErrorType); nsAutoString errorPageUrl; errorPageUrl.AssignLiteral("chrome://global/content/netError.xhtml?e="); - errorPageUrl.AppendWithConversion(escapedError); + errorPageUrl.AppendASCII(escapedError); errorPageUrl.AppendLiteral("&u="); - errorPageUrl.AppendWithConversion(escapedUrl); + errorPageUrl.AppendASCII(escapedUrl); errorPageUrl.AppendLiteral("&d="); - errorPageUrl.AppendWithConversion(escapedDescription); + errorPageUrl.AppendASCII(escapedDescription); PR_FREEIF(escapedDescription); PR_FREEIF(escapedError); PR_FREEIF(escapedUrl); - - return LoadURI(errorPageUrl.get(), // URI string - LOAD_FLAGS_BYPASS_HISTORY, - nsnull, - nsnull, - nsnull); + + nsCOMPtr errorPageURI; + nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); + NS_ENSURE_SUCCESS(rv, rv); + + return InternalLoad(errorPageURI, nsnull, nsnull, PR_TRUE, nsnull, nsnull, + nsnull, nsnull, LOAD_ERROR_PAGE, + nsnull, PR_TRUE, nsnull, nsnull); } @@ -3665,7 +3702,8 @@ nsDocShell::SetTitle(const PRUnichar * aTitle) // there is no need to update the title. There is no need to // go to mSessionHistory to update the title. Setting it in mOSHE // would suffice. - if (mOSHE && (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_HISTORY)) { + if (mOSHE && (mLoadType != LOAD_BYPASS_HISTORY) && + (mLoadType != LOAD_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) { mOSHE->SetTitle(mTitle.get()); } @@ -4538,7 +4576,8 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress, if (httpChannel) { // figure out if SH should be saving layout state. PRBool discardLayoutState = ShouldDiscardLayoutState(httpChannel); - if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) && (mLoadType != LOAD_BYPASS_HISTORY)) + if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) && + (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) mLSHE->SetSaveLayoutStateFlag(PR_FALSE); } @@ -5592,13 +5631,17 @@ nsDocShell::InternalLoad(nsIURI * aURI, // been called. mLSHE = aSHEntry; + nsCOMPtr req; rv = DoURILoad(aURI, aReferrer, !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER), owner, aTypeHint, aPostData, aHeadersData, aFirstParty, - aDocShell, aRequest); + aDocShell, getter_AddRefs(req)); + if (req && aRequest) + NS_ADDREF(*aRequest = req); if (NS_FAILED(rv)) { - DisplayLoadError(rv, aURI, nsnull); + nsCOMPtr chan(do_QueryInterface(req)); + DisplayLoadError(rv, aURI, nsnull, chan); } return rv; @@ -5666,6 +5709,11 @@ nsDocShell::DoURILoad(nsIURI * aURI, loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI; } + if (mLoadType == LOAD_ERROR_PAGE) { + // Error pages are LOAD_BACKGROUND + loadFlags |= nsIChannel::LOAD_BACKGROUND; + } + // open a channel for the url nsCOMPtr channel; @@ -5692,6 +5740,11 @@ nsDocShell::DoURILoad(nsIURI * aURI, return rv; } + // 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 (aTypeHint && *aTypeHint) { channel->SetContentType(nsDependentCString(aTypeHint)); @@ -5819,9 +5872,6 @@ nsDocShell::DoURILoad(nsIURI * aURI, *aDocShell = this; NS_ADDREF(*aDocShell); } - if (aRequest) { - CallQueryInterface(channel, aRequest); - } } return rv; @@ -6173,6 +6223,19 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, PRUint32 aLoadType) { NS_ASSERTION(aURI, "uri is null"); +#ifdef PR_LOGGING + if (PR_LOG_TEST(gDocShellLog, PR_LOG_DEBUG)) { + nsCAutoString spec; + aURI->GetSpec(spec); + + nsCAutoString chanName; + aChannel->GetName(chanName); + + PR_LOG(gDocShellLog, PR_LOG_DEBUG, + ("nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n", this, spec.get(), + chanName.get(), aLoadType)); + } +#endif PRBool updateHistory = PR_TRUE; PRBool equalUri = PR_FALSE; @@ -6209,6 +6272,7 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, // Determine if this type of load should update history. if (aLoadType == LOAD_BYPASS_HISTORY || + aLoadType == LOAD_ERROR_PAGE || aLoadType & LOAD_CMD_HISTORY || aLoadType & LOAD_CMD_RELOAD) updateHistory = PR_FALSE; @@ -6258,7 +6322,7 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, if (cacheChannel) cacheChannel->GetCacheKey(getter_AddRefs(cacheKey)); if (mLSHE) - mLSHE->SetCacheKey(cacheKey); + mLSHE->SetCacheKey(cacheKey); } if (updateHistory && shAvailable) { @@ -6357,6 +6421,20 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel, nsISHEntry ** aNewEntry) { +#ifdef PR_LOGGING + if (PR_LOG_TEST(gDocShellLog, PR_LOG_DEBUG)) { + nsCAutoString spec; + aURI->GetSpec(spec); + + nsCAutoString chanName; + aChannel->GetName(chanName); + + PR_LOG(gDocShellLog, PR_LOG_DEBUG, + ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n", this, spec.get(), + chanName.get())); + } +#endif + nsresult rv = NS_OK; nsCOMPtr entry; PRBool shouldPersist; diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index 2620591a92f..a6050137fc0 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -100,6 +100,11 @@ #include "nsDocShellTransferableHooks.h" #include "nsIAuthPromptProvider.h" +/** + * Load flag for error pages. This should be bigger than all flags on + * nsIWebNavigation. + */ +#define LOAD_FLAGS_ERROR_PAGE 0x8000U #define MAKE_LOAD_TYPE(type, flags) ((type) | ((flags) << 16)) #define LOAD_TYPE_HAS_FLAGS(type, flags) ((type) & ((flags) << 16)) @@ -125,7 +130,14 @@ enum LoadType { LOAD_RELOAD_CHARSET_CHANGE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_RELOAD, nsIWebNavigation::LOAD_FLAGS_CHARSET_CHANGE), LOAD_BYPASS_HISTORY = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_BYPASS_HISTORY), LOAD_STOP_CONTENT = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT), - LOAD_STOP_CONTENT_AND_REPLACE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT | nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY) + LOAD_STOP_CONTENT_AND_REPLACE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, nsIWebNavigation::LOAD_FLAGS_STOP_CONTENT | nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY), + /** + * Load type for an error page. These loads are never triggered by users of + * Docshell. Instead, Docshell triggers the load itself when a + * consumer-triggered load failed. + */ + LOAD_ERROR_PAGE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL, LOAD_FLAGS_ERROR_PAGE) + // NOTE: Adding a new value? Remember to update IsValidLoadType! }; static inline PRBool IsValidLoadType(PRUint32 aLoadType) @@ -145,6 +157,7 @@ static inline PRBool IsValidLoadType(PRUint32 aLoadType) case LOAD_BYPASS_HISTORY: case LOAD_STOP_CONTENT: case LOAD_STOP_CONTENT_AND_REPLACE: + case LOAD_ERROR_PAGE: return PR_TRUE; } return PR_FALSE; @@ -312,8 +325,13 @@ protected: nsresult EnsureTransferableHookData(); NS_IMETHOD EnsureFind(); NS_IMETHOD RefreshURIFromQueue(); - NS_IMETHOD DisplayLoadError(nsresult aError, nsIURI *aURI, const PRUnichar *aURL); - NS_IMETHOD LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL, const PRUnichar *aPage, const PRUnichar *aDescription); + NS_IMETHOD DisplayLoadError(nsresult aError, nsIURI *aURI, + const PRUnichar *aURL, + nsIChannel* aFailedChannel = nsnull); + NS_IMETHOD LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL, + const PRUnichar *aPage, + const PRUnichar *aDescription, + nsIChannel* aFailedChannel); PRBool IsPrintingOrPP(PRBool aDisplayErrorDialog = PR_TRUE); nsresult SetBaseUrlForWyciwyg(nsIContentViewer * aContentViewer); diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index 8633fc1b6f4..06a5da99c4b 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -686,7 +686,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, if(url && NS_FAILED(aStatus)) { if (aStatus == NS_ERROR_FILE_NOT_FOUND) { - DisplayLoadError(aStatus, url, nsnull); + DisplayLoadError(aStatus, url, nsnull, channel); return NS_OK; } @@ -819,7 +819,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED) && (isTopFrame || mUseErrorPages)) { - DisplayLoadError(aStatus, url, nsnull); + DisplayLoadError(aStatus, url, nsnull, channel); } // Errors to be shown for any frame else if (aStatus == NS_ERROR_NET_TIMEOUT || @@ -827,7 +827,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE || aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET) { - DisplayLoadError(aStatus, url, nsnull); + DisplayLoadError(aStatus, url, nsnull, channel); } else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) { /* A document that was requested to be fetched *only* from @@ -925,7 +925,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, } } else { - DisplayLoadError(aStatus, url, nsnull); + DisplayLoadError(aStatus, url, nsnull, channel); } } } // if we have a host diff --git a/mozilla/docshell/resources/content/netError.js b/mozilla/docshell/resources/content/netError.js index dd54a439627..ff12b8fa53b 100644 --- a/mozilla/docshell/resources/content/netError.js +++ b/mozilla/docshell/resources/content/netError.js @@ -1,9 +1,15 @@ // Error url MUST be formatted like this: // chrome://neterror.xhtml?e=error&u=url&d=desc +// Note that this file uses document.documentURI to get +// the URL (with the format from above). This is because +// document.location.href gets the current URI off the docshell, +// which is the URL displayed in the location bar, i.e. +// the URI that the user attempted to load. + function getErrorCode() { - var url = document.location.href; + var url = document.documentURI; var error = url.search(/e\=/); var duffUrl = url.search(/\&u\=/); return decodeURIComponent(url.slice(error + 2, duffUrl)); @@ -11,7 +17,7 @@ function getErrorCode() function getDuffUrl() { - var url = document.location.href; + var url = document.documentURI; var duffUrl = url.search(/u\=/); var desc = url.search(/\&d\=/); return decodeURIComponent(url.slice(duffUrl + 2, desc)); @@ -19,7 +25,7 @@ function getDuffUrl() function getDescription() { - var url = document.location.href; + var url = document.documentURI; var desc = url.search(/d\=/); return decodeURIComponent(url.slice(desc + 2)); } diff --git a/mozilla/docshell/resources/content/netError.xhtml b/mozilla/docshell/resources/content/netError.xhtml index b4230372978..0b0e2a51eaf 100644 --- a/mozilla/docshell/resources/content/netError.xhtml +++ b/mozilla/docshell/resources/content/netError.xhtml @@ -86,7 +86,7 @@ ]]> - +
@@ -162,6 +162,12 @@

&retry.label;

+ +