Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8806)

Unified Diff: chrome/renderer/net/net_error_helper_core.cc

Issue 137623011: Switch to using the new Link Doctor API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Remove bonus line from a merge conflict Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/renderer/net/net_error_helper_core.h ('k') | chrome/renderer/net/net_error_helper_core_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/renderer/net/net_error_helper_core.cc
===================================================================
--- chrome/renderer/net/net_error_helper_core.cc (revision 253247)
+++ chrome/renderer/net/net_error_helper_core.cc (working copy)
@@ -6,16 +6,45 @@
#include <string>
+#include "base/i18n/rtl.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/metrics/histogram.h"
+#include "base/strings/string16.h"
+#include "base/values.h"
#include "chrome/common/localized_error.h"
+#include "grit/generated_resources.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"},
+};
+
// 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) {
@@ -24,16 +53,24 @@
error.reason == net::ERR_NAME_RESOLUTION_FAILED);
}
-// If an alternate error page should be retrieved remotely for a main frame load
-// that failed with |error|, returns true and sets |error_page_url| to the URL
-// of the remote error page.
-bool GetErrorPageURL(const blink::WebURLError& error,
- const GURL& alt_error_page_url,
- GURL* error_page_url) {
- if (!alt_error_page_url.is_valid())
- return false;
+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);
+}
- // Parameter to send to the error page indicating the error type.
+// 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.
+bool GetFixUrlRequestBody(const blink::WebURLError& error,
+ const std::string& language,
+ const std::string& country_code,
+ const std::string& api_key,
+ std::string* correction_request_body) {
+ // Parameter to send to the correction service indicating the error type.
std::string error_param;
std::string domain = error.domain.utf8();
@@ -46,45 +83,157 @@
error.reason == net::ERR_CONNECTION_REFUSED ||
error.reason == net::ERR_ADDRESS_UNREACHABLE ||
error.reason == net::ERR_CONNECTION_TIMED_OUT)) {
- error_param = "connectionfailure";
+ error_param = "connectionFailure";
} else {
return false;
}
- // Don't use the Link Doctor for HTTPS (for privacy reasons).
+ // Don't use the correction service for HTTPS (for privacy reasons).
GURL unreachable_url(error.unreachableURL);
if (unreachable_url.SchemeIsSecure())
return false;
- // Sanitize the unreachable URL.
- GURL::Replacements remove_params;
- remove_params.ClearUsername();
- remove_params.ClearPassword();
- remove_params.ClearQuery();
- remove_params.ClearRef();
- // TODO(yuusuke): change to net::FormatUrl when Link Doctor becomes
+ // TODO(yuusuke): Change to net::FormatUrl when Link Doctor becomes
// unicode-capable.
- std::string spec_to_send =
- unreachable_url.ReplaceComponents(remove_params).spec();
+ std::string spec_to_send = SanitizeURL(unreachable_url).spec();
- // Notify Link Doctor of the url truncation by sending of "?" at the end.
+ // Notify navigation correction service of the url truncation by sending of
+ // "?" at the end.
if (unreachable_url.has_query())
spec_to_send.append("?");
- std::string params(alt_error_page_url.query());
- params.append("&url=");
- params.append(net::EscapeQueryParamValue(spec_to_send, true));
- params.append("&sourceid=chrome");
- params.append("&error=");
- params.append(error_param);
+ // Assemble request body, which is a JSON string.
+ // TODO(mmenke): Investigate open sourcing the relevant protocol buffers and
+ // using those directly instead.
- // Build the final url to request.
- GURL::Replacements link_doctor_params;
- link_doctor_params.SetQueryStr(params);
- *error_page_url = alt_error_page_url.ReplaceComponents(link_doctor_params);
+ base::DictionaryValue request_dict;
+ request_dict.SetString("method", "linkdoctor.fixurl.fixurl");
+ request_dict.SetString("apiVersion", "v1");
+
+ base::DictionaryValue* params_dict = new base::DictionaryValue();
+ request_dict.Set("params", params_dict);
+
+ params_dict->SetString("key", api_key);
+ params_dict->SetString("urlQuery", spec_to_send);
+ params_dict->SetString("clientName", "chrome");
+ params_dict->SetString("error", error_param);
+
+ if (!language.empty())
+ params_dict->SetString("language", language);
+
+ if (!country_code.empty())
+ params_dict->SetString("originCountry", country_code);
+
+ base::JSONWriter::Write(&request_dict, correction_request_body);
return true;
}
+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;
+}
+
+LocalizedError::ErrorPageParams* ParseAdditionalSuggestions(
+ const std::string& data,
+ const GURL& original_url,
+ const GURL& search_url,
+ const std::string& accept_languages,
+ bool is_rtl) {
+ scoped_ptr<base::Value> parsed(base::JSONReader::Read(data));
+ if (!parsed)
+ return NULL;
+ // TODO(mmenke): Open source related protocol buffers and use them directly.
+ base::DictionaryValue* parsed_dict;
+ base::ListValue* corrections;
+ if (!parsed->GetAsDictionary(&parsed_dict))
+ return NULL;
+ if (!parsed_dict->GetList("result.UrlCorrections", &corrections))
+ return NULL;
+
+ // 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(original_url), 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 (base::ListValue::iterator it = corrections->begin();
+ it != corrections->end(); ++it) {
+ base::DictionaryValue* correction;
+ if (!(*it)->GetAsDictionary(&correction))
+ continue;
+
+ // Doesn't seem like a good idea to show these.
+ bool is_porn;
+ if (correction->GetBoolean("isPorn", &is_porn) && is_porn)
+ continue;
+ if (correction->GetBoolean("isSoftPorn", &is_porn) && is_porn)
+ continue;
+
+ std::string correction_type;
+ std::string url_correction;
+ if (!correction->GetString("correctionType", &correction_type) ||
+ !correction->GetString("urlCorrection", &url_correction)) {
+ continue;
+ }
+
+ std::string click_tracking_url;
+ correction->GetString("clickTrackingUrl", &click_tracking_url);
+
+ if (correction_type == "reloadPage") {
+ params->suggest_reload = true;
+ continue;
+ }
+
+ if (correction_type == "webSearchQuery") {
+ // If there are mutliple searches suggested, use the first suggestion.
+ if (params->search_terms.empty()) {
+ params->search_url = search_url;
+ params->search_terms = url_correction;
+ }
+ continue;
+ }
+
+ size_t correction_index;
+ for (correction_index = 0;
+ correction_index < arraysize(kCorrectionResourceTable);
+ ++correction_index) {
+ if (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",
+ !click_tracking_url.empty() ? click_tracking_url :
+ url_correction);
+ suggest->SetString(
+ "urlCorrectionForDisplay",
+ FormatURLForDisplay(GURL(url_correction), is_rtl, accept_languages));
+ suggest->SetString("originalUrlForDisplay", original_url_for_display);
+ params->override_suggestions->Append(suggest);
+ break;
+ }
+ }
+
+ if (params->override_suggestions->empty() &&
+ !params->search_url.is_valid()) {
+ return NULL;
+ }
+ return params.release();
+}
+
} // namespace
struct NetErrorHelperCore::ErrorPageInfo {
@@ -105,12 +254,18 @@
// probe status.
bool needs_dns_updates;
- // URL of an alternate error page to repace this error page with, if it's a
- // valid URL. Request will be issued when the error page finishes loading.
- // This is done on load complete to ensure that there are two complete loads
- // for tests to wait for.
- GURL alternate_error_page_url;
+ // Navigation correction service url, which will be used in response to
+ // certain types of network errors. This is also stored by the
+ // NetErrorHelperCore itself, but it stored here as well in case its modified
+ // in the middle of an error page load. Empty when no error page should be
+ // fetched, or if there's already a fetch in progress.
+ GURL navigation_correction_url;
+ // Request body to use when requesting corrections from a web service.
+ // TODO(mmenke): Investigate loading the error page at the same time as
+ // the blank page is loading, to get rid of these.
+ std::string navigation_correction_request_body;
+
// True if a page has completed loading, at which point it can receive
// updates.
bool is_finished_loading;
@@ -125,14 +280,19 @@
}
void NetErrorHelperCore::OnStop() {
- // On stop, 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_->alternate_error_page_url = GURL();
- if (pending_error_page_info_)
- pending_error_page_info_->alternate_error_page_url = GURL();
- delegate_->CancelFetchErrorPage();
+ // On stop, cancel loading navigation corrections, and prevent any
+ // pending error page load from starting to load corrections. Swapping in an
+ // error page once corrections are received could interrupt a navigation,
+ // otherwise.
+ if (committed_error_page_info_) {
+ committed_error_page_info_->navigation_correction_url = GURL();
+ committed_error_page_info_->navigation_correction_request_body.clear();
+ }
+ if (pending_error_page_info_) {
+ pending_error_page_info_->navigation_correction_url = GURL();
+ pending_error_page_info_->navigation_correction_request_body.clear();
+ }
+ delegate_->CancelFetchNavigationCorrections();
}
void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) {
@@ -159,14 +319,14 @@
committed_error_page_info_->is_finished_loading = true;
- if (committed_error_page_info_->alternate_error_page_url.is_valid()) {
- // If there is another pending error page load,
- // |replace_with_alternate_error_page| should have been set to false.
+ if (committed_error_page_info_->navigation_correction_url.is_valid()) {
+ // 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);
- GURL error_page_url;
- delegate_->FetchErrorPage(
- committed_error_page_info_->alternate_error_page_url);
+ delegate_->FetchNavigationCorrections(
+ committed_error_page_info_->navigation_correction_url,
+ committed_error_page_info_->navigation_correction_request_body);
}
if (!committed_error_page_info_->needs_dns_updates ||
@@ -183,11 +343,24 @@
bool is_failed_post,
std::string* error_html) {
if (frame_type == MAIN_FRAME) {
- // If an alternate error page was going to be fetched, that should have been
- // cancelled by loading a new page load (Which has now failed to load).
+ // 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_->alternate_error_page_url.is_valid());
+ !committed_error_page_info_->navigation_correction_url.is_valid());
+ std::string navigation_correction_request_body;
+
+ if (navigation_correction_url_.is_valid() &&
+ GetFixUrlRequestBody(error, language_, country_code_, api_key_,
+ &navigation_correction_request_body)) {
+ pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post));
+ pending_error_page_info_->navigation_correction_url =
+ navigation_correction_url_;
+ pending_error_page_info_->navigation_correction_request_body =
+ navigation_correction_request_body;
+ return;
+ }
+
// 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
@@ -195,38 +368,38 @@
// will just get the results for the next page load.
if (IsDnsError(error))
last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE;
-
- GURL error_page_url;
- if (GetErrorPageURL(error, alt_error_page_url_, &error_page_url)) {
- pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post));
- pending_error_page_info_->alternate_error_page_url = error_page_url;
- return;
- }
}
- GenerateLocalErrorPage(frame_type, error, is_failed_post, error_html);
+ GenerateLocalErrorPage(frame_type, error, is_failed_post,
+ scoped_ptr<LocalizedError::ErrorPageParams>(),
+ error_html);
}
void NetErrorHelperCore::GenerateLocalErrorPage(
FrameType frame_type,
const blink::WebURLError& error,
bool is_failed_post,
+ scoped_ptr<LocalizedError::ErrorPageParams> params,
std::string* error_html) {
if (frame_type == MAIN_FRAME) {
pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post));
- if (IsDnsError(error)) {
+ // Skip DNS logic if suggestions were received from a remote server.
+ if (IsDnsError(error) && !params) {
// This is not strictly necessary, but waiting for a new status to be
// sent as a result of the DidFinishLoading call keeps the histograms
// consistent with older versions of the code, at no real cost.
last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE;
delegate_->GenerateLocalizedErrorPage(
- GetUpdatedError(error), is_failed_post, error_html);
+ GetUpdatedError(error), is_failed_post, params.Pass(),
+ error_html);
pending_error_page_info_->needs_dns_updates = true;
return;
}
}
- delegate_->GenerateLocalizedErrorPage(error, is_failed_post, error_html);
+
+ delegate_->GenerateLocalizedErrorPage(error, is_failed_post,
+ params.Pass(), error_html);
}
void NetErrorHelperCore::OnNetErrorInfo(
@@ -244,6 +417,19 @@
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_url_ = navigation_correction_url;
+ language_ = language;
+ country_code_ = country_code;
+ api_key_ = api_key;
+ search_url_ = search_url;
+}
+
void NetErrorHelperCore::UpdateErrorPage() {
DCHECK(committed_error_page_info_->needs_dns_updates);
DCHECK(committed_error_page_info_->is_finished_loading);
@@ -263,30 +449,25 @@
committed_error_page_info_->was_failed_post);
}
-void NetErrorHelperCore::OnAlternateErrorPageFetched(const std::string& data) {
- // Alternate error page load only starts when an error page finishes loading,
- // and is cancelled with a new load
+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);
- const std::string* error_html = NULL;
- std::string generated_html;
- if (!data.empty()) {
- // If the request succeeded, use the response in place of a generated error
- // page.
- pending_error_page_info_.reset(
- new ErrorPageInfo(committed_error_page_info_->error,
- committed_error_page_info_->was_failed_post));
- error_html = &data;
- } else {
- // Otherwise, generate a local error page. |pending_error_page_info_| will
- // be set by GenerateLocalErrorPage.
- GenerateLocalErrorPage(MAIN_FRAME,
- committed_error_page_info_->error,
- committed_error_page_info_->was_failed_post,
- &generated_html);
- error_html = &generated_html;
- }
+ scoped_ptr<LocalizedError::ErrorPageParams> params(
+ ParseAdditionalSuggestions(
+ corrections, GURL(committed_error_page_info_->error.unreachableURL),
+ search_url_, accept_languages, is_rtl));
+ std::string error_html;
+ GenerateLocalErrorPage(MAIN_FRAME,
+ committed_error_page_info_->error,
+ committed_error_page_info_->was_failed_post,
+ params.Pass(),
+ &error_html);
// |error_page_info| may have been destroyed by this point, since
// |pending_error_page_info_| was set to a new ErrorPageInfo.
@@ -295,7 +476,7 @@
// double page load by just updating the error page, like DNS
// probes do.
delegate_->LoadErrorPageInMainFrame(
- *error_html,
+ error_html,
pending_error_page_info_->error.unreachableURL);
}
« no previous file with comments | « chrome/renderer/net/net_error_helper_core.h ('k') | chrome/renderer/net/net_error_helper_core_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698