diff options
-rw-r--r-- | chrome/app/generated_resources.grd | 71 | ||||
-rw-r--r-- | chrome/renderer/localized_error.cc | 193 | ||||
-rw-r--r-- | chrome/renderer/localized_error.h | 55 | ||||
-rw-r--r-- | chrome/renderer/navigation_state.h | 7 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 76 |
5 files changed, 324 insertions, 78 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 3e594f0..5768c5d 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -5266,7 +5266,10 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_ERRORPAGES_TITLE_NOT_AVAILABLE" desc="Title of the error page when we can't connect to a site."> <ph name="SITE">$1<ex>google.xom</ex></ph> is not available </message> - <message name="IDS_ERRORPAGES_TITLE_NOT_FOUND" desc="Title of the error page when the server returns a 404."> + <message name="IDS_ERRORPAGES_TITLE_ACCESS_DENIED" desc="Title in the error page when a server returns a 403. Also suitable for similar error codes."> + Access to <ph name="URL">$1<ex>http://www.google.com/foo/bar</ex></ph> denied. + </message> + <message name="IDS_ERRORPAGES_TITLE_NOT_FOUND" desc="Title of the error page when the server returns a 404 or 410."> <ph name="URL">$1<ex>http://www.google.com/foo/bar</ex></ph> is not found </message> <message name="IDS_ERRORPAGES_TITLE_LOAD_FAILED" desc="Title of the error page when we can't load a page."> @@ -5275,7 +5278,7 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_ERRORPAGES_HEADING_NOT_AVAILABLE" desc="Heading in the error page when we can't connect to a site."> This webpage is not available. </message> - <message name="IDS_ERRORPAGES_HEADING_NOT_FOUND" desc="Heading in the error page when the server returns a 404."> + <message name="IDS_ERRORPAGES_HEADING_NOT_FOUND" desc="Heading in the error page when the server returns a 404 or 410."> This webpage is not found. </message> <message name="IDS_ERRORPAGES_HEADING_TOO_MANY_REDIRECTS" desc="Heading in the error page when there are too many URL redirects."> @@ -5297,6 +5300,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_ERRORPAGES_DETAILS_TEMPLATE" desc="On the bottom of the error page text, there is a box that includes extra information for tech savvy users."> Error <ph name="ERROR_NUMBER">$1<ex>5</ex></ph> (<ph name="ERROR_NAME">$2<ex>net::ERR_FILE_NOT_FOUND</ex></ph>): <ph name="ERROR_TEXT">$3<ex>The requested file is not found.</ex></ph> </message> + <message name="IDS_ERRORPAGES_HTTP_DETAILS_TEMPLATE" desc="On the bottom of the error page text for http errors, there is a box that includes extra information for tech savvy users."> + HTTP Error <ph name="ERROR_NUMBER">$1<ex>500</ex></ph> (<ph name="ERROR_NAME">$2<ex>Internal Server Error</ex></ph>): <ph name="ERROR_TEXT">$3<ex>The server encountered an internal error.</ex></ph> + </message> <message name="IDS_ERRORPAGES_DETAILS_TIMED_OUT" desc="The error message displayed when a page takes too long to load."> The operation timed out. @@ -5320,6 +5326,67 @@ Keep your key file in a safe place. You will need it to create new versions of y Unknown error. </message> + <message name="IDS_ERRORPAGES_HEADING_ACCESS_DENIED" desc="Heading in the error page when a server returns a 403. Also suitable for similar error codes."> + Access to the webpage was denied. + </message> + <message name="IDS_ERRORPAGES_SUMMARY_FORBIDDEN" desc="Summary in the error page when a server returns a 403."> + You are not authorized to access the webpage at <ph name="URL"><strong jscontent="failedUrl"></strong></ph>. You may need to log in. + </message> + <message name="IDS_ERRORPAGES_DETAILS_FORBIDDEN" desc="Details in the error page when a server returns a 403."> + The server refused to fulfill the request. + </message> + + <message name="IDS_ERRORPAGES_SUMMARY_GONE" desc="Summary of the error page when the server returns a 410."> + The webpage at <ph name="URL"><strong jscontent="failedUrl"></strong></ph> no longer exists. + </message> + <message name="IDS_ERRORPAGES_DETAILS_GONE" desc="Details in the error page when a server returns a 403."> + The requested resource no longer exists, and there is forwarding address. This is expected to be a permanent condition. + </message> + + <message name="IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR" desc="Heading in the error page for 5xx errors."> + Server error. + </message> + + <message name="IDS_ERRORPAGES_SUMMARY_INTERNAL_SERVER_ERROR" desc="Summary in the error page when the server returns a 500."> + The website encountered an error while retrieving <ph name="URL"><strong jscontent="failedUrl"></strong></ph>. + It may be down for maintenance or configured incorrectly. + </message> + <message name="IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR" desc="The error message displayed when the server returns a 500."> + As unexpected condition was encountered while the server was attempting to fulfill the request. + </message> + + <message name="IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE" desc="Summary in the error page when the server returns a 501 or 505."> + The website is unable to handle the request for <ph name="URL"><strong jscontent="failedUrl"></strong></ph>. + </message> + <message name="IDS_ERRORPAGES_DETAILS_NOT_IMPLEMENTED" desc="The error message displayed when the server returns a 502."> + The server does have the functionality needed to fulfill the request. + </message> + <message name="IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED" desc="The error message displayed when the server returns a 505."> + The server does not support the HTTP version used in the request. + </message> + + <message name="IDS_ERRORPAGES_SUMMARY_BAD_GATEWAY" desc="Summary in the error page when the server returns a 502."> + An invalid response was received while attempting to load <ph name="URL"><strong jscontent="failedUrl"></strong></ph>. + The server may be down for maintenance or configured incorrectly. + </message> + <message name="IDS_ERRORPAGES_DETAILS_BAD_GATEWAY" desc="The error message displayed when the server returns a 502."> + The gateway or proxy server received an invalid response from an upstream server. + </message> + + <message name="IDS_ERRORPAGES_SUMMARY_SERVICE_UNAVAILABLE" desc="Summary in the error page when the server returns a 503."> + The webpage at <ph name="URL"><strong jscontent="failedUrl"></strong></ph> is currently unavailable. It may be overloaded or down for maintenance. + </message> + <message name="IDS_ERRORPAGES_DETAILS_SERVICE_UNAVAILABLE" desc="The error message displayed when the server returns a 503."> + The server is currently unable to handle the request. This code indicates this is a temporary condition, and the server will be up again after a delay. + </message> + + <message name="IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT" desc="Summary in the error page when the server returns a 504."> + The server for <ph name="URL"><strong jscontent="failedUrl"></strong></ph> took too long to respond. It may be overloaded. + </message> + <message name="IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT" desc="The error message displayed when the server returns a 504."> + The gateway or proxy server timed out while waiting for a response from an upstream server. + </message> + <message name="IDS_ERRORPAGES_HEADING_SSL_PROTOCOL_ERROR" desc="Heading in the error page for SSL protocol errors."> SSL connection error. </message> diff --git a/chrome/renderer/localized_error.cc b/chrome/renderer/localized_error.cc index 2bf9841..394844d 100644 --- a/chrome/renderer/localized_error.cc +++ b/chrome/renderer/localized_error.cc @@ -33,16 +33,16 @@ enum NAV_SUGGESTIONS { SUGGEST_LEARNMORE = 1 << 2, }; -struct WebErrorNetErrorMap { - const int error_code; - const unsigned int title_resource_id; - const unsigned int heading_resource_id; - const unsigned int summary_resource_id; - const unsigned int details_resource_id; - const int suggestions; // Bitmap of SUGGEST_* values. +struct LocalizedErrorMap { + int error_code; + unsigned int title_resource_id; + unsigned int heading_resource_id; + unsigned int summary_resource_id; + unsigned int details_resource_id; + int suggestions; // Bitmap of SUGGEST_* values. }; -WebErrorNetErrorMap net_error_options[] = { +const LocalizedErrorMap net_error_options[] = { {net::ERR_TIMED_OUT, IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, @@ -115,6 +115,139 @@ WebErrorNetErrorMap net_error_options[] = { }, }; +const LocalizedErrorMap http_error_options[] = { + {403, + IDS_ERRORPAGES_TITLE_ACCESS_DENIED, + IDS_ERRORPAGES_HEADING_ACCESS_DENIED, + IDS_ERRORPAGES_SUMMARY_FORBIDDEN, + IDS_ERRORPAGES_DETAILS_FORBIDDEN, + SUGGEST_NONE, + }, + {410, + IDS_ERRORPAGES_TITLE_NOT_FOUND, + IDS_ERRORPAGES_HEADING_NOT_FOUND, + IDS_ERRORPAGES_SUMMARY_GONE, + IDS_ERRORPAGES_DETAILS_GONE, + SUGGEST_NONE, + }, + + {500, + IDS_ERRORPAGES_TITLE_LOAD_FAILED, + IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, + IDS_ERRORPAGES_SUMMARY_INTERNAL_SERVER_ERROR, + IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR, + SUGGEST_RELOAD, + }, + {501, + IDS_ERRORPAGES_TITLE_LOAD_FAILED, + IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, + IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE, + IDS_ERRORPAGES_DETAILS_NOT_IMPLEMENTED, + SUGGEST_NONE, + }, + {502, + IDS_ERRORPAGES_TITLE_LOAD_FAILED, + IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, + IDS_ERRORPAGES_SUMMARY_BAD_GATEWAY, + IDS_ERRORPAGES_DETAILS_BAD_GATEWAY, + SUGGEST_RELOAD, + }, + {503, + IDS_ERRORPAGES_TITLE_LOAD_FAILED, + IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, + IDS_ERRORPAGES_SUMMARY_SERVICE_UNAVAILABLE, + IDS_ERRORPAGES_DETAILS_SERVICE_UNAVAILABLE, + SUGGEST_RELOAD, + }, + {504, + IDS_ERRORPAGES_TITLE_LOAD_FAILED, + IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, + IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT, + IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT, + SUGGEST_RELOAD, + }, + {505, + IDS_ERRORPAGES_TITLE_LOAD_FAILED, + IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, + IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE, + IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED, + SUGGEST_NONE, + }, +}; + +const char* HttpErrorToString(int status_code) { + switch (status_code) { + case 403: + return "Forbidden"; + case 410: + return "Gone"; + case 500: + return "Internal Server Error"; + case 501: + return "Not Implemented"; + case 502: + return "Bad Gateway"; + case 503: + return "Service Unavailable"; + case 504: + return "Gateway Timeout"; + case 505: + return "HTTP Version Not Supported"; + default: + return ""; + } +} + +string16 GetErrorDetailsString(const std::string& error_domain, + int error_code, + const string16& details) { + int error_page_template; + const char* error_string; + if (error_domain == net::kErrorDomain) { + error_page_template = IDS_ERRORPAGES_DETAILS_TEMPLATE; + DCHECK(error_code < 0); // Net error codes are negative. + error_code = -error_code; + error_string = net::ErrorToString(error_code); + } else if (error_domain == LocalizedError::kHttpErrorDomain) { + error_page_template = IDS_ERRORPAGES_HTTP_DETAILS_TEMPLATE; + error_string = HttpErrorToString(error_code); + } else { + NOTREACHED(); + return string16(); + } + return l10n_util::GetStringFUTF16( + error_page_template, + base::IntToString16(error_code), + ASCIIToUTF16(error_string), + details); +} + +const LocalizedErrorMap* FindErrorMapInArray(const LocalizedErrorMap* maps, + size_t num_maps, + int error_code) { + for (size_t i = 0; i < num_maps; ++i) { + if (maps[i].error_code == error_code) + return &maps[i]; + } + return NULL; +} + +const LocalizedErrorMap* LookupErrorMap(const std::string& error_domain, + int error_code) { + if (error_domain == net::kErrorDomain) { + return FindErrorMapInArray(net_error_options, + arraysize(net_error_options), + error_code); + } else if (error_domain == LocalizedError::kHttpErrorDomain) { + return FindErrorMapInArray(http_error_options, + arraysize(http_error_options), + error_code); + } else { + NOTREACHED(); + return NULL; + } +} + bool LocaleIsRTL() { #if defined(TOOLKIT_GTK) // base::i18n::IsRTL() uses the GTK text direction, which doesn't work within @@ -127,8 +260,10 @@ bool LocaleIsRTL() { } // namespace -void GetLocalizedErrorValues(const WebURLError& error, - DictionaryValue* error_strings) { +const char LocalizedError::kHttpErrorDomain[] = "http"; + +void LocalizedError::GetStrings(const WebKit::WebURLError& error, + DictionaryValue* error_strings) { bool rtl = LocaleIsRTL(); error_strings->SetString("textdirection", rtl ? "rtl" : "ltr"); @@ -140,7 +275,7 @@ void GetLocalizedErrorValues(const WebURLError& error, // Grab the strings and settings that depend on the error type. Init // options with default values. - WebErrorNetErrorMap options = { + LocalizedErrorMap options = { 0, IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, @@ -148,13 +283,13 @@ void GetLocalizedErrorValues(const WebURLError& error, IDS_ERRORPAGES_DETAILS_UNKNOWN, SUGGEST_NONE, }; + + const std::string error_domain = error.domain.utf8(); int error_code = error.reason; - for (size_t i = 0; i < arraysize(net_error_options); ++i) { - if (net_error_options[i].error_code == error_code) { - memcpy(&options, &net_error_options[i], sizeof(WebErrorNetErrorMap)); - break; - } - } + const LocalizedErrorMap* error_map = + LookupErrorMap(error_domain, error_code); + if (error_map) + options = *error_map; string16 suggestions_heading; if (options.suggestions != SUGGEST_NONE) { @@ -179,14 +314,9 @@ void GetLocalizedErrorValues(const WebURLError& error, summary->SetString("failedUrl", failed_url); error_strings->Set("summary", summary); - // Error codes are expected to be negative - DCHECK(error_code < 0); string16 details = l10n_util::GetStringUTF16(options.details_resource_id); error_strings->SetString("details", - l10n_util::GetStringFUTF16(IDS_ERRORPAGES_DETAILS_TEMPLATE, - base::IntToString16(-error_code), - ASCIIToUTF16(net::ErrorToString(error_code)), - details)); + GetErrorDetailsString(error_domain, error_code, details)); if (options.suggestions & SUGGEST_RELOAD) { DictionaryValue* suggest_reload = new DictionaryValue; @@ -241,8 +371,13 @@ void GetLocalizedErrorValues(const WebURLError& error, } } -void GetFormRepostErrorValues(const GURL& display_url, - DictionaryValue* error_strings) { +bool LocalizedError::HasStrings(const std::string& error_domain, + int error_code) { + return LookupErrorMap(error_domain, error_code) != NULL; +} + +void LocalizedError::GetFormRepostStrings(const GURL& display_url, + DictionaryValue* error_strings) { bool rtl = LocaleIsRTL(); error_strings->SetString("textdirection", rtl ? "rtl" : "ltr"); @@ -262,10 +397,10 @@ void GetFormRepostErrorValues(const GURL& display_url, error_strings->Set("summary", summary); } -void GetAppErrorValues(const WebURLError& error, - const GURL& display_url, - const ExtensionRendererInfo* app, - DictionaryValue* error_strings) { +void LocalizedError::GetAppErrorStrings(const WebURLError& error, + const GURL& display_url, + const ExtensionRendererInfo* app, + DictionaryValue* error_strings) { DCHECK(app); bool rtl = LocaleIsRTL(); diff --git a/chrome/renderer/localized_error.h b/chrome/renderer/localized_error.h index 4fa5304..1ea1c36 100644 --- a/chrome/renderer/localized_error.h +++ b/chrome/renderer/localized_error.h @@ -6,6 +6,10 @@ #define CHROME_RENDERER_LOCALIZED_ERROR_H_ #pragma once +#include <string> + +#include "base/basictypes.h" + class DictionaryValue; class ExtensionRendererInfo; class GURL; @@ -14,25 +18,36 @@ namespace WebKit { struct WebURLError; } -// Fills |error_strings| with values to be used to build an error page used -// on HTTP errors, like 404 or connection reset. -void GetLocalizedErrorValues(const WebKit::WebURLError& error, - DictionaryValue* error_strings); - -// Fills |error_strings| with values to be used to build an error page which -// warns against reposting form data. This is special cased because the form -// repost "error page" has no real error associated with it, and doesn't have -// enough strings localized to meaningfully fill the net error template. -void GetFormRepostErrorValues(const GURL& display_url, - DictionaryValue* error_strings); - -// Fills |error_strings| with values to be used to build an error page used -// on HTTP errors, like 404 or connection reset, but using information from -// the associated |app| in order to make the error page look like it's more -// part of the app. -void GetAppErrorValues(const WebKit::WebURLError& error, - const GURL& display_url, - const ExtensionRendererInfo* app, - DictionaryValue* error_strings); +class LocalizedError { + public: + // Fills |error_strings| with values to be used to build an error page used + // on HTTP errors, like 404 or connection reset. + static void GetStrings(const WebKit::WebURLError& error, + DictionaryValue* strings); + + // Returns true if an error page exists for the specified parameters. + static bool HasStrings(const std::string& error_domain, int error_code); + + // Fills |error_strings| with values to be used to build an error page which + // warns against reposting form data. This is special cased because the form + // repost "error page" has no real error associated with it, and doesn't have + // enough strings localized to meaningfully fill the net error template. + static void GetFormRepostStrings(const GURL& display_url, + DictionaryValue* error_strings); + + // Fills |error_strings| with values to be used to build an error page used + // on HTTP errors, like 404 or connection reset, but using information from + // the associated |app| in order to make the error page look like it's more + // part of the app. + static void GetAppErrorStrings(const WebKit::WebURLError& error, + const GURL& display_url, + const ExtensionRendererInfo* app, + DictionaryValue* error_strings); + + static const char kHttpErrorDomain[]; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(LocalizedError); +}; #endif // CHROME_RENDERER_LOCALIZED_ERROR_H_ diff --git a/chrome/renderer/navigation_state.h b/chrome/renderer/navigation_state.h index 6923def..d9cee3e 100644 --- a/chrome/renderer/navigation_state.h +++ b/chrome/renderer/navigation_state.h @@ -211,6 +211,11 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { postponed_data_.append(data, data_len); } + int http_status_code() const { return http_status_code_; } + void set_http_status_code(int http_status_code) { + http_status_code_ = http_status_code; + } + // Sets the cache policy. The cache policy is only used if explicitly set and // by default is not set. You can mark a NavigationState as not having a cache // state by way of clear_cache_policy_override. @@ -286,6 +291,7 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { cache_policy_override_set_(false), cache_policy_override_(WebKit::WebURLRequest::UseProtocolCachePolicy), user_script_idle_scheduler_(NULL), + http_status_code_(0), was_fetched_via_spdy_(false), was_npn_negotiated_(false), was_alternate_protocol_available_(false), @@ -323,6 +329,7 @@ class NavigationState : public WebKit::WebDataSource::ExtraData { WebKit::WebURLRequest::CachePolicy cache_policy_override_; scoped_ptr<UserScriptIdleScheduler> user_script_idle_scheduler_; + int http_status_code_; bool was_fetched_via_spdy_; bool was_npn_negotiated_; diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 721bfb6..c2810c2 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -1542,18 +1542,20 @@ void RenderView::LoadNavigationErrorPage(WebFrame* frame, if (failed_url.is_valid()) extension = ExtensionRendererInfo::GetByURL(failed_url); if (extension) { - GetAppErrorValues(error, failed_url, extension, &error_strings); + LocalizedError::GetAppErrorStrings(error, failed_url, extension, + &error_strings); // TODO(erikkay): Should we use a different template for different // error messages? resource_id = IDR_ERROR_APP_HTML; } else { - if (error.reason == net::ERR_CACHE_MISS && + if (error.domain == WebString::fromUTF8(net::kErrorDomain) && + error.reason == net::ERR_CACHE_MISS && EqualsASCII(failed_request.httpMethod(), "POST")) { - GetFormRepostErrorValues(failed_url, &error_strings); + LocalizedError::GetFormRepostStrings(failed_url, &error_strings); resource_id = IDR_ERROR_NO_DETAILS_HTML; } else { - GetLocalizedErrorValues(error, &error_strings); + LocalizedError::GetStrings(error, &error_strings); resource_id = IDR_NET_ERROR_HTML; } } @@ -2957,8 +2959,7 @@ void RenderView::didFailProvisionalLoad(WebFrame* frame, return; // Fallback to a local error page. - LoadNavigationErrorPage(frame, failed_request, error, std::string(), - replace); + LoadNavigationErrorPage(frame, failed_request, error, std::string(), replace); } void RenderView::didReceiveDocumentData( @@ -2972,10 +2973,12 @@ void RenderView::didReceiveDocumentData( // We're going to call commitDocumentData ourselves... prevent_default = true; - // Continue buffering the response data for the original 404 page. If it - // grows too large, then we'll just let it through. + // Continue buffering the response data for the original error page. If it + // grows too large, then we'll just let it through. For any error other than + // a 404, "too large" means any data at all. navigation_state->append_postponed_data(data, data_len); - if (navigation_state->postponed_data().size() >= 512) { + if (navigation_state->postponed_data().size() >= 512 || + navigation_state->http_status_code() != 404) { navigation_state->set_postpone_loading_data(false); frame->commitDocumentData(navigation_state->postponed_data().data(), navigation_state->postponed_data().size()); @@ -3245,13 +3248,14 @@ void RenderView::didReceiveResponse( return; // If we are in view source mode, then just let the user see the source of - // the server's 404 error page. + // the server's error page. if (frame->isViewSourceModeEnabled()) return; NavigationState* navigation_state = NavigationState::FromDataSource(frame->provisionalDataSource()); CHECK(navigation_state); + int http_status_code = response.httpStatusCode(); // Record page load flags. navigation_state->set_was_fetched_via_spdy(response.wasFetchedViaSPDY()); @@ -3259,14 +3263,20 @@ void RenderView::didReceiveResponse( navigation_state->set_was_alternate_protocol_available( response.wasAlternateProtocolAvailable()); navigation_state->set_was_fetched_via_proxy(response.wasFetchedViaProxy()); + navigation_state->set_http_status_code(http_status_code); // Consider loading an alternate error page for 404 responses. - if (response.httpStatusCode() != 404) - return; - - // Can we even load an alternate error page for this URL? - if (!GetAlternateErrorPageURL(response.url(), HTTP_404).is_valid()) + if (http_status_code == 404) { + // Can we even load an alternate error page for this URL? + if (!GetAlternateErrorPageURL(response.url(), HTTP_404).is_valid()) + return; + } else if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, + http_status_code)) { + // If no corresponding error strings for a particular status code, just + // render any received data, regardless of whether or not the status code + // indicates an error. return; + } navigation_state->set_postpone_loading_data(true); navigation_state->clear_postponed_data(); @@ -3279,21 +3289,33 @@ void RenderView::didFinishResourceLoad( if (!navigation_state->postpone_loading_data()) return; - // The server returned a 404 and the content was < 512 bytes (which we + // The server returned an error and the content was < 512 bytes (which we // suppressed). Go ahead and fetch the alternate page content. + int http_status_code = navigation_state->http_status_code(); + if (http_status_code == 404) { + // On 404s, try a remote search page as a fallback. + const GURL& frame_url = frame->url(); - const GURL& frame_url = frame->url(); + const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404); + DCHECK(error_page_url.is_valid()); - const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404); - DCHECK(error_page_url.is_valid()); + WebURLError original_error; + original_error.unreachableURL = frame_url; - WebURLError original_error; - original_error.unreachableURL = frame_url; + navigation_state->set_alt_error_page_fetcher( + new AltErrorPageResourceFetcher( + error_page_url, frame, original_error, + NewCallback(this, &RenderView::AltErrorPageFinished))); + } else { + // On other errors, use an internal error page. + WebURLError error; + error.unreachableURL = frame->url(); + error.domain = WebString::fromUTF8(LocalizedError::kHttpErrorDomain); + error.reason = http_status_code; - navigation_state->set_alt_error_page_fetcher( - new AltErrorPageResourceFetcher( - error_page_url, frame, original_error, - NewCallback(this, &RenderView::AltErrorPageFinished))); + LoadNavigationErrorPage(frame, frame->dataSource()->request(), error, + std::string(), true); + } } void RenderView::didFailResourceLoad( @@ -4587,8 +4609,8 @@ void RenderView::AltErrorPageFinished(WebFrame* frame, NavigationState::FromDataSource(frame->dataSource()); html_to_load = &navigation_state->postponed_data(); } - LoadNavigationErrorPage( - frame, WebURLRequest(), original_error, *html_to_load, true); + LoadNavigationErrorPage(frame, WebURLRequest(), original_error, *html_to_load, + true); } void RenderView::OnMoveOrResizeStarted() { |