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 |
65 // If URL correction information should be retrieved remotely for a main frame | |
66 // load that failed with |error|, returns true and sets | |
67 // |fix_url_request_body| to be the body for the correcion 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* fix_url_request_body) { | |
36 // Parameter to send to the error page indicating the error type. | 73 // Parameter to send to the error page 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 Link Doctor 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 Link Doctor of the url truncation by sending of "?" at the end. |
71 if (unreachable_url.has_query()) | 101 if (unreachable_url.has_query()) |
72 spec_to_send.append("?"); | 102 spec_to_send.append("?"); |
73 | 103 |
74 std::string params(alt_error_page_url.query()); | 104 // Assemble request body, which is a JSON string. |
75 params.append("&url="); | 105 // TODO(mmenke): Investigate open sourcing the relevant protocol buffers and |
76 params.append(net::EscapeQueryParamValue(spec_to_send, true)); | 106 // using those directly instead. |
77 params.append("&sourceid=chrome"); | |
78 params.append("&error="); | |
79 params.append(error_param); | |
80 | 107 |
81 // Build the final url to request. | 108 base::DictionaryValue request_dict; |
82 GURL::Replacements link_doctor_params; | 109 request_dict.SetString("method", "linkdoctor.fixurl.fixurl"); |
83 link_doctor_params.SetQueryStr(params); | 110 request_dict.SetString("apiVersion", "v1"); |
84 *error_page_url = alt_error_page_url.ReplaceComponents(link_doctor_params); | 111 |
112 base::DictionaryValue* params_dict = new base::DictionaryValue(); | |
113 request_dict.Set("params", params_dict); | |
114 | |
115 params_dict->SetString("key", api_key); | |
116 params_dict->SetString("urlQuery", spec_to_send); | |
117 params_dict->SetString("clientName", "chrome"); | |
118 params_dict->SetString("error", error_param); | |
119 | |
120 if (!language.empty()) | |
121 params_dict->SetString("language", language); | |
122 | |
123 // TODO(mmenke): Figure out if the originCountry can be set correctly. | |
124 // locale.getCountry() just seems to give the default country | |
125 // for the language resources currently in use. | |
126 | |
127 if (!country_code.empty()) | |
128 params_dict->SetString("originCountry", country_code); | |
129 | |
130 base::JSONWriter::Write(&request_dict, fix_url_request_body); | |
85 return true; | 131 return true; |
86 } | 132 } |
87 | 133 |
134 base::string16 FormatURLForDisplay(const GURL& url, bool is_rtl, | |
135 const std::string accept_languages) { | |
136 // Translate punycode into UTF8, unescape UTF8 URLs. | |
137 base::string16 url_for_display(net::FormatUrl( | |
138 url, accept_languages, net::kFormatUrlOmitNothing, | |
139 net::UnescapeRule::NORMAL, NULL, NULL, NULL)); | |
140 // URLs are always LTR. | |
141 if (is_rtl) | |
142 base::i18n::WrapStringWithLTRFormatting(&url_for_display); | |
143 return url_for_display; | |
144 } | |
145 | |
146 LocalizedError::ErrorPageParams* ParseAdditionalSuggestions( | |
147 const std::string& data, | |
148 const GURL& original_url, | |
149 const GURL& search_url, | |
150 const std::string& accept_languages, | |
151 bool is_rtl) { | |
152 scoped_ptr<base::Value> parsed(base::JSONReader::Read(data)); | |
153 if (!parsed) | |
154 return NULL; | |
155 // TODO(mmenke): Open source related protocol buffers and use them directly. | |
156 base::DictionaryValue* parsed_dict; | |
157 base::ListValue* corrections; | |
158 if (!parsed->GetAsDictionary(&parsed_dict)) | |
159 return NULL; | |
160 if (!parsed_dict->GetList("result.UrlCorrections", &corrections)) | |
161 return NULL; | |
162 | |
163 // Version of URL for display in suggestions. It has to be sanitized first | |
164 // because any received suggestions will be relative to the sanitized URL. | |
165 base::string16 original_url_for_display = | |
166 FormatURLForDisplay(SanitizeURL(original_url), is_rtl, accept_languages); | |
167 | |
168 scoped_ptr<LocalizedError::ErrorPageParams> params( | |
169 new LocalizedError::ErrorPageParams()); | |
170 params->override_suggestions.reset(new base::ListValue()); | |
171 scoped_ptr<base::ListValue> parsed_corrections(new base::ListValue()); | |
172 for (base::ListValue::iterator it = corrections->begin(); | |
173 it != corrections->end(); ++it) { | |
174 base::DictionaryValue* correction; | |
175 if (!(*it)->GetAsDictionary(&correction)) | |
176 continue; | |
177 | |
178 // Doesn't seem like a good idea to show these. | |
Deprecated (see juliatuttle)
2014/02/04 17:44:21
What if that's what the user was looking for? (Is
mmenke
2014/02/04 19:43:56
In my experience, FixURL isn't really that clever.
Deprecated (see juliatuttle)
2014/02/04 20:20:20
Alright. I'll tinker with it and see how clever i
mmenke
2014/02/04 20:31:09
May also want to see if we're already excluding po
| |
179 bool is_porn; | |
180 if (correction->GetBoolean("isPorn", &is_porn) && is_porn) | |
181 continue; | |
182 if (correction->GetBoolean("isSoftPorn", &is_porn) && is_porn) | |
183 continue; | |
184 | |
185 std::string correction_type; | |
186 std::string url_correction; | |
187 if (!correction->GetString("correctionType", &correction_type) || | |
188 !correction->GetString("urlCorrection", &url_correction)) { | |
189 continue; | |
190 } | |
191 | |
192 std::string click_tracking_url; | |
193 correction->GetString("clickTrackingUrl", &click_tracking_url); | |
194 | |
195 if (correction_type == "reloadPage") { | |
196 params->suggest_reload = true; | |
197 continue; | |
198 } | |
199 | |
200 if (correction_type == "webSearchQuery") { | |
201 // If there are mutliple searches suggested, use the first suggestion. | |
202 if (params->search_terms.empty()) { | |
203 params->search_url = search_url; | |
204 params->search_terms = url_correction; | |
205 } | |
206 continue; | |
207 } | |
208 | |
209 size_t correction_index; | |
210 for (correction_index = 0; | |
211 correction_index < arraysize(kCorrectionResourceTable); | |
212 ++correction_index) { | |
213 if (correction_type != | |
214 kCorrectionResourceTable[correction_index].correction_type) { | |
215 continue; | |
216 } | |
217 base::DictionaryValue* suggest = new base::DictionaryValue(); | |
218 suggest->SetString("header", | |
219 l10n_util::GetStringUTF16( | |
220 kCorrectionResourceTable[correction_index].resource_id)); | |
221 suggest->SetString("urlCorrection", | |
222 !click_tracking_url.empty() ? click_tracking_url : | |
223 url_correction); | |
224 suggest->SetString( | |
225 "urlCorrectionForDisplay", | |
226 FormatURLForDisplay(GURL(url_correction), is_rtl, accept_languages)); | |
227 suggest->SetString("originalUrlForDisplay", original_url_for_display); | |
228 params->override_suggestions->Append(suggest); | |
229 break; | |
230 } | |
231 } | |
232 | |
233 if (params->override_suggestions->empty() && | |
234 !params->search_url.is_valid()) { | |
235 return NULL; | |
236 } | |
237 return params.release(); | |
238 } | |
239 | |
88 } // namespace | 240 } // namespace |
89 | 241 |
90 struct NetErrorHelperCore::ErrorPageInfo { | 242 struct NetErrorHelperCore::ErrorPageInfo { |
91 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) | 243 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) |
92 : error(error), | 244 : error(error), |
93 was_failed_post(was_failed_post), | 245 was_failed_post(was_failed_post), |
94 needs_dns_updates(false), | 246 needs_dns_updates(false), |
95 is_finished_loading(false) { | 247 is_finished_loading(false) { |
96 } | 248 } |
97 | 249 |
98 // Information about the failed page load. | 250 // Information about the failed page load. |
99 blink::WebURLError error; | 251 blink::WebURLError error; |
100 bool was_failed_post; | 252 bool was_failed_post; |
101 | 253 |
102 // Information about the status of the error page. | 254 // Information about the status of the error page. |
103 | 255 |
104 // True if a page is a DNS error page and has not yet received a final DNS | 256 // True if a page is a DNS error page and has not yet received a final DNS |
105 // probe status. | 257 // probe status. |
106 bool needs_dns_updates; | 258 bool needs_dns_updates; |
107 | 259 |
108 // URL of an alternate error page to repace this error page with, if it's a | 260 // URL of the FixURL service, which will be used to request suggestions on |
109 // valid URL. Request will be issued when the error page finishes loading. | 261 // 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 | 262 // NetErrorHelperCore itself, but it stored here as well in case its modified |
111 // for tests to wait for. | 263 // in the middle of an error page load. Empty when no error page should be |
112 GURL alternate_error_page_url; | 264 // fetched, or if there's already a fetch in progress. |
265 GURL link_doctor_url; | |
266 | |
267 // Request body to use when requesting suggestions from the FixURL service. | |
268 // TODO(mmenke): Investigate loading the error page at the same time as | |
269 // the blank page is loading, to get rid of these. | |
270 std::string link_doctor_request_body; | |
113 | 271 |
114 // True if a page has completed loading, at which point it can receive | 272 // True if a page has completed loading, at which point it can receive |
115 // updates. | 273 // updates. |
116 bool is_finished_loading; | 274 bool is_finished_loading; |
117 }; | 275 }; |
118 | 276 |
119 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 277 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) |
120 : delegate_(delegate), | 278 : delegate_(delegate), |
121 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { | 279 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { |
122 } | 280 } |
123 | 281 |
124 NetErrorHelperCore::~NetErrorHelperCore() { | 282 NetErrorHelperCore::~NetErrorHelperCore() { |
125 } | 283 } |
126 | 284 |
127 void NetErrorHelperCore::OnStop() { | 285 void NetErrorHelperCore::OnStop() { |
128 // On stop, cancel loading the alternate error page, and prevent any pending | 286 // On stop, cancel loading the alternate error page, and prevent any pending |
129 // error page load from starting a new error page load. Swapping in the error | 287 // error page load from starting a new error page load. Swapping in the error |
130 // page when it's finished loading could abort the navigation, otherwise. | 288 // page when it's finished loading could abort the navigation, otherwise. |
131 if (committed_error_page_info_) | 289 if (committed_error_page_info_) { |
132 committed_error_page_info_->alternate_error_page_url = GURL(); | 290 committed_error_page_info_->link_doctor_url = GURL(); |
133 if (pending_error_page_info_) | 291 committed_error_page_info_->link_doctor_request_body.clear(); |
134 pending_error_page_info_->alternate_error_page_url = GURL(); | 292 } |
293 if (pending_error_page_info_) { | |
294 pending_error_page_info_->link_doctor_url = GURL(); | |
295 pending_error_page_info_->link_doctor_request_body.clear(); | |
296 } | |
135 delegate_->CancelFetchErrorPage(); | 297 delegate_->CancelFetchErrorPage(); |
136 } | 298 } |
137 | 299 |
138 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { | 300 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { |
139 if (frame_type != MAIN_FRAME) | 301 if (frame_type != MAIN_FRAME) |
140 return; | 302 return; |
141 | 303 |
142 // If there's no pending error page information associated with the page load, | 304 // 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. | 305 // 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) { | 306 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { |
145 OnStop(); | 307 OnStop(); |
146 } | 308 } |
147 } | 309 } |
148 | 310 |
149 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 311 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { |
150 if (frame_type != MAIN_FRAME) | 312 if (frame_type != MAIN_FRAME) |
151 return; | 313 return; |
152 | 314 |
153 committed_error_page_info_.reset(pending_error_page_info_.release()); | 315 committed_error_page_info_.reset(pending_error_page_info_.release()); |
154 } | 316 } |
155 | 317 |
156 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 318 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
157 if (frame_type != MAIN_FRAME || !committed_error_page_info_) | 319 if (frame_type != MAIN_FRAME || !committed_error_page_info_) |
158 return; | 320 return; |
159 | 321 |
160 committed_error_page_info_->is_finished_loading = true; | 322 committed_error_page_info_->is_finished_loading = true; |
161 | 323 |
162 if (committed_error_page_info_->alternate_error_page_url.is_valid()) { | 324 if (committed_error_page_info_->link_doctor_url.is_valid()) { |
163 // If there is another pending error page load, | 325 // 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. | 326 // cleared. |
165 DCHECK(!pending_error_page_info_); | 327 DCHECK(!pending_error_page_info_); |
166 DCHECK(!committed_error_page_info_->needs_dns_updates); | 328 DCHECK(!committed_error_page_info_->needs_dns_updates); |
167 GURL error_page_url; | |
168 delegate_->FetchErrorPage( | 329 delegate_->FetchErrorPage( |
169 committed_error_page_info_->alternate_error_page_url); | 330 committed_error_page_info_->link_doctor_url, |
331 committed_error_page_info_->link_doctor_request_body); | |
170 } | 332 } |
171 | 333 |
172 if (!committed_error_page_info_->needs_dns_updates || | 334 if (!committed_error_page_info_->needs_dns_updates || |
173 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { | 335 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { |
174 return; | 336 return; |
175 } | 337 } |
176 DVLOG(1) << "Error page finished loading; sending saved status."; | 338 DVLOG(1) << "Error page finished loading; sending saved status."; |
177 UpdateErrorPage(); | 339 UpdateErrorPage(); |
178 } | 340 } |
179 | 341 |
180 void NetErrorHelperCore::GetErrorHTML( | 342 void NetErrorHelperCore::GetErrorHTML( |
181 FrameType frame_type, | 343 FrameType frame_type, |
182 const blink::WebURLError& error, | 344 const blink::WebURLError& error, |
183 bool is_failed_post, | 345 bool is_failed_post, |
184 std::string* error_html) { | 346 std::string* error_html) { |
185 if (frame_type == MAIN_FRAME) { | 347 if (frame_type == MAIN_FRAME) { |
186 // If an alternate error page was going to be fetched, that should have been | 348 // If an alternate error page was going to be fetched, that should have been |
187 // cancelled by loading a new page load (Which has now failed to load). | 349 // cancelled by loading a new page load (Which has now failed to load). |
188 DCHECK(!committed_error_page_info_ || | 350 DCHECK(!committed_error_page_info_ || |
189 !committed_error_page_info_->alternate_error_page_url.is_valid()); | 351 !committed_error_page_info_->link_doctor_url.is_valid()); |
352 | |
353 std::string link_doctor_request_body; | |
354 | |
355 if (link_doctor_url_.is_valid() && | |
356 GetFixUrlRequestBody(error, language_, country_code_, api_key_, | |
357 &link_doctor_request_body)) { | |
358 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); | |
359 pending_error_page_info_->link_doctor_url = link_doctor_url_; | |
360 pending_error_page_info_->link_doctor_request_body = | |
361 link_doctor_request_body; | |
362 return; | |
363 } | |
190 | 364 |
191 // The last probe status needs to be reset if this is a DNS error. This | 365 // 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 | 366 // 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 | 367 // 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 | 368 // 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. | 369 // will just get the results for the next page load. |
196 if (IsDnsError(error)) | 370 if (IsDnsError(error)) |
197 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; | 371 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 } | 372 } |
206 | 373 |
207 GenerateLocalErrorPage(frame_type, error, is_failed_post, error_html); | 374 GenerateLocalErrorPage(frame_type, error, is_failed_post, |
375 scoped_ptr<LocalizedError::ErrorPageParams>(), | |
376 error_html); | |
208 } | 377 } |
209 | 378 |
210 void NetErrorHelperCore::GenerateLocalErrorPage( | 379 void NetErrorHelperCore::GenerateLocalErrorPage( |
211 FrameType frame_type, | 380 FrameType frame_type, |
212 const blink::WebURLError& error, | 381 const blink::WebURLError& error, |
213 bool is_failed_post, | 382 bool is_failed_post, |
383 scoped_ptr<LocalizedError::ErrorPageParams> params, | |
214 std::string* error_html) { | 384 std::string* error_html) { |
215 if (frame_type == MAIN_FRAME) { | 385 if (frame_type == MAIN_FRAME) { |
216 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); | 386 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); |
217 if (IsDnsError(error)) { | 387 // Skip DNS logic if suggestions were received from a remote server. |
388 // TODO(mmenke): Consider integrating probe results with Link Doctor | |
389 // suggestions. | |
390 if (IsDnsError(error) && !params) { | |
218 // This is not strictly necessary, but waiting for a new status to be | 391 // 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 | 392 // sent as a result of the DidFinishLoading call keeps the histograms |
220 // consistent with older versions of the code, at no real cost. | 393 // consistent with older versions of the code, at no real cost. |
221 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; | 394 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; |
222 | 395 |
223 delegate_->GenerateLocalizedErrorPage( | 396 delegate_->GenerateLocalizedErrorPage( |
224 GetUpdatedError(error), is_failed_post, error_html); | 397 GetUpdatedError(error), is_failed_post, params.Pass(), |
398 error_html); | |
225 pending_error_page_info_->needs_dns_updates = true; | 399 pending_error_page_info_->needs_dns_updates = true; |
226 return; | 400 return; |
227 } | 401 } |
228 } | 402 } |
229 delegate_->GenerateLocalizedErrorPage(error, is_failed_post, error_html); | 403 |
404 delegate_->GenerateLocalizedErrorPage(error, is_failed_post, | |
405 params.Pass(), error_html); | |
230 } | 406 } |
231 | 407 |
232 void NetErrorHelperCore::OnNetErrorInfo( | 408 void NetErrorHelperCore::OnNetErrorInfo( |
233 chrome_common_net::DnsProbeStatus status) { | 409 chrome_common_net::DnsProbeStatus status) { |
234 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); | 410 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); |
235 | 411 |
236 last_probe_status_ = status; | 412 last_probe_status_ = status; |
237 | 413 |
238 if (!committed_error_page_info_ || | 414 if (!committed_error_page_info_ || |
239 !committed_error_page_info_->needs_dns_updates || | 415 !committed_error_page_info_->needs_dns_updates || |
240 !committed_error_page_info_->is_finished_loading) { | 416 !committed_error_page_info_->is_finished_loading) { |
241 return; | 417 return; |
242 } | 418 } |
243 | 419 |
244 UpdateErrorPage(); | 420 UpdateErrorPage(); |
245 } | 421 } |
246 | 422 |
423 void NetErrorHelperCore::OnSetLinkDoctorInfo(const GURL& link_doctor_url, | |
424 const std::string& language, | |
425 const std::string& country_code, | |
426 const std::string& api_key, | |
427 const GURL& search_url) { | |
428 link_doctor_url_ = link_doctor_url; | |
429 language_ = language; | |
430 country_code_ = country_code; | |
431 api_key_ = api_key; | |
432 search_url_ = search_url; | |
433 } | |
434 | |
247 void NetErrorHelperCore::UpdateErrorPage() { | 435 void NetErrorHelperCore::UpdateErrorPage() { |
248 DCHECK(committed_error_page_info_->needs_dns_updates); | 436 DCHECK(committed_error_page_info_->needs_dns_updates); |
249 DCHECK(committed_error_page_info_->is_finished_loading); | 437 DCHECK(committed_error_page_info_->is_finished_loading); |
250 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_probe_status_); | 438 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_probe_status_); |
251 | 439 |
252 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", | 440 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", |
253 last_probe_status_, | 441 last_probe_status_, |
254 chrome_common_net::DNS_PROBE_MAX); | 442 chrome_common_net::DNS_PROBE_MAX); |
255 // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a | 443 // 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 | 444 // final status code. Once one is reached, the page does not need further |
257 // updates. | 445 // updates. |
258 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) | 446 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) |
259 committed_error_page_info_->needs_dns_updates = false; | 447 committed_error_page_info_->needs_dns_updates = false; |
260 | 448 |
261 delegate_->UpdateErrorPage( | 449 delegate_->UpdateErrorPage( |
262 GetUpdatedError(committed_error_page_info_->error), | 450 GetUpdatedError(committed_error_page_info_->error), |
263 committed_error_page_info_->was_failed_post); | 451 committed_error_page_info_->was_failed_post); |
264 } | 452 } |
265 | 453 |
266 void NetErrorHelperCore::OnAlternateErrorPageFetched(const std::string& data) { | 454 void NetErrorHelperCore::OnAlternateErrorPageFetched( |
455 const std::string& data, const std::string& accept_languages, bool is_rtl) { | |
267 // Alternate error page load only starts when an error page finishes loading, | 456 // Alternate error page load only starts when an error page finishes loading, |
268 // and is cancelled with a new load | 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 data, 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 | 497 |
317 return updated_error; | 498 return updated_error; |
318 } | 499 } |
OLD | NEW |