OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/net/net_error_helper_core.h" | 5 #include "chrome/renderer/net/net_error_helper_core.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
| 9 #include "base/i18n/rtl.h" |
| 10 #include "base/json/json_reader.h" |
| 11 #include "base/json/json_writer.h" |
9 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/string16.h" |
| 14 #include "base/values.h" |
10 #include "chrome/common/localized_error.h" | 15 #include "chrome/common/localized_error.h" |
| 16 #include "grit/generated_resources.h" |
11 #include "net/base/escape.h" | 17 #include "net/base/escape.h" |
12 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 19 #include "net/base/net_util.h" |
13 #include "third_party/WebKit/public/platform/WebString.h" | 20 #include "third_party/WebKit/public/platform/WebString.h" |
14 #include "third_party/WebKit/public/platform/WebURLError.h" | 21 #include "third_party/WebKit/public/platform/WebURLError.h" |
| 22 #include "ui/base/l10n/l10n_util.h" |
15 #include "url/gurl.h" | 23 #include "url/gurl.h" |
16 | 24 |
17 namespace { | 25 namespace { |
18 | 26 |
| 27 struct CorrectionTypeToResourceTable { |
| 28 int resource_id; |
| 29 const char* correction_type; |
| 30 }; |
| 31 |
| 32 const CorrectionTypeToResourceTable kCorrectionResourceTable[] = { |
| 33 {IDS_ERRORPAGES_SUGGESTION_VISIT_GOOGLE_CACHE, "cachedPage"}, |
| 34 // "reloadPage" is has special handling. |
| 35 {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "urlCorrection"}, |
| 36 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "siteDomain"}, |
| 37 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "host"}, |
| 38 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "sitemap"}, |
| 39 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "pathParentFolder"}, |
| 40 // "siteSearchQuery" is not yet supported. |
| 41 // TODO(mmenke): Figure out what format "siteSearchQuery" uses for its |
| 42 // suggestions. |
| 43 // "webSearchQuery" has special handling. |
| 44 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "contentOverlap"}, |
| 45 {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "emphasizedUrlCorrection"}, |
| 46 }; |
| 47 |
19 // Returns whether |net_error| is a DNS-related error (and therefore whether | 48 // Returns whether |net_error| is a DNS-related error (and therefore whether |
20 // the tab helper should start a DNS probe after receiving it.) | 49 // the tab helper should start a DNS probe after receiving it.) |
21 bool IsDnsError(const blink::WebURLError& error) { | 50 bool IsDnsError(const blink::WebURLError& error) { |
22 return error.domain.utf8() == net::kErrorDomain && | 51 return error.domain.utf8() == net::kErrorDomain && |
23 (error.reason == net::ERR_NAME_NOT_RESOLVED || | 52 (error.reason == net::ERR_NAME_NOT_RESOLVED || |
24 error.reason == net::ERR_NAME_RESOLUTION_FAILED); | 53 error.reason == net::ERR_NAME_RESOLUTION_FAILED); |
25 } | 54 } |
26 | 55 |
27 // If an alternate error page should be retrieved remotely for a main frame load | 56 GURL SanitizeURL(const GURL& url) { |
28 // that failed with |error|, returns true and sets |error_page_url| to the URL | 57 GURL::Replacements remove_params; |
29 // of the remote error page. | 58 remove_params.ClearUsername(); |
30 bool GetErrorPageURL(const blink::WebURLError& error, | 59 remove_params.ClearPassword(); |
31 const GURL& alt_error_page_url, | 60 remove_params.ClearQuery(); |
32 GURL* error_page_url) { | 61 remove_params.ClearRef(); |
33 if (!alt_error_page_url.is_valid()) | 62 return url.ReplaceComponents(remove_params); |
34 return false; | 63 } |
35 | 64 |
36 // Parameter to send to the error page indicating the error type. | 65 // If URL correction information should be retrieved remotely for a main frame |
| 66 // load that failed with |error|, returns true and sets |
| 67 // |correction_request_body| to be the body for the correction request. |
| 68 bool GetFixUrlRequestBody(const blink::WebURLError& error, |
| 69 const std::string& language, |
| 70 const std::string& country_code, |
| 71 const std::string& api_key, |
| 72 std::string* correction_request_body) { |
| 73 // Parameter to send to the correction service indicating the error type. |
37 std::string error_param; | 74 std::string error_param; |
38 | 75 |
39 std::string domain = error.domain.utf8(); | 76 std::string domain = error.domain.utf8(); |
40 if (domain == "http" && error.reason == 404) { | 77 if (domain == "http" && error.reason == 404) { |
41 error_param = "http404"; | 78 error_param = "http404"; |
42 } else if (IsDnsError(error)) { | 79 } else if (IsDnsError(error)) { |
43 error_param = "dnserror"; | 80 error_param = "dnserror"; |
44 } else if (domain == net::kErrorDomain && | 81 } else if (domain == net::kErrorDomain && |
45 (error.reason == net::ERR_CONNECTION_FAILED || | 82 (error.reason == net::ERR_CONNECTION_FAILED || |
46 error.reason == net::ERR_CONNECTION_REFUSED || | 83 error.reason == net::ERR_CONNECTION_REFUSED || |
47 error.reason == net::ERR_ADDRESS_UNREACHABLE || | 84 error.reason == net::ERR_ADDRESS_UNREACHABLE || |
48 error.reason == net::ERR_CONNECTION_TIMED_OUT)) { | 85 error.reason == net::ERR_CONNECTION_TIMED_OUT)) { |
49 error_param = "connectionfailure"; | 86 error_param = "connectionFailure"; |
50 } else { | 87 } else { |
51 return false; | 88 return false; |
52 } | 89 } |
53 | 90 |
54 // Don't use the Link Doctor for HTTPS (for privacy reasons). | 91 // Don't use the correction service for HTTPS (for privacy reasons). |
55 GURL unreachable_url(error.unreachableURL); | 92 GURL unreachable_url(error.unreachableURL); |
56 if (unreachable_url.SchemeIsSecure()) | 93 if (unreachable_url.SchemeIsSecure()) |
57 return false; | 94 return false; |
58 | 95 |
59 // Sanitize the unreachable URL. | 96 // TODO(yuusuke): Change to net::FormatUrl when Link Doctor becomes |
60 GURL::Replacements remove_params; | |
61 remove_params.ClearUsername(); | |
62 remove_params.ClearPassword(); | |
63 remove_params.ClearQuery(); | |
64 remove_params.ClearRef(); | |
65 // TODO(yuusuke): change to net::FormatUrl when Link Doctor becomes | |
66 // unicode-capable. | 97 // unicode-capable. |
67 std::string spec_to_send = | 98 std::string spec_to_send = SanitizeURL(unreachable_url).spec(); |
68 unreachable_url.ReplaceComponents(remove_params).spec(); | |
69 | 99 |
70 // Notify Link Doctor of the url truncation by sending of "?" at the end. | 100 // Notify navigation correction service of the url truncation by sending of |
| 101 // "?" at the end. |
71 if (unreachable_url.has_query()) | 102 if (unreachable_url.has_query()) |
72 spec_to_send.append("?"); | 103 spec_to_send.append("?"); |
73 | 104 |
74 std::string params(alt_error_page_url.query()); | 105 // Assemble request body, which is a JSON string. |
75 params.append("&url="); | 106 // TODO(mmenke): Investigate open sourcing the relevant protocol buffers and |
76 params.append(net::EscapeQueryParamValue(spec_to_send, true)); | 107 // using those directly instead. |
77 params.append("&sourceid=chrome"); | |
78 params.append("&error="); | |
79 params.append(error_param); | |
80 | 108 |
81 // Build the final url to request. | 109 base::DictionaryValue request_dict; |
82 GURL::Replacements link_doctor_params; | 110 request_dict.SetString("method", "linkdoctor.fixurl.fixurl"); |
83 link_doctor_params.SetQueryStr(params); | 111 request_dict.SetString("apiVersion", "v1"); |
84 *error_page_url = alt_error_page_url.ReplaceComponents(link_doctor_params); | 112 |
| 113 base::DictionaryValue* params_dict = new base::DictionaryValue(); |
| 114 request_dict.Set("params", params_dict); |
| 115 |
| 116 params_dict->SetString("key", api_key); |
| 117 params_dict->SetString("urlQuery", spec_to_send); |
| 118 params_dict->SetString("clientName", "chrome"); |
| 119 params_dict->SetString("error", error_param); |
| 120 |
| 121 if (!language.empty()) |
| 122 params_dict->SetString("language", language); |
| 123 |
| 124 if (!country_code.empty()) |
| 125 params_dict->SetString("originCountry", country_code); |
| 126 |
| 127 base::JSONWriter::Write(&request_dict, correction_request_body); |
85 return true; | 128 return true; |
86 } | 129 } |
87 | 130 |
| 131 base::string16 FormatURLForDisplay(const GURL& url, bool is_rtl, |
| 132 const std::string accept_languages) { |
| 133 // Translate punycode into UTF8, unescape UTF8 URLs. |
| 134 base::string16 url_for_display(net::FormatUrl( |
| 135 url, accept_languages, net::kFormatUrlOmitNothing, |
| 136 net::UnescapeRule::NORMAL, NULL, NULL, NULL)); |
| 137 // URLs are always LTR. |
| 138 if (is_rtl) |
| 139 base::i18n::WrapStringWithLTRFormatting(&url_for_display); |
| 140 return url_for_display; |
| 141 } |
| 142 |
| 143 LocalizedError::ErrorPageParams* ParseAdditionalSuggestions( |
| 144 const std::string& data, |
| 145 const GURL& original_url, |
| 146 const GURL& search_url, |
| 147 const std::string& accept_languages, |
| 148 bool is_rtl) { |
| 149 scoped_ptr<base::Value> parsed(base::JSONReader::Read(data)); |
| 150 if (!parsed) |
| 151 return NULL; |
| 152 // TODO(mmenke): Open source related protocol buffers and use them directly. |
| 153 base::DictionaryValue* parsed_dict; |
| 154 base::ListValue* corrections; |
| 155 if (!parsed->GetAsDictionary(&parsed_dict)) |
| 156 return NULL; |
| 157 if (!parsed_dict->GetList("result.UrlCorrections", &corrections)) |
| 158 return NULL; |
| 159 |
| 160 // Version of URL for display in suggestions. It has to be sanitized first |
| 161 // because any received suggestions will be relative to the sanitized URL. |
| 162 base::string16 original_url_for_display = |
| 163 FormatURLForDisplay(SanitizeURL(original_url), is_rtl, accept_languages); |
| 164 |
| 165 scoped_ptr<LocalizedError::ErrorPageParams> params( |
| 166 new LocalizedError::ErrorPageParams()); |
| 167 params->override_suggestions.reset(new base::ListValue()); |
| 168 scoped_ptr<base::ListValue> parsed_corrections(new base::ListValue()); |
| 169 for (base::ListValue::iterator it = corrections->begin(); |
| 170 it != corrections->end(); ++it) { |
| 171 base::DictionaryValue* correction; |
| 172 if (!(*it)->GetAsDictionary(&correction)) |
| 173 continue; |
| 174 |
| 175 // Doesn't seem like a good idea to show these. |
| 176 bool is_porn; |
| 177 if (correction->GetBoolean("isPorn", &is_porn) && is_porn) |
| 178 continue; |
| 179 if (correction->GetBoolean("isSoftPorn", &is_porn) && is_porn) |
| 180 continue; |
| 181 |
| 182 std::string correction_type; |
| 183 std::string url_correction; |
| 184 if (!correction->GetString("correctionType", &correction_type) || |
| 185 !correction->GetString("urlCorrection", &url_correction)) { |
| 186 continue; |
| 187 } |
| 188 |
| 189 std::string click_tracking_url; |
| 190 correction->GetString("clickTrackingUrl", &click_tracking_url); |
| 191 |
| 192 if (correction_type == "reloadPage") { |
| 193 params->suggest_reload = true; |
| 194 continue; |
| 195 } |
| 196 |
| 197 if (correction_type == "webSearchQuery") { |
| 198 // If there are mutliple searches suggested, use the first suggestion. |
| 199 if (params->search_terms.empty()) { |
| 200 params->search_url = search_url; |
| 201 params->search_terms = url_correction; |
| 202 } |
| 203 continue; |
| 204 } |
| 205 |
| 206 size_t correction_index; |
| 207 for (correction_index = 0; |
| 208 correction_index < arraysize(kCorrectionResourceTable); |
| 209 ++correction_index) { |
| 210 if (correction_type != |
| 211 kCorrectionResourceTable[correction_index].correction_type) { |
| 212 continue; |
| 213 } |
| 214 base::DictionaryValue* suggest = new base::DictionaryValue(); |
| 215 suggest->SetString("header", |
| 216 l10n_util::GetStringUTF16( |
| 217 kCorrectionResourceTable[correction_index].resource_id)); |
| 218 suggest->SetString("urlCorrection", |
| 219 !click_tracking_url.empty() ? click_tracking_url : |
| 220 url_correction); |
| 221 suggest->SetString( |
| 222 "urlCorrectionForDisplay", |
| 223 FormatURLForDisplay(GURL(url_correction), is_rtl, accept_languages)); |
| 224 suggest->SetString("originalUrlForDisplay", original_url_for_display); |
| 225 params->override_suggestions->Append(suggest); |
| 226 break; |
| 227 } |
| 228 } |
| 229 |
| 230 if (params->override_suggestions->empty() && |
| 231 !params->search_url.is_valid()) { |
| 232 return NULL; |
| 233 } |
| 234 return params.release(); |
| 235 } |
| 236 |
88 } // namespace | 237 } // namespace |
89 | 238 |
90 struct NetErrorHelperCore::ErrorPageInfo { | 239 struct NetErrorHelperCore::ErrorPageInfo { |
91 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) | 240 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) |
92 : error(error), | 241 : error(error), |
93 was_failed_post(was_failed_post), | 242 was_failed_post(was_failed_post), |
94 needs_dns_updates(false), | 243 needs_dns_updates(false), |
95 is_finished_loading(false) { | 244 is_finished_loading(false) { |
96 } | 245 } |
97 | 246 |
98 // Information about the failed page load. | 247 // Information about the failed page load. |
99 blink::WebURLError error; | 248 blink::WebURLError error; |
100 bool was_failed_post; | 249 bool was_failed_post; |
101 | 250 |
102 // Information about the status of the error page. | 251 // Information about the status of the error page. |
103 | 252 |
104 // True if a page is a DNS error page and has not yet received a final DNS | 253 // True if a page is a DNS error page and has not yet received a final DNS |
105 // probe status. | 254 // probe status. |
106 bool needs_dns_updates; | 255 bool needs_dns_updates; |
107 | 256 |
108 // URL of an alternate error page to repace this error page with, if it's a | 257 // Navigation correction service url, which will be used in response to |
109 // valid URL. Request will be issued when the error page finishes loading. | 258 // certain types of network errors. This is also stored by the |
110 // This is done on load complete to ensure that there are two complete loads | 259 // NetErrorHelperCore itself, but it stored here as well in case its modified |
111 // for tests to wait for. | 260 // in the middle of an error page load. Empty when no error page should be |
112 GURL alternate_error_page_url; | 261 // fetched, or if there's already a fetch in progress. |
| 262 GURL navigation_correction_url; |
| 263 |
| 264 // Request body to use when requesting corrections from a web service. |
| 265 // TODO(mmenke): Investigate loading the error page at the same time as |
| 266 // the blank page is loading, to get rid of these. |
| 267 std::string navigation_correction_request_body; |
113 | 268 |
114 // True if a page has completed loading, at which point it can receive | 269 // True if a page has completed loading, at which point it can receive |
115 // updates. | 270 // updates. |
116 bool is_finished_loading; | 271 bool is_finished_loading; |
117 }; | 272 }; |
118 | 273 |
119 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 274 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) |
120 : delegate_(delegate), | 275 : delegate_(delegate), |
121 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { | 276 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { |
122 } | 277 } |
123 | 278 |
124 NetErrorHelperCore::~NetErrorHelperCore() { | 279 NetErrorHelperCore::~NetErrorHelperCore() { |
125 } | 280 } |
126 | 281 |
127 void NetErrorHelperCore::OnStop() { | 282 void NetErrorHelperCore::OnStop() { |
128 // On stop, cancel loading the alternate error page, and prevent any pending | 283 // On stop, cancel loading navigation corrections, and prevent any |
129 // error page load from starting a new error page load. Swapping in the error | 284 // pending error page load from starting to load corrections. Swapping in an |
130 // page when it's finished loading could abort the navigation, otherwise. | 285 // error page once corrections are received could interrupt a navigation, |
131 if (committed_error_page_info_) | 286 // otherwise. |
132 committed_error_page_info_->alternate_error_page_url = GURL(); | 287 if (committed_error_page_info_) { |
133 if (pending_error_page_info_) | 288 committed_error_page_info_->navigation_correction_url = GURL(); |
134 pending_error_page_info_->alternate_error_page_url = GURL(); | 289 committed_error_page_info_->navigation_correction_request_body.clear(); |
135 delegate_->CancelFetchErrorPage(); | 290 } |
| 291 if (pending_error_page_info_) { |
| 292 pending_error_page_info_->navigation_correction_url = GURL(); |
| 293 pending_error_page_info_->navigation_correction_request_body.clear(); |
| 294 } |
| 295 delegate_->CancelFetchNavigationCorrections(); |
136 } | 296 } |
137 | 297 |
138 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { | 298 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { |
139 if (frame_type != MAIN_FRAME) | 299 if (frame_type != MAIN_FRAME) |
140 return; | 300 return; |
141 | 301 |
142 // If there's no pending error page information associated with the page load, | 302 // If there's no pending error page information associated with the page load, |
143 // or the new page is not an error page, then reset pending error page state. | 303 // or the new page is not an error page, then reset pending error page state. |
144 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { | 304 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { |
145 OnStop(); | 305 OnStop(); |
146 } | 306 } |
147 } | 307 } |
148 | 308 |
149 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 309 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { |
150 if (frame_type != MAIN_FRAME) | 310 if (frame_type != MAIN_FRAME) |
151 return; | 311 return; |
152 | 312 |
153 committed_error_page_info_.reset(pending_error_page_info_.release()); | 313 committed_error_page_info_.reset(pending_error_page_info_.release()); |
154 } | 314 } |
155 | 315 |
156 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 316 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
157 if (frame_type != MAIN_FRAME || !committed_error_page_info_) | 317 if (frame_type != MAIN_FRAME || !committed_error_page_info_) |
158 return; | 318 return; |
159 | 319 |
160 committed_error_page_info_->is_finished_loading = true; | 320 committed_error_page_info_->is_finished_loading = true; |
161 | 321 |
162 if (committed_error_page_info_->alternate_error_page_url.is_valid()) { | 322 if (committed_error_page_info_->navigation_correction_url.is_valid()) { |
163 // If there is another pending error page load, | 323 // If there is another pending error page load, |fix_url| should have been |
164 // |replace_with_alternate_error_page| should have been set to false. | 324 // cleared. |
165 DCHECK(!pending_error_page_info_); | 325 DCHECK(!pending_error_page_info_); |
166 DCHECK(!committed_error_page_info_->needs_dns_updates); | 326 DCHECK(!committed_error_page_info_->needs_dns_updates); |
167 GURL error_page_url; | 327 delegate_->FetchNavigationCorrections( |
168 delegate_->FetchErrorPage( | 328 committed_error_page_info_->navigation_correction_url, |
169 committed_error_page_info_->alternate_error_page_url); | 329 committed_error_page_info_->navigation_correction_request_body); |
170 } | 330 } |
171 | 331 |
172 if (!committed_error_page_info_->needs_dns_updates || | 332 if (!committed_error_page_info_->needs_dns_updates || |
173 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { | 333 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { |
174 return; | 334 return; |
175 } | 335 } |
176 DVLOG(1) << "Error page finished loading; sending saved status."; | 336 DVLOG(1) << "Error page finished loading; sending saved status."; |
177 UpdateErrorPage(); | 337 UpdateErrorPage(); |
178 } | 338 } |
179 | 339 |
180 void NetErrorHelperCore::GetErrorHTML( | 340 void NetErrorHelperCore::GetErrorHTML( |
181 FrameType frame_type, | 341 FrameType frame_type, |
182 const blink::WebURLError& error, | 342 const blink::WebURLError& error, |
183 bool is_failed_post, | 343 bool is_failed_post, |
184 std::string* error_html) { | 344 std::string* error_html) { |
185 if (frame_type == MAIN_FRAME) { | 345 if (frame_type == MAIN_FRAME) { |
186 // If an alternate error page was going to be fetched, that should have been | 346 // If navigation corrections were needed before, that should have been |
187 // cancelled by loading a new page load (Which has now failed to load). | 347 // cancelled earlier by starting a new page load (Which has now failed). |
188 DCHECK(!committed_error_page_info_ || | 348 DCHECK(!committed_error_page_info_ || |
189 !committed_error_page_info_->alternate_error_page_url.is_valid()); | 349 !committed_error_page_info_->navigation_correction_url.is_valid()); |
| 350 |
| 351 std::string navigation_correction_request_body; |
| 352 |
| 353 if (navigation_correction_url_.is_valid() && |
| 354 GetFixUrlRequestBody(error, language_, country_code_, api_key_, |
| 355 &navigation_correction_request_body)) { |
| 356 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); |
| 357 pending_error_page_info_->navigation_correction_url = |
| 358 navigation_correction_url_; |
| 359 pending_error_page_info_->navigation_correction_request_body = |
| 360 navigation_correction_request_body; |
| 361 return; |
| 362 } |
190 | 363 |
191 // The last probe status needs to be reset if this is a DNS error. This | 364 // The last probe status needs to be reset if this is a DNS error. This |
192 // means that if a DNS error page is committed but has not yet finished | 365 // means that if a DNS error page is committed but has not yet finished |
193 // loading, a DNS probe status scheduled to be sent to it may be thrown | 366 // loading, a DNS probe status scheduled to be sent to it may be thrown |
194 // out, but since the new error page should trigger a new DNS probe, it | 367 // out, but since the new error page should trigger a new DNS probe, it |
195 // will just get the results for the next page load. | 368 // will just get the results for the next page load. |
196 if (IsDnsError(error)) | 369 if (IsDnsError(error)) |
197 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; | 370 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; |
198 | |
199 GURL error_page_url; | |
200 if (GetErrorPageURL(error, alt_error_page_url_, &error_page_url)) { | |
201 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); | |
202 pending_error_page_info_->alternate_error_page_url = error_page_url; | |
203 return; | |
204 } | |
205 } | 371 } |
206 | 372 |
207 GenerateLocalErrorPage(frame_type, error, is_failed_post, error_html); | 373 GenerateLocalErrorPage(frame_type, error, is_failed_post, |
| 374 scoped_ptr<LocalizedError::ErrorPageParams>(), |
| 375 error_html); |
208 } | 376 } |
209 | 377 |
210 void NetErrorHelperCore::GenerateLocalErrorPage( | 378 void NetErrorHelperCore::GenerateLocalErrorPage( |
211 FrameType frame_type, | 379 FrameType frame_type, |
212 const blink::WebURLError& error, | 380 const blink::WebURLError& error, |
213 bool is_failed_post, | 381 bool is_failed_post, |
| 382 scoped_ptr<LocalizedError::ErrorPageParams> params, |
214 std::string* error_html) { | 383 std::string* error_html) { |
215 if (frame_type == MAIN_FRAME) { | 384 if (frame_type == MAIN_FRAME) { |
216 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); | 385 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); |
217 if (IsDnsError(error)) { | 386 // Skip DNS logic if suggestions were received from a remote server. |
| 387 if (IsDnsError(error) && !params) { |
218 // This is not strictly necessary, but waiting for a new status to be | 388 // This is not strictly necessary, but waiting for a new status to be |
219 // sent as a result of the DidFinishLoading call keeps the histograms | 389 // sent as a result of the DidFinishLoading call keeps the histograms |
220 // consistent with older versions of the code, at no real cost. | 390 // consistent with older versions of the code, at no real cost. |
221 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; | 391 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; |
222 | 392 |
223 delegate_->GenerateLocalizedErrorPage( | 393 delegate_->GenerateLocalizedErrorPage( |
224 GetUpdatedError(error), is_failed_post, error_html); | 394 GetUpdatedError(error), is_failed_post, params.Pass(), |
| 395 error_html); |
225 pending_error_page_info_->needs_dns_updates = true; | 396 pending_error_page_info_->needs_dns_updates = true; |
226 return; | 397 return; |
227 } | 398 } |
228 } | 399 } |
229 delegate_->GenerateLocalizedErrorPage(error, is_failed_post, error_html); | 400 |
| 401 delegate_->GenerateLocalizedErrorPage(error, is_failed_post, |
| 402 params.Pass(), error_html); |
230 } | 403 } |
231 | 404 |
232 void NetErrorHelperCore::OnNetErrorInfo( | 405 void NetErrorHelperCore::OnNetErrorInfo( |
233 chrome_common_net::DnsProbeStatus status) { | 406 chrome_common_net::DnsProbeStatus status) { |
234 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); | 407 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); |
235 | 408 |
236 last_probe_status_ = status; | 409 last_probe_status_ = status; |
237 | 410 |
238 if (!committed_error_page_info_ || | 411 if (!committed_error_page_info_ || |
239 !committed_error_page_info_->needs_dns_updates || | 412 !committed_error_page_info_->needs_dns_updates || |
240 !committed_error_page_info_->is_finished_loading) { | 413 !committed_error_page_info_->is_finished_loading) { |
241 return; | 414 return; |
242 } | 415 } |
243 | 416 |
244 UpdateErrorPage(); | 417 UpdateErrorPage(); |
245 } | 418 } |
246 | 419 |
| 420 void NetErrorHelperCore::OnSetNavigationCorrectionInfo( |
| 421 const GURL& navigation_correction_url, |
| 422 const std::string& language, |
| 423 const std::string& country_code, |
| 424 const std::string& api_key, |
| 425 const GURL& search_url) { |
| 426 navigation_correction_url_ = navigation_correction_url; |
| 427 language_ = language; |
| 428 country_code_ = country_code; |
| 429 api_key_ = api_key; |
| 430 search_url_ = search_url; |
| 431 } |
| 432 |
247 void NetErrorHelperCore::UpdateErrorPage() { | 433 void NetErrorHelperCore::UpdateErrorPage() { |
248 DCHECK(committed_error_page_info_->needs_dns_updates); | 434 DCHECK(committed_error_page_info_->needs_dns_updates); |
249 DCHECK(committed_error_page_info_->is_finished_loading); | 435 DCHECK(committed_error_page_info_->is_finished_loading); |
250 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_probe_status_); | 436 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_probe_status_); |
251 | 437 |
252 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", | 438 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", |
253 last_probe_status_, | 439 last_probe_status_, |
254 chrome_common_net::DNS_PROBE_MAX); | 440 chrome_common_net::DNS_PROBE_MAX); |
255 // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a | 441 // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a |
256 // final status code. Once one is reached, the page does not need further | 442 // final status code. Once one is reached, the page does not need further |
257 // updates. | 443 // updates. |
258 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) | 444 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) |
259 committed_error_page_info_->needs_dns_updates = false; | 445 committed_error_page_info_->needs_dns_updates = false; |
260 | 446 |
261 delegate_->UpdateErrorPage( | 447 delegate_->UpdateErrorPage( |
262 GetUpdatedError(committed_error_page_info_->error), | 448 GetUpdatedError(committed_error_page_info_->error), |
263 committed_error_page_info_->was_failed_post); | 449 committed_error_page_info_->was_failed_post); |
264 } | 450 } |
265 | 451 |
266 void NetErrorHelperCore::OnAlternateErrorPageFetched(const std::string& data) { | 452 void NetErrorHelperCore::OnNavigationCorrectionsFetched( |
267 // Alternate error page load only starts when an error page finishes loading, | 453 const std::string& corrections, |
268 // and is cancelled with a new load | 454 const std::string& accept_languages, |
| 455 bool is_rtl) { |
| 456 // Loading suggestions only starts when a blank error page finishes loading, |
| 457 // and is cancelled with a new load. |
269 DCHECK(!pending_error_page_info_); | 458 DCHECK(!pending_error_page_info_); |
270 DCHECK(committed_error_page_info_->is_finished_loading); | 459 DCHECK(committed_error_page_info_->is_finished_loading); |
271 | 460 |
272 const std::string* error_html = NULL; | 461 scoped_ptr<LocalizedError::ErrorPageParams> params( |
273 std::string generated_html; | 462 ParseAdditionalSuggestions( |
274 if (!data.empty()) { | 463 corrections, GURL(committed_error_page_info_->error.unreachableURL), |
275 // If the request succeeded, use the response in place of a generated error | 464 search_url_, accept_languages, is_rtl)); |
276 // page. | 465 std::string error_html; |
277 pending_error_page_info_.reset( | 466 GenerateLocalErrorPage(MAIN_FRAME, |
278 new ErrorPageInfo(committed_error_page_info_->error, | 467 committed_error_page_info_->error, |
279 committed_error_page_info_->was_failed_post)); | 468 committed_error_page_info_->was_failed_post, |
280 error_html = &data; | 469 params.Pass(), |
281 } else { | 470 &error_html); |
282 // Otherwise, generate a local error page. |pending_error_page_info_| will | |
283 // be set by GenerateLocalErrorPage. | |
284 GenerateLocalErrorPage(MAIN_FRAME, | |
285 committed_error_page_info_->error, | |
286 committed_error_page_info_->was_failed_post, | |
287 &generated_html); | |
288 error_html = &generated_html; | |
289 } | |
290 | 471 |
291 // |error_page_info| may have been destroyed by this point, since | 472 // |error_page_info| may have been destroyed by this point, since |
292 // |pending_error_page_info_| was set to a new ErrorPageInfo. | 473 // |pending_error_page_info_| was set to a new ErrorPageInfo. |
293 | 474 |
294 // TODO(mmenke): Once the new API is in place, look into replacing this | 475 // TODO(mmenke): Once the new API is in place, look into replacing this |
295 // double page load by just updating the error page, like DNS | 476 // double page load by just updating the error page, like DNS |
296 // probes do. | 477 // probes do. |
297 delegate_->LoadErrorPageInMainFrame( | 478 delegate_->LoadErrorPageInMainFrame( |
298 *error_html, | 479 error_html, |
299 pending_error_page_info_->error.unreachableURL); | 480 pending_error_page_info_->error.unreachableURL); |
300 } | 481 } |
301 | 482 |
302 blink::WebURLError NetErrorHelperCore::GetUpdatedError( | 483 blink::WebURLError NetErrorHelperCore::GetUpdatedError( |
303 const blink::WebURLError& error) const { | 484 const blink::WebURLError& error) const { |
304 // If a probe didn't run or wasn't conclusive, restore the original error. | 485 // If a probe didn't run or wasn't conclusive, restore the original error. |
305 if (last_probe_status_ == chrome_common_net::DNS_PROBE_NOT_RUN || | 486 if (last_probe_status_ == chrome_common_net::DNS_PROBE_NOT_RUN || |
306 last_probe_status_ == | 487 last_probe_status_ == |
307 chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE) { | 488 chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE) { |
308 return error; | 489 return error; |
309 } | 490 } |
310 | 491 |
311 blink::WebURLError updated_error; | 492 blink::WebURLError updated_error; |
312 updated_error.domain = blink::WebString::fromUTF8( | 493 updated_error.domain = blink::WebString::fromUTF8( |
313 chrome_common_net::kDnsProbeErrorDomain); | 494 chrome_common_net::kDnsProbeErrorDomain); |
314 updated_error.reason = last_probe_status_; | 495 updated_error.reason = last_probe_status_; |
315 updated_error.unreachableURL = error.unreachableURL; | 496 updated_error.unreachableURL = error.unreachableURL; |
316 updated_error.staleCopyInCache = error.staleCopyInCache; | 497 updated_error.staleCopyInCache = error.staleCopyInCache; |
317 | 498 |
318 return updated_error; | 499 return updated_error; |
319 } | 500 } |
OLD | NEW |