Index: chrome/renderer/net/net_error_helper_core.cc |
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc |
deleted file mode 100644 |
index 94196295869d1bc75ac517632ed30728a763b4e6..0000000000000000000000000000000000000000 |
--- a/chrome/renderer/net/net_error_helper_core.cc |
+++ /dev/null |
@@ -1,948 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/renderer/net/net_error_helper_core.h" |
- |
-#include <set> |
-#include <string> |
-#include <vector> |
- |
-#include "base/bind.h" |
-#include "base/callback.h" |
-#include "base/i18n/rtl.h" |
-#include "base/json/json_reader.h" |
-#include "base/json/json_value_converter.h" |
-#include "base/json/json_writer.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/memory/scoped_vector.h" |
-#include "base/metrics/histogram.h" |
-#include "base/strings/string16.h" |
-#include "base/strings/string_util.h" |
-#include "base/values.h" |
-#include "chrome/common/localized_error.h" |
-#include "chrome/grit/generated_resources.h" |
-#include "content/public/common/url_constants.h" |
-#include "net/base/escape.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/net_util.h" |
-#include "third_party/WebKit/public/platform/WebString.h" |
-#include "third_party/WebKit/public/platform/WebURLError.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "url/gurl.h" |
- |
-namespace { |
- |
-struct CorrectionTypeToResourceTable { |
- int resource_id; |
- const char* correction_type; |
-}; |
- |
-const CorrectionTypeToResourceTable kCorrectionResourceTable[] = { |
- {IDS_ERRORPAGES_SUGGESTION_VISIT_GOOGLE_CACHE, "cachedPage"}, |
- // "reloadPage" is has special handling. |
- {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "urlCorrection"}, |
- {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "siteDomain"}, |
- {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "host"}, |
- {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "sitemap"}, |
- {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "pathParentFolder"}, |
- // "siteSearchQuery" is not yet supported. |
- // TODO(mmenke): Figure out what format "siteSearchQuery" uses for its |
- // suggestions. |
- // "webSearchQuery" has special handling. |
- {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "contentOverlap"}, |
- {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "emphasizedUrlCorrection"}, |
-}; |
- |
-struct NavigationCorrection { |
- NavigationCorrection() : is_porn(false), is_soft_porn(false) { |
- } |
- |
- static void RegisterJSONConverter( |
- base::JSONValueConverter<NavigationCorrection>* converter) { |
- converter->RegisterStringField("correctionType", |
- &NavigationCorrection::correction_type); |
- converter->RegisterStringField("urlCorrection", |
- &NavigationCorrection::url_correction); |
- converter->RegisterStringField("clickType", |
- &NavigationCorrection::click_type); |
- converter->RegisterStringField("clickData", |
- &NavigationCorrection::click_data); |
- converter->RegisterBoolField("isPorn", &NavigationCorrection::is_porn); |
- converter->RegisterBoolField("isSoftPorn", |
- &NavigationCorrection::is_soft_porn); |
- } |
- |
- std::string correction_type; |
- std::string url_correction; |
- std::string click_type; |
- std::string click_data; |
- bool is_porn; |
- bool is_soft_porn; |
-}; |
- |
-struct NavigationCorrectionResponse { |
- std::string event_id; |
- std::string fingerprint; |
- ScopedVector<NavigationCorrection> corrections; |
- |
- static void RegisterJSONConverter( |
- base::JSONValueConverter<NavigationCorrectionResponse>* converter) { |
- converter->RegisterStringField("result.eventId", |
- &NavigationCorrectionResponse::event_id); |
- converter->RegisterStringField("result.fingerprint", |
- &NavigationCorrectionResponse::fingerprint); |
- converter->RegisterRepeatedMessage( |
- "result.UrlCorrections", |
- &NavigationCorrectionResponse::corrections); |
- } |
-}; |
- |
-base::TimeDelta GetAutoReloadTime(size_t reload_count) { |
- static const int kDelaysMs[] = { |
- 0, 5000, 30000, 60000, 300000, 600000, 1800000 |
- }; |
- if (reload_count >= arraysize(kDelaysMs)) |
- reload_count = arraysize(kDelaysMs) - 1; |
- return base::TimeDelta::FromMilliseconds(kDelaysMs[reload_count]); |
-} |
- |
-// Returns whether |net_error| is a DNS-related error (and therefore whether |
-// the tab helper should start a DNS probe after receiving it.) |
-bool IsDnsError(const blink::WebURLError& error) { |
- return error.domain.utf8() == net::kErrorDomain && |
- (error.reason == net::ERR_NAME_NOT_RESOLVED || |
- error.reason == net::ERR_NAME_RESOLUTION_FAILED); |
-} |
- |
-GURL SanitizeURL(const GURL& url) { |
- GURL::Replacements remove_params; |
- remove_params.ClearUsername(); |
- remove_params.ClearPassword(); |
- remove_params.ClearQuery(); |
- remove_params.ClearRef(); |
- return url.ReplaceComponents(remove_params); |
-} |
- |
-// Sanitizes and formats a URL for upload to the error correction service. |
-std::string PrepareUrlForUpload(const GURL& url) { |
- // TODO(yuusuke): Change to net::FormatUrl when Link Doctor becomes |
- // unicode-capable. |
- std::string spec_to_send = SanitizeURL(url).spec(); |
- |
- // Notify navigation correction service of the url truncation by sending of |
- // "?" at the end. |
- if (url.has_query()) |
- spec_to_send.append("?"); |
- return spec_to_send; |
-} |
- |
-// Given a WebURLError, returns true if the FixURL service should be used |
-// for that error. Also sets |error_param| to the string that should be sent to |
-// the FixURL service to identify the error type. |
-bool ShouldUseFixUrlServiceForError(const blink::WebURLError& error, |
- std::string* error_param) { |
- error_param->clear(); |
- |
- // Don't use the correction service for HTTPS (for privacy reasons). |
- GURL unreachable_url(error.unreachableURL); |
- if (GURL(unreachable_url).SchemeIsSecure()) |
- return false; |
- |
- std::string domain = error.domain.utf8(); |
- if (domain == "http" && error.reason == 404) { |
- *error_param = "http404"; |
- return true; |
- } |
- if (IsDnsError(error)) { |
- *error_param = "dnserror"; |
- return true; |
- } |
- if (domain == net::kErrorDomain && |
- (error.reason == net::ERR_CONNECTION_FAILED || |
- error.reason == net::ERR_CONNECTION_REFUSED || |
- error.reason == net::ERR_ADDRESS_UNREACHABLE || |
- error.reason == net::ERR_CONNECTION_TIMED_OUT)) { |
- *error_param = "connectionFailure"; |
- return true; |
- } |
- return false; |
-} |
- |
-// Creates a request body for use with the fixurl service. Sets parameters |
-// shared by all types of requests to the service. |correction_params| must |
-// contain the parameters specific to the actual request type. |
-std::string CreateRequestBody( |
- const std::string& method, |
- const std::string& error_param, |
- const NetErrorHelperCore::NavigationCorrectionParams& correction_params, |
- scoped_ptr<base::DictionaryValue> params_dict) { |
- // Set params common to all request types. |
- params_dict->SetString("key", correction_params.api_key); |
- params_dict->SetString("clientName", "chrome"); |
- params_dict->SetString("error", error_param); |
- |
- if (!correction_params.language.empty()) |
- params_dict->SetString("language", correction_params.language); |
- |
- if (!correction_params.country_code.empty()) |
- params_dict->SetString("originCountry", correction_params.country_code); |
- |
- base::DictionaryValue request_dict; |
- request_dict.SetString("method", method); |
- request_dict.SetString("apiVersion", "v1"); |
- request_dict.Set("params", params_dict.release()); |
- |
- std::string request_body; |
- bool success = base::JSONWriter::Write(&request_dict, &request_body); |
- DCHECK(success); |
- return request_body; |
-} |
- |
-// If URL correction information should be retrieved remotely for a main frame |
-// load that failed with |error|, returns true and sets |
-// |correction_request_body| to be the body for the correction request. |
-std::string CreateFixUrlRequestBody( |
- const blink::WebURLError& error, |
- const NetErrorHelperCore::NavigationCorrectionParams& correction_params) { |
- std::string error_param; |
- bool result = ShouldUseFixUrlServiceForError(error, &error_param); |
- DCHECK(result); |
- |
- // TODO(mmenke): Investigate open sourcing the relevant protocol buffers and |
- // using those directly instead. |
- scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue()); |
- params->SetString("urlQuery", PrepareUrlForUpload(error.unreachableURL)); |
- return CreateRequestBody("linkdoctor.fixurl.fixurl", error_param, |
- correction_params, params.Pass()); |
-} |
- |
-std::string CreateClickTrackingUrlRequestBody( |
- const blink::WebURLError& error, |
- const NetErrorHelperCore::NavigationCorrectionParams& correction_params, |
- const NavigationCorrectionResponse& response, |
- const NavigationCorrection& correction) { |
- std::string error_param; |
- bool result = ShouldUseFixUrlServiceForError(error, &error_param); |
- DCHECK(result); |
- |
- scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue()); |
- |
- params->SetString("originalUrlQuery", |
- PrepareUrlForUpload(error.unreachableURL)); |
- |
- params->SetString("clickedUrlCorrection", correction.url_correction); |
- params->SetString("clickType", correction.click_type); |
- params->SetString("clickData", correction.click_data); |
- |
- params->SetString("eventId", response.event_id); |
- params->SetString("fingerprint", response.fingerprint); |
- |
- return CreateRequestBody("linkdoctor.fixurl.clicktracking", error_param, |
- correction_params, params.Pass()); |
-} |
- |
-base::string16 FormatURLForDisplay(const GURL& url, bool is_rtl, |
- const std::string accept_languages) { |
- // Translate punycode into UTF8, unescape UTF8 URLs. |
- base::string16 url_for_display(net::FormatUrl( |
- url, accept_languages, net::kFormatUrlOmitNothing, |
- net::UnescapeRule::NORMAL, NULL, NULL, NULL)); |
- // URLs are always LTR. |
- if (is_rtl) |
- base::i18n::WrapStringWithLTRFormatting(&url_for_display); |
- return url_for_display; |
-} |
- |
-scoped_ptr<NavigationCorrectionResponse> ParseNavigationCorrectionResponse( |
- const std::string raw_response) { |
- // TODO(mmenke): Open source related protocol buffers and use them directly. |
- scoped_ptr<base::Value> parsed(base::JSONReader::Read(raw_response)); |
- scoped_ptr<NavigationCorrectionResponse> response( |
- new NavigationCorrectionResponse()); |
- base::JSONValueConverter<NavigationCorrectionResponse> converter; |
- if (!parsed || !converter.Convert(*parsed, response.get())) |
- response.reset(); |
- return response.Pass(); |
-} |
- |
-scoped_ptr<LocalizedError::ErrorPageParams> CreateErrorPageParams( |
- const NavigationCorrectionResponse& response, |
- const blink::WebURLError& error, |
- const NetErrorHelperCore::NavigationCorrectionParams& correction_params, |
- const std::string& accept_languages, |
- bool is_rtl) { |
- // Version of URL for display in suggestions. It has to be sanitized first |
- // because any received suggestions will be relative to the sanitized URL. |
- base::string16 original_url_for_display = |
- FormatURLForDisplay(SanitizeURL(GURL(error.unreachableURL)), is_rtl, |
- accept_languages); |
- |
- scoped_ptr<LocalizedError::ErrorPageParams> params( |
- new LocalizedError::ErrorPageParams()); |
- params->override_suggestions.reset(new base::ListValue()); |
- scoped_ptr<base::ListValue> parsed_corrections(new base::ListValue()); |
- for (ScopedVector<NavigationCorrection>::const_iterator it = |
- response.corrections.begin(); |
- it != response.corrections.end(); ++it) { |
- // Doesn't seem like a good idea to show these. |
- if ((*it)->is_porn || (*it)->is_soft_porn) |
- continue; |
- |
- int tracking_id = it - response.corrections.begin(); |
- |
- if ((*it)->correction_type == "reloadPage") { |
- params->suggest_reload = true; |
- params->reload_tracking_id = tracking_id; |
- continue; |
- } |
- |
- if ((*it)->correction_type == "webSearchQuery") { |
- // If there are mutliple searches suggested, use the first suggestion. |
- if (params->search_terms.empty()) { |
- params->search_url = correction_params.search_url; |
- params->search_terms = (*it)->url_correction; |
- params->search_tracking_id = tracking_id; |
- } |
- continue; |
- } |
- |
- // Allow reload page and web search query to be empty strings, but not |
- // links. |
- if ((*it)->url_correction.empty()) |
- continue; |
- size_t correction_index; |
- for (correction_index = 0; |
- correction_index < arraysize(kCorrectionResourceTable); |
- ++correction_index) { |
- if ((*it)->correction_type != |
- kCorrectionResourceTable[correction_index].correction_type) { |
- continue; |
- } |
- base::DictionaryValue* suggest = new base::DictionaryValue(); |
- suggest->SetString("header", |
- l10n_util::GetStringUTF16( |
- kCorrectionResourceTable[correction_index].resource_id)); |
- suggest->SetString("urlCorrection", (*it)->url_correction); |
- suggest->SetString( |
- "urlCorrectionForDisplay", |
- FormatURLForDisplay(GURL((*it)->url_correction), is_rtl, |
- accept_languages)); |
- suggest->SetString("originalUrlForDisplay", original_url_for_display); |
- suggest->SetInteger("trackingId", tracking_id); |
- params->override_suggestions->Append(suggest); |
- break; |
- } |
- } |
- |
- if (params->override_suggestions->empty() && !params->search_url.is_valid()) |
- params.reset(); |
- return params.Pass(); |
-} |
- |
-void ReportAutoReloadSuccess(const blink::WebURLError& error, size_t count) { |
- if (error.domain.utf8() != net::kErrorDomain) |
- return; |
- UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", |
- -error.reason, |
- net::GetAllErrorCodesForUma()); |
- UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", count); |
- if (count == 1) { |
- UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", |
- -error.reason, |
- net::GetAllErrorCodesForUma()); |
- } |
-} |
- |
-void ReportAutoReloadFailure(const blink::WebURLError& error, size_t count) { |
- if (error.domain.utf8() != net::kErrorDomain) |
- return; |
- UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", |
- -error.reason, |
- net::GetAllErrorCodesForUma()); |
- UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", count); |
-} |
- |
-} // namespace |
- |
-struct NetErrorHelperCore::ErrorPageInfo { |
- ErrorPageInfo(blink::WebURLError error, bool was_failed_post) |
- : error(error), |
- was_failed_post(was_failed_post), |
- needs_dns_updates(false), |
- needs_load_navigation_corrections(false), |
- reload_button_in_page(false), |
- load_stale_button_in_page(false), |
- is_finished_loading(false), |
- auto_reload_triggered(false) { |
- } |
- |
- // Information about the failed page load. |
- blink::WebURLError error; |
- bool was_failed_post; |
- |
- // Information about the status of the error page. |
- |
- // True if a page is a DNS error page and has not yet received a final DNS |
- // probe status. |
- bool needs_dns_updates; |
- |
- // True if a blank page was loaded, and navigation corrections need to be |
- // loaded to generate the real error page. |
- bool needs_load_navigation_corrections; |
- |
- // Navigation correction service paramers, which will be used in response to |
- // certain types of network errors. They are all stored here in case they |
- // change over the course of displaying the error page. |
- scoped_ptr<NetErrorHelperCore::NavigationCorrectionParams> |
- navigation_correction_params; |
- |
- scoped_ptr<NavigationCorrectionResponse> navigation_correction_response; |
- |
- // All the navigation corrections that have been clicked, for tracking |
- // purposes. |
- std::set<int> clicked_corrections; |
- |
- // Track if specific buttons are included in an error page, for statistics. |
- bool reload_button_in_page; |
- bool load_stale_button_in_page; |
- |
- // True if a page has completed loading, at which point it can receive |
- // updates. |
- bool is_finished_loading; |
- |
- // True if the auto-reload timer has fired and a reload is or has been in |
- // flight. |
- bool auto_reload_triggered; |
-}; |
- |
-NetErrorHelperCore::NavigationCorrectionParams::NavigationCorrectionParams() { |
-} |
- |
-NetErrorHelperCore::NavigationCorrectionParams::~NavigationCorrectionParams() { |
-} |
- |
-bool NetErrorHelperCore::IsReloadableError( |
- const NetErrorHelperCore::ErrorPageInfo& info) { |
- return info.error.domain.utf8() == net::kErrorDomain && |
- info.error.reason != net::ERR_ABORTED && |
- !info.was_failed_post; |
-} |
- |
-NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate, |
- bool auto_reload_enabled, |
- bool auto_reload_visible_only, |
- bool is_visible) |
- : delegate_(delegate), |
- last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), |
- auto_reload_enabled_(auto_reload_enabled), |
- auto_reload_visible_only_(auto_reload_visible_only), |
- auto_reload_timer_(new base::Timer(false, false)), |
- auto_reload_paused_(false), |
- uncommitted_load_started_(false), |
- // TODO(ellyjones): Make online_ accurate at object creation. |
- online_(true), |
- visible_(is_visible), |
- auto_reload_count_(0), |
- navigation_from_button_(NO_BUTTON) { |
-} |
- |
-NetErrorHelperCore::~NetErrorHelperCore() { |
- if (committed_error_page_info_ && |
- committed_error_page_info_->auto_reload_triggered) { |
- ReportAutoReloadFailure(committed_error_page_info_->error, |
- auto_reload_count_); |
- } |
-} |
- |
-void NetErrorHelperCore::CancelPendingFetches() { |
- // Cancel loading the alternate error page, and prevent any pending error page |
- // load from starting a new error page load. Swapping in the error page when |
- // it's finished loading could abort the navigation, otherwise. |
- if (committed_error_page_info_) |
- committed_error_page_info_->needs_load_navigation_corrections = false; |
- if (pending_error_page_info_) |
- pending_error_page_info_->needs_load_navigation_corrections = false; |
- delegate_->CancelFetchNavigationCorrections(); |
- auto_reload_timer_->Stop(); |
- auto_reload_paused_ = false; |
-} |
- |
-void NetErrorHelperCore::OnStop() { |
- if (committed_error_page_info_ && |
- committed_error_page_info_->auto_reload_triggered) { |
- ReportAutoReloadFailure(committed_error_page_info_->error, |
- auto_reload_count_); |
- } |
- CancelPendingFetches(); |
- uncommitted_load_started_ = false; |
- auto_reload_count_ = 0; |
-} |
- |
-void NetErrorHelperCore::OnWasShown() { |
- visible_ = true; |
- if (!auto_reload_visible_only_) |
- return; |
- if (auto_reload_paused_) |
- MaybeStartAutoReloadTimer(); |
-} |
- |
-void NetErrorHelperCore::OnWasHidden() { |
- visible_ = false; |
- if (!auto_reload_visible_only_) |
- return; |
- PauseAutoReloadTimer(); |
-} |
- |
-void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { |
- if (frame_type != MAIN_FRAME) |
- return; |
- |
- uncommitted_load_started_ = true; |
- |
- // If there's no pending error page information associated with the page load, |
- // or the new page is not an error page, then reset pending error page state. |
- if (!pending_error_page_info_ || page_type != ERROR_PAGE) |
- CancelPendingFetches(); |
-} |
- |
-void NetErrorHelperCore::OnCommitLoad(FrameType frame_type, const GURL& url) { |
- if (frame_type != MAIN_FRAME) |
- return; |
- |
- // uncommitted_load_started_ could already be false, since RenderFrameImpl |
- // calls OnCommitLoad once for each in-page navigation (like a fragment |
- // change) with no corresponding OnStartLoad. |
- uncommitted_load_started_ = false; |
- |
- // Track if an error occurred due to a page button press. |
- // This isn't perfect; if (for instance), the server is slow responding |
- // to a request generated from the page reload button, and the user hits |
- // the browser reload button, this code will still believe the |
- // result is from the page reload button. |
- if (committed_error_page_info_ && pending_error_page_info_ && |
- navigation_from_button_ != NO_BUTTON && |
- committed_error_page_info_->error.unreachableURL == |
- pending_error_page_info_->error.unreachableURL) { |
- DCHECK(navigation_from_button_ == RELOAD_BUTTON || |
- navigation_from_button_ == LOAD_STALE_BUTTON); |
- chrome_common_net::RecordEvent( |
- navigation_from_button_ == RELOAD_BUTTON ? |
- chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_ERROR : |
- chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_ERROR); |
- } |
- navigation_from_button_ = NO_BUTTON; |
- |
- if (committed_error_page_info_ && !pending_error_page_info_ && |
- committed_error_page_info_->auto_reload_triggered) { |
- const blink::WebURLError& error = committed_error_page_info_->error; |
- const GURL& error_url = error.unreachableURL; |
- if (url == error_url) |
- ReportAutoReloadSuccess(error, auto_reload_count_); |
- else if (url != GURL(content::kUnreachableWebDataURL)) |
- ReportAutoReloadFailure(error, auto_reload_count_); |
- } |
- |
- committed_error_page_info_.reset(pending_error_page_info_.release()); |
-} |
- |
-void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
- if (frame_type != MAIN_FRAME) |
- return; |
- |
- if (!committed_error_page_info_) { |
- auto_reload_count_ = 0; |
- return; |
- } |
- |
- committed_error_page_info_->is_finished_loading = true; |
- |
- chrome_common_net::RecordEvent(chrome_common_net::NETWORK_ERROR_PAGE_SHOWN); |
- if (committed_error_page_info_->reload_button_in_page) { |
- chrome_common_net::RecordEvent( |
- chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_SHOWN); |
- } |
- if (committed_error_page_info_->load_stale_button_in_page) { |
- chrome_common_net::RecordEvent( |
- chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_SHOWN); |
- } |
- |
- delegate_->EnablePageHelperFunctions(); |
- |
- if (committed_error_page_info_->needs_load_navigation_corrections) { |
- // If there is another pending error page load, |fix_url| should have been |
- // cleared. |
- DCHECK(!pending_error_page_info_); |
- DCHECK(!committed_error_page_info_->needs_dns_updates); |
- delegate_->FetchNavigationCorrections( |
- committed_error_page_info_->navigation_correction_params->url, |
- CreateFixUrlRequestBody( |
- committed_error_page_info_->error, |
- *committed_error_page_info_->navigation_correction_params)); |
- } else if (auto_reload_enabled_ && |
- IsReloadableError(*committed_error_page_info_)) { |
- MaybeStartAutoReloadTimer(); |
- } |
- |
- if (!committed_error_page_info_->needs_dns_updates || |
- last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { |
- return; |
- } |
- DVLOG(1) << "Error page finished loading; sending saved status."; |
- UpdateErrorPage(); |
-} |
- |
-void NetErrorHelperCore::GetErrorHTML( |
- FrameType frame_type, |
- const blink::WebURLError& error, |
- bool is_failed_post, |
- std::string* error_html) { |
- if (frame_type == MAIN_FRAME) { |
- // If navigation corrections were needed before, that should have been |
- // cancelled earlier by starting a new page load (Which has now failed). |
- DCHECK(!committed_error_page_info_ || |
- !committed_error_page_info_->needs_load_navigation_corrections); |
- |
- pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); |
- pending_error_page_info_->navigation_correction_params.reset( |
- new NavigationCorrectionParams(navigation_correction_params_)); |
- GetErrorHtmlForMainFrame(pending_error_page_info_.get(), error_html); |
- } else { |
- // These values do not matter, as error pages in iframes hide the buttons. |
- bool reload_button_in_page; |
- bool load_stale_button_in_page; |
- |
- delegate_->GenerateLocalizedErrorPage( |
- error, is_failed_post, scoped_ptr<LocalizedError::ErrorPageParams>(), |
- &reload_button_in_page, &load_stale_button_in_page, |
- error_html); |
- } |
-} |
- |
-void NetErrorHelperCore::OnNetErrorInfo( |
- chrome_common_net::DnsProbeStatus status) { |
- DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); |
- |
- last_probe_status_ = status; |
- |
- if (!committed_error_page_info_ || |
- !committed_error_page_info_->needs_dns_updates || |
- !committed_error_page_info_->is_finished_loading) { |
- return; |
- } |
- |
- UpdateErrorPage(); |
-} |
- |
-void NetErrorHelperCore::OnSetNavigationCorrectionInfo( |
- const GURL& navigation_correction_url, |
- const std::string& language, |
- const std::string& country_code, |
- const std::string& api_key, |
- const GURL& search_url) { |
- navigation_correction_params_.url = navigation_correction_url; |
- navigation_correction_params_.language = language; |
- navigation_correction_params_.country_code = country_code; |
- navigation_correction_params_.api_key = api_key; |
- navigation_correction_params_.search_url = search_url; |
-} |
- |
-void NetErrorHelperCore::GetErrorHtmlForMainFrame( |
- ErrorPageInfo* pending_error_page_info, |
- std::string* error_html) { |
- std::string error_param; |
- blink::WebURLError error = pending_error_page_info->error; |
- |
- if (pending_error_page_info->navigation_correction_params && |
- pending_error_page_info->navigation_correction_params->url.is_valid() && |
- ShouldUseFixUrlServiceForError(error, &error_param)) { |
- pending_error_page_info->needs_load_navigation_corrections = true; |
- return; |
- } |
- |
- if (IsDnsError(pending_error_page_info->error)) { |
- // The last probe status needs to be reset if this is a DNS error. This |
- // means that if a DNS error page is committed but has not yet finished |
- // loading, a DNS probe status scheduled to be sent to it may be thrown |
- // out, but since the new error page should trigger a new DNS probe, it |
- // will just get the results for the next page load. |
- last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; |
- pending_error_page_info->needs_dns_updates = true; |
- error = GetUpdatedError(error); |
- } |
- |
- delegate_->GenerateLocalizedErrorPage( |
- error, pending_error_page_info->was_failed_post, |
- scoped_ptr<LocalizedError::ErrorPageParams>(), |
- &pending_error_page_info->reload_button_in_page, |
- &pending_error_page_info->load_stale_button_in_page, |
- error_html); |
-} |
- |
-void NetErrorHelperCore::UpdateErrorPage() { |
- DCHECK(committed_error_page_info_->needs_dns_updates); |
- DCHECK(committed_error_page_info_->is_finished_loading); |
- DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_probe_status_); |
- |
- UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", |
- last_probe_status_, |
- chrome_common_net::DNS_PROBE_MAX); |
- // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a |
- // final status code. Once one is reached, the page does not need further |
- // updates. |
- if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) |
- committed_error_page_info_->needs_dns_updates = false; |
- |
- // There is no need to worry about the button display statistics here because |
- // the presentation of the reload and load stale buttons can't be changed |
- // by a DNS error update. |
- delegate_->UpdateErrorPage( |
- GetUpdatedError(committed_error_page_info_->error), |
- committed_error_page_info_->was_failed_post); |
-} |
- |
-void NetErrorHelperCore::OnNavigationCorrectionsFetched( |
- const std::string& corrections, |
- const std::string& accept_languages, |
- bool is_rtl) { |
- // Loading suggestions only starts when a blank error page finishes loading, |
- // and is cancelled with a new load. |
- DCHECK(!pending_error_page_info_); |
- DCHECK(committed_error_page_info_->is_finished_loading); |
- DCHECK(committed_error_page_info_->needs_load_navigation_corrections); |
- DCHECK(committed_error_page_info_->navigation_correction_params); |
- |
- pending_error_page_info_.reset( |
- new ErrorPageInfo(committed_error_page_info_->error, |
- committed_error_page_info_->was_failed_post)); |
- pending_error_page_info_->navigation_correction_response = |
- ParseNavigationCorrectionResponse(corrections); |
- |
- std::string error_html; |
- scoped_ptr<LocalizedError::ErrorPageParams> params; |
- if (pending_error_page_info_->navigation_correction_response) { |
- // Copy navigation correction parameters used for the request, so tracking |
- // requests can still be sent if the configuration changes. |
- pending_error_page_info_->navigation_correction_params.reset( |
- new NavigationCorrectionParams( |
- *committed_error_page_info_->navigation_correction_params)); |
- params = CreateErrorPageParams( |
- *pending_error_page_info_->navigation_correction_response, |
- pending_error_page_info_->error, |
- *pending_error_page_info_->navigation_correction_params, |
- accept_languages, is_rtl); |
- delegate_->GenerateLocalizedErrorPage( |
- pending_error_page_info_->error, |
- pending_error_page_info_->was_failed_post, |
- params.Pass(), |
- &pending_error_page_info_->reload_button_in_page, |
- &pending_error_page_info_->load_stale_button_in_page, |
- &error_html); |
- } else { |
- // Since |navigation_correction_params| in |pending_error_page_info_| is |
- // NULL, this won't trigger another attempt to load corrections. |
- GetErrorHtmlForMainFrame(pending_error_page_info_.get(), &error_html); |
- } |
- |
- // TODO(mmenke): Once the new API is in place, look into replacing this |
- // double page load by just updating the error page, like DNS |
- // probes do. |
- delegate_->LoadErrorPageInMainFrame( |
- error_html, |
- pending_error_page_info_->error.unreachableURL); |
-} |
- |
-blink::WebURLError NetErrorHelperCore::GetUpdatedError( |
- const blink::WebURLError& error) const { |
- // If a probe didn't run or wasn't conclusive, restore the original error. |
- if (last_probe_status_ == chrome_common_net::DNS_PROBE_NOT_RUN || |
- last_probe_status_ == |
- chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE) { |
- return error; |
- } |
- |
- blink::WebURLError updated_error; |
- updated_error.domain = blink::WebString::fromUTF8( |
- chrome_common_net::kDnsProbeErrorDomain); |
- updated_error.reason = last_probe_status_; |
- updated_error.unreachableURL = error.unreachableURL; |
- updated_error.staleCopyInCache = error.staleCopyInCache; |
- |
- return updated_error; |
-} |
- |
-void NetErrorHelperCore::Reload() { |
- if (!committed_error_page_info_) { |
- return; |
- } |
- delegate_->ReloadPage(); |
-} |
- |
-bool NetErrorHelperCore::MaybeStartAutoReloadTimer() { |
- if (!committed_error_page_info_ || |
- !committed_error_page_info_->is_finished_loading || |
- pending_error_page_info_ || |
- uncommitted_load_started_) { |
- return false; |
- } |
- |
- StartAutoReloadTimer(); |
- return true; |
-} |
- |
-void NetErrorHelperCore::StartAutoReloadTimer() { |
- DCHECK(committed_error_page_info_); |
- DCHECK(IsReloadableError(*committed_error_page_info_)); |
- |
- committed_error_page_info_->auto_reload_triggered = true; |
- |
- if (!online_ || (!visible_ && auto_reload_visible_only_)) { |
- auto_reload_paused_ = true; |
- return; |
- } |
- |
- auto_reload_paused_ = false; |
- base::TimeDelta delay = GetAutoReloadTime(auto_reload_count_); |
- auto_reload_timer_->Stop(); |
- auto_reload_timer_->Start(FROM_HERE, delay, |
- base::Bind(&NetErrorHelperCore::AutoReloadTimerFired, |
- base::Unretained(this))); |
-} |
- |
-void NetErrorHelperCore::AutoReloadTimerFired() { |
- auto_reload_count_++; |
- Reload(); |
-} |
- |
-void NetErrorHelperCore::PauseAutoReloadTimer() { |
- if (!auto_reload_timer_->IsRunning()) |
- return; |
- DCHECK(committed_error_page_info_); |
- DCHECK(!auto_reload_paused_); |
- DCHECK(committed_error_page_info_->auto_reload_triggered); |
- auto_reload_timer_->Stop(); |
- auto_reload_paused_ = true; |
-} |
- |
-void NetErrorHelperCore::NetworkStateChanged(bool online) { |
- bool was_online = online_; |
- online_ = online; |
- if (!was_online && online) { |
- // Transitioning offline -> online |
- if (auto_reload_paused_) |
- MaybeStartAutoReloadTimer(); |
- } else if (was_online && !online) { |
- // Transitioning online -> offline |
- if (auto_reload_timer_->IsRunning()) |
- auto_reload_count_ = 0; |
- PauseAutoReloadTimer(); |
- } |
-} |
- |
-bool NetErrorHelperCore::ShouldSuppressErrorPage(FrameType frame_type, |
- const GURL& url) { |
- // Don't suppress child frame errors. |
- if (frame_type != MAIN_FRAME) |
- return false; |
- |
- if (!auto_reload_enabled_) |
- return false; |
- |
- // If there's no committed error page, this error page wasn't from an auto |
- // reload. |
- if (!committed_error_page_info_) |
- return false; |
- |
- // If the error page wasn't reloadable, display it. |
- if (!IsReloadableError(*committed_error_page_info_)) |
- return false; |
- |
- // If |auto_reload_timer_| is still running or is paused, this error page |
- // isn't from an auto reload. |
- if (auto_reload_timer_->IsRunning() || auto_reload_paused_) |
- return false; |
- |
- // If the error page was reloadable, and the timer isn't running or paused, an |
- // auto-reload has already been triggered. |
- DCHECK(committed_error_page_info_->auto_reload_triggered); |
- |
- GURL error_url = committed_error_page_info_->error.unreachableURL; |
- // TODO(ellyjones): also plumb the error code down to CCRC and check that |
- if (error_url != url) |
- return false; |
- |
- // Suppressed an error-page load; the previous uncommitted load was the error |
- // page load starting, so forget about it. |
- uncommitted_load_started_ = false; |
- |
- // The first iteration of the timer is started by OnFinishLoad calling |
- // MaybeStartAutoReloadTimer, but since error pages for subsequent loads are |
- // suppressed in this function, subsequent iterations of the timer have to be |
- // started here. |
- MaybeStartAutoReloadTimer(); |
- return true; |
-} |
- |
-void NetErrorHelperCore::ExecuteButtonPress(Button button) { |
- switch (button) { |
- case RELOAD_BUTTON: |
- chrome_common_net::RecordEvent( |
- chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_CLICKED); |
- navigation_from_button_ = RELOAD_BUTTON; |
- Reload(); |
- return; |
- case LOAD_STALE_BUTTON: |
- chrome_common_net::RecordEvent( |
- chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_CLICKED); |
- navigation_from_button_ = LOAD_STALE_BUTTON; |
- delegate_->LoadPageFromCache( |
- committed_error_page_info_->error.unreachableURL); |
- return; |
- case MORE_BUTTON: |
- // Visual effects on page are handled in Javascript code. |
- chrome_common_net::RecordEvent( |
- chrome_common_net::NETWORK_ERROR_PAGE_MORE_BUTTON_CLICKED); |
- return; |
- case NO_BUTTON: |
- NOTREACHED(); |
- return; |
- } |
-} |
- |
-void NetErrorHelperCore::TrackClick(int tracking_id) { |
- // It's technically possible for |navigation_correction_params| to be NULL but |
- // for |navigation_correction_response| not to be NULL, if the paramters |
- // changed between loading the original error page and loading the error page |
- if (!committed_error_page_info_ || |
- !committed_error_page_info_->navigation_correction_response) { |
- return; |
- } |
- |
- NavigationCorrectionResponse* response = |
- committed_error_page_info_->navigation_correction_response.get(); |
- |
- // |tracking_id| is less than 0 when the error page was not generated by the |
- // navigation correction service. |tracking_id| should never be greater than |
- // the array size, but best to be safe, since it contains data from a remote |
- // site, though none of that data should make it into Javascript callbacks. |
- if (tracking_id < 0 || |
- static_cast<size_t>(tracking_id) >= response->corrections.size()) { |
- return; |
- } |
- |
- // Only report a clicked link once. |
- if (committed_error_page_info_->clicked_corrections.count(tracking_id)) |
- return; |
- |
- committed_error_page_info_->clicked_corrections.insert(tracking_id); |
- std::string request_body = CreateClickTrackingUrlRequestBody( |
- committed_error_page_info_->error, |
- *committed_error_page_info_->navigation_correction_params, |
- *response, |
- *response->corrections[tracking_id]); |
- delegate_->SendTrackingRequest( |
- committed_error_page_info_->navigation_correction_params->url, |
- request_body); |
-} |
- |