diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 47f562b7ff18..2f26a65e4bf2 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -4282,7 +4282,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, bool* aDisplayedErrorPage) { *aDisplayedErrorPage = false; - // Get prompt and string bundle servcies + // Get prompt and string bundle services nsCOMPtr prompter; nsCOMPtr stringBundle; GetPromptAndStringBundle(getter_AddRefs(prompter), @@ -4303,20 +4303,24 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, nsAutoCString cssClass; nsAutoCString errorPage; - errorPage.AssignLiteral("neterror"); - if (mLoadURIDelegate) { - bool loadErrorHandled = false; + nsCOMPtr errorPageURI; rv = mLoadURIDelegate->HandleLoadError(aURI, aError, NS_ERROR_GET_MODULE(aError), - &loadErrorHandled); - if (NS_SUCCEEDED(rv) && loadErrorHandled) { - // The request has been handled, nothing to do here. + getter_AddRefs(errorPageURI)); + if (NS_FAILED(rv)) { *aDisplayedErrorPage = false; return NS_OK; } + + if (errorPageURI) { + *aDisplayedErrorPage = NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel)); + return NS_OK; + } } + errorPage.AssignLiteral("neterror"); + // Turn the error code into a human readable error message. if (NS_ERROR_UNKNOWN_PROTOCOL == aError) { NS_ENSURE_ARG_POINTER(aURI); @@ -4757,16 +4761,6 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, chanName.get())); } #endif - mFailedChannel = aFailedChannel; - mFailedURI = aURI; - mFailedLoadType = mLoadType; - - if (mLSHE) { - // Abandon mLSHE's BFCache entry and create a new one. This way, if - // we go back or forward to another SHEntry with the same doc - // identifier, the error page won't persist. - mLSHE->AbandonBFCacheEntry(); - } nsAutoCString url; if (aURI) { @@ -4833,7 +4827,24 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); NS_ENSURE_SUCCESS(rv, rv); - return InternalLoad(errorPageURI, nullptr, Nothing(), false, false, nullptr, RP_Unset, + return LoadErrorPage(errorPageURI, aURI, aFailedChannel); +} + +nsresult +nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, nsIChannel* aFailedChannel) +{ + mFailedChannel = aFailedChannel; + mFailedURI = aFailedURI; + mFailedLoadType = mLoadType; + + if (mLSHE) { + // Abandon mLSHE's BFCache entry and create a new one. This way, if + // we go back or forward to another SHEntry with the same doc + // identifier, the error page won't persist. + mLSHE->AbandonBFCacheEntry(); + } + + return InternalLoad(aErrorURI, nullptr, Nothing(), false, false, nullptr, RP_Unset, nsContentUtils::GetSystemPrincipal(), nullptr, INTERNAL_LOAD_FLAGS_NONE, EmptyString(), nullptr, VoidString(), nullptr, nullptr, @@ -9526,7 +9537,7 @@ nsDocShell::InternalLoad(nsIURI* aURI, const bool checkLoadDelegates = !(aFlags & INTERNAL_LOAD_FLAGS_DELEGATES_CHECKED); aFlags = aFlags & ~INTERNAL_LOAD_FLAGS_DELEGATES_CHECKED; - if (aURI && mLoadURIDelegate && checkLoadDelegates && + if (aURI && mLoadURIDelegate && checkLoadDelegates && aLoadType != LOAD_ERROR_PAGE && (!targetDocShell || targetDocShell == static_cast(this))) { // Dispatch only load requests for the current or a new window to the // delegate, e.g., to allow for GeckoView apps to handle the load event diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 965c35fecc8e..b05c25bf9f1a 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -590,12 +590,18 @@ private: // member functions nsresult aResult); + // Builds an error page URI (e.g. about:neterror?etc) for the given aURI + // and displays it via the LoadErrorPage() overload below. nsresult LoadErrorPage(nsIURI* aURI, const char16_t* aURL, - const char* aErrorPage, - const char* aErrorType, - const char16_t* aDescription, - const char* aCSSClass, - nsIChannel* aFailedChannel); + const char* aErrorPage, + const char* aErrorType, + const char16_t* aDescription, + const char* aCSSClass, + nsIChannel* aFailedChannel); + + // This method directly loads aErrorURI as an error page. aFailedURI and aFailedChannel + // come from DisplayLoadError() or the LoadErrorPage() overload above. + nsresult LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI, nsIChannel* aFailedChannel); bool DisplayLoadError(nsresult aError, nsIURI* aURI, const char16_t* aURL, nsIChannel* aFailedChannel) diff --git a/xpcom/base/nsILoadURIDelegate.idl b/xpcom/base/nsILoadURIDelegate.idl index e3c45c0a5a3e..5e90961a1392 100644 --- a/xpcom/base/nsILoadURIDelegate.idl +++ b/xpcom/base/nsILoadURIDelegate.idl @@ -41,9 +41,9 @@ interface nsILoadURIDelegate : nsISupports * @param aError The error code. * @param aErrorModule The error module code. - * Returns whether the page load error has been successfully handled. + * Returns an error page URL to load, or null to show the default error page. + * No error page is shown at all if an error is thrown. */ - boolean + nsIURI handleLoadError(in nsIURI aURI, in nsresult aError, in short aErrorModule); - };