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/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/i18n/rtl.h" | 11 #include "base/i18n/rtl.h" |
12 #include "base/json/json_reader.h" | 12 #include "base/json/json_reader.h" |
13 #include "base/json/json_writer.h" | 13 #include "base/json/json_writer.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/logging.h" | |
15 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
16 #include "base/strings/string16.h" | 17 #include "base/strings/string16.h" |
17 #include "base/values.h" | 18 #include "base/values.h" |
18 #include "chrome/common/localized_error.h" | 19 #include "chrome/common/localized_error.h" |
19 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
20 #include "net/base/escape.h" | 21 #include "net/base/escape.h" |
21 #include "net/base/net_errors.h" | 22 #include "net/base/net_errors.h" |
22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
23 #include "third_party/WebKit/public/platform/WebString.h" | 24 #include "third_party/WebKit/public/platform/WebString.h" |
24 #include "third_party/WebKit/public/platform/WebURLError.h" | 25 #include "third_party/WebKit/public/platform/WebURLError.h" |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 return params.release(); | 247 return params.release(); |
247 } | 248 } |
248 | 249 |
249 } // namespace | 250 } // namespace |
250 | 251 |
251 struct NetErrorHelperCore::ErrorPageInfo { | 252 struct NetErrorHelperCore::ErrorPageInfo { |
252 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) | 253 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) |
253 : error(error), | 254 : error(error), |
254 was_failed_post(was_failed_post), | 255 was_failed_post(was_failed_post), |
255 needs_dns_updates(false), | 256 needs_dns_updates(false), |
257 reload_button_in_page(false), | |
258 load_stale_button_in_page(false), | |
256 is_finished_loading(false) { | 259 is_finished_loading(false) { |
257 } | 260 } |
258 | 261 |
259 // Information about the failed page load. | 262 // Information about the failed page load. |
260 blink::WebURLError error; | 263 blink::WebURLError error; |
261 bool was_failed_post; | 264 bool was_failed_post; |
262 | 265 |
263 // Information about the status of the error page. | 266 // Information about the status of the error page. |
264 | 267 |
265 // True if a page is a DNS error page and has not yet received a final DNS | 268 // True if a page is a DNS error page and has not yet received a final DNS |
266 // probe status. | 269 // probe status. |
267 bool needs_dns_updates; | 270 bool needs_dns_updates; |
268 | 271 |
269 // Navigation correction service url, which will be used in response to | 272 // Navigation correction service url, which will be used in response to |
270 // certain types of network errors. This is also stored by the | 273 // certain types of network errors. This is also stored by the |
271 // NetErrorHelperCore itself, but it stored here as well in case its modified | 274 // NetErrorHelperCore itself, but it stored here as well in case its modified |
272 // in the middle of an error page load. Empty when no error page should be | 275 // in the middle of an error page load. Empty when no error page should be |
273 // fetched, or if there's already a fetch in progress. | 276 // fetched, or if there's already a fetch in progress. |
274 GURL navigation_correction_url; | 277 GURL navigation_correction_url; |
275 | 278 |
276 // Request body to use when requesting corrections from a web service. | 279 // Request body to use when requesting corrections from a web service. |
277 // TODO(mmenke): Investigate loading the error page at the same time as | 280 // TODO(mmenke): Investigate loading the error page at the same time as |
278 // the blank page is loading, to get rid of these. | 281 // the blank page is loading, to get rid of these. |
279 std::string navigation_correction_request_body; | 282 std::string navigation_correction_request_body; |
280 | 283 |
284 // Track if specific buttons are included in an error page, for statistics. | |
285 bool reload_button_in_page; | |
286 bool load_stale_button_in_page; | |
287 | |
281 // True if a page has completed loading, at which point it can receive | 288 // True if a page has completed loading, at which point it can receive |
282 // updates. | 289 // updates. |
283 bool is_finished_loading; | 290 bool is_finished_loading; |
284 }; | 291 }; |
285 | 292 |
286 bool NetErrorHelperCore::IsReloadableError( | 293 bool NetErrorHelperCore::IsReloadableError( |
287 const NetErrorHelperCore::ErrorPageInfo& info) { | 294 const NetErrorHelperCore::ErrorPageInfo& info) { |
288 return info.error.domain.utf8() == net::kErrorDomain && | 295 return info.error.domain.utf8() == net::kErrorDomain && |
289 info.error.reason != net::ERR_ABORTED && | 296 info.error.reason != net::ERR_ABORTED && |
290 !info.was_failed_post; | 297 !info.was_failed_post; |
291 } | 298 } |
292 | 299 |
293 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 300 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) |
294 : delegate_(delegate), | 301 : delegate_(delegate), |
295 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), | 302 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), |
296 auto_reload_enabled_(false), | 303 auto_reload_enabled_(false), |
297 auto_reload_timer_(new base::Timer(false, false)), | 304 auto_reload_timer_(new base::Timer(false, false)), |
298 // TODO(ellyjones): Make online_ accurate at object creation. | 305 // TODO(ellyjones): Make online_ accurate at object creation. |
299 online_(true), | 306 online_(true), |
300 auto_reload_count_(0), | 307 auto_reload_count_(0), |
301 can_auto_reload_page_(false) { | 308 can_auto_reload_page_(false), |
309 navigation_from_button_(NO_BUTTON) { | |
302 } | 310 } |
303 | 311 |
304 NetErrorHelperCore::~NetErrorHelperCore() { | 312 NetErrorHelperCore::~NetErrorHelperCore() { |
305 if (committed_error_page_info_ && can_auto_reload_page_) { | 313 if (committed_error_page_info_ && can_auto_reload_page_) { |
306 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", | 314 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", |
307 -committed_error_page_info_->error.reason, | 315 -committed_error_page_info_->error.reason, |
308 net::GetAllErrorCodesForUma()); | 316 net::GetAllErrorCodesForUma()); |
309 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); | 317 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); |
310 } | 318 } |
311 } | 319 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 } else if (auto_reload_enabled_) { | 357 } else if (auto_reload_enabled_) { |
350 // If an error load is starting, the resulting error page is autoreloadable. | 358 // If an error load is starting, the resulting error page is autoreloadable. |
351 can_auto_reload_page_ = IsReloadableError(*pending_error_page_info_); | 359 can_auto_reload_page_ = IsReloadableError(*pending_error_page_info_); |
352 } | 360 } |
353 } | 361 } |
354 | 362 |
355 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 363 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { |
356 if (frame_type != MAIN_FRAME) | 364 if (frame_type != MAIN_FRAME) |
357 return; | 365 return; |
358 | 366 |
367 // Track if an error occurred due to a page button press. | |
368 // This isn't perfect; if (for instance), the server is slow responding | |
369 // to a request generated from the page reload button, and the user hits | |
370 // the browser reload button, this code will still believe the | |
371 // result is from the page reload button. | |
372 if (committed_error_page_info_ && pending_error_page_info_ && | |
373 navigation_from_button_ != NO_BUTTON && | |
374 committed_error_page_info_->error.unreachableURL == | |
375 pending_error_page_info_->error.unreachableURL) { | |
376 DCHECK(navigation_from_button_ == RELOAD_BUTTON || | |
377 navigation_from_button_ == LOAD_STALE_BUTTON); | |
378 chrome_common_net::RecordEvent( | |
379 navigation_from_button_ == RELOAD_BUTTON ? | |
jar (doing other things)
2014/04/21 23:48:19
nit: This will fit on the previous line...and then
mmenke
2014/04/22 00:24:59
While the Google style guide doesn't explicitly di
jar (doing other things)
2014/04/22 17:53:43
If you really prefer to start a new line... that's
Randy Smith (Not in Mondays)
2014/04/22 20:40:02
I formatted it this way in response to Matt's comm
mmenke
2014/04/22 21:03:27
The style guide says nothing about this case, so w
jar (doing other things)
2014/04/23 01:52:01
As noted, this is a nit. I couldn't find any reas
| |
380 chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_ERROR : | |
381 chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_ERROR); | |
382 } | |
383 navigation_from_button_ = NO_BUTTON; | |
384 | |
359 if (committed_error_page_info_ && !pending_error_page_info_ && | 385 if (committed_error_page_info_ && !pending_error_page_info_ && |
360 can_auto_reload_page_) { | 386 can_auto_reload_page_) { |
361 int reason = committed_error_page_info_->error.reason; | 387 int reason = committed_error_page_info_->error.reason; |
362 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", | 388 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", |
363 -reason, | 389 -reason, |
364 net::GetAllErrorCodesForUma()); | 390 net::GetAllErrorCodesForUma()); |
365 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_); | 391 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_); |
366 if (auto_reload_count_ == 1) { | 392 if (auto_reload_count_ == 1) { |
367 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", | 393 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", |
368 -reason, | 394 -reason, |
369 net::GetAllErrorCodesForUma()); | 395 net::GetAllErrorCodesForUma()); |
370 } | 396 } |
371 } | 397 } |
372 | 398 |
373 committed_error_page_info_.reset(pending_error_page_info_.release()); | 399 committed_error_page_info_.reset(pending_error_page_info_.release()); |
374 } | 400 } |
375 | 401 |
376 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 402 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
377 if (frame_type != MAIN_FRAME) | 403 if (frame_type != MAIN_FRAME) |
378 return; | 404 return; |
379 | 405 |
380 if (!committed_error_page_info_) { | 406 if (!committed_error_page_info_) { |
381 auto_reload_count_ = 0; | 407 auto_reload_count_ = 0; |
382 return; | 408 return; |
383 } | 409 } |
384 | 410 |
385 committed_error_page_info_->is_finished_loading = true; | 411 committed_error_page_info_->is_finished_loading = true; |
386 | 412 |
387 // Only enable stale cache JS bindings if this wasn't a post. | 413 chrome_common_net::RecordEvent(chrome_common_net::NETWORK_ERROR_PAGE_SHOWN); |
388 if (!committed_error_page_info_->was_failed_post) { | 414 if (committed_error_page_info_->reload_button_in_page) { |
389 delegate_->EnableStaleLoadBindings( | 415 chrome_common_net::RecordEvent( |
390 committed_error_page_info_->error.unreachableURL); | 416 chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_SHOWN); |
391 } | 417 } |
418 if (committed_error_page_info_->load_stale_button_in_page) { | |
419 chrome_common_net::RecordEvent( | |
420 chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_SHOWN); | |
421 } | |
422 | |
423 delegate_->EnablePageHelperFunctions(); | |
392 | 424 |
393 if (committed_error_page_info_->navigation_correction_url.is_valid()) { | 425 if (committed_error_page_info_->navigation_correction_url.is_valid()) { |
394 // If there is another pending error page load, |fix_url| should have been | 426 // If there is another pending error page load, |fix_url| should have been |
395 // cleared. | 427 // cleared. |
396 DCHECK(!pending_error_page_info_); | 428 DCHECK(!pending_error_page_info_); |
397 DCHECK(!committed_error_page_info_->needs_dns_updates); | 429 DCHECK(!committed_error_page_info_->needs_dns_updates); |
398 delegate_->FetchNavigationCorrections( | 430 delegate_->FetchNavigationCorrections( |
399 committed_error_page_info_->navigation_correction_url, | 431 committed_error_page_info_->navigation_correction_url, |
400 committed_error_page_info_->navigation_correction_request_body); | 432 committed_error_page_info_->navigation_correction_request_body); |
401 } else if (auto_reload_enabled_ && | 433 } else if (auto_reload_enabled_ && |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); | 491 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); |
460 // Skip DNS logic if suggestions were received from a remote server. | 492 // Skip DNS logic if suggestions were received from a remote server. |
461 if (IsDnsError(error) && !params) { | 493 if (IsDnsError(error) && !params) { |
462 // This is not strictly necessary, but waiting for a new status to be | 494 // This is not strictly necessary, but waiting for a new status to be |
463 // sent as a result of the DidFinishLoading call keeps the histograms | 495 // sent as a result of the DidFinishLoading call keeps the histograms |
464 // consistent with older versions of the code, at no real cost. | 496 // consistent with older versions of the code, at no real cost. |
465 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; | 497 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; |
466 | 498 |
467 delegate_->GenerateLocalizedErrorPage( | 499 delegate_->GenerateLocalizedErrorPage( |
468 GetUpdatedError(error), is_failed_post, params.Pass(), | 500 GetUpdatedError(error), is_failed_post, params.Pass(), |
501 &pending_error_page_info_->reload_button_in_page, | |
502 &pending_error_page_info_->load_stale_button_in_page, | |
469 error_html); | 503 error_html); |
470 pending_error_page_info_->needs_dns_updates = true; | 504 pending_error_page_info_->needs_dns_updates = true; |
471 return; | 505 return; |
472 } | 506 } |
473 } | 507 } |
474 | 508 |
475 delegate_->GenerateLocalizedErrorPage(error, is_failed_post, | 509 bool reload_button_in_page = false; |
476 params.Pass(), error_html); | 510 bool load_stale_button_in_page = false; |
511 delegate_->GenerateLocalizedErrorPage( | |
512 error, is_failed_post, params.Pass(), | |
513 &reload_button_in_page, &load_stale_button_in_page, error_html); | |
514 if (pending_error_page_info_ && frame_type == MAIN_FRAME) { | |
515 pending_error_page_info_->reload_button_in_page = reload_button_in_page; | |
516 pending_error_page_info_->load_stale_button_in_page = | |
517 load_stale_button_in_page; | |
518 } | |
477 } | 519 } |
478 | 520 |
479 void NetErrorHelperCore::OnNetErrorInfo( | 521 void NetErrorHelperCore::OnNetErrorInfo( |
480 chrome_common_net::DnsProbeStatus status) { | 522 chrome_common_net::DnsProbeStatus status) { |
481 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); | 523 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); |
482 | 524 |
483 last_probe_status_ = status; | 525 last_probe_status_ = status; |
484 | 526 |
485 if (!committed_error_page_info_ || | 527 if (!committed_error_page_info_ || |
486 !committed_error_page_info_->needs_dns_updates || | 528 !committed_error_page_info_->needs_dns_updates || |
(...skipping 24 matching lines...) Expand all Loading... | |
511 | 553 |
512 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", | 554 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", |
513 last_probe_status_, | 555 last_probe_status_, |
514 chrome_common_net::DNS_PROBE_MAX); | 556 chrome_common_net::DNS_PROBE_MAX); |
515 // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a | 557 // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a |
516 // final status code. Once one is reached, the page does not need further | 558 // final status code. Once one is reached, the page does not need further |
517 // updates. | 559 // updates. |
518 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) | 560 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) |
519 committed_error_page_info_->needs_dns_updates = false; | 561 committed_error_page_info_->needs_dns_updates = false; |
520 | 562 |
563 // There is no need to worry about the button display statistics here because | |
564 // the presentation of the reload and load stale buttons can't be changed | |
565 // by a DNS error update. | |
521 delegate_->UpdateErrorPage( | 566 delegate_->UpdateErrorPage( |
522 GetUpdatedError(committed_error_page_info_->error), | 567 GetUpdatedError(committed_error_page_info_->error), |
523 committed_error_page_info_->was_failed_post); | 568 committed_error_page_info_->was_failed_post); |
524 } | 569 } |
525 | 570 |
526 void NetErrorHelperCore::OnNavigationCorrectionsFetched( | 571 void NetErrorHelperCore::OnNavigationCorrectionsFetched( |
527 const std::string& corrections, | 572 const std::string& corrections, |
528 const std::string& accept_languages, | 573 const std::string& accept_languages, |
529 bool is_rtl) { | 574 bool is_rtl) { |
530 // Loading suggestions only starts when a blank error page finishes loading, | 575 // Loading suggestions only starts when a blank error page finishes loading, |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
643 if (error_url != url) | 688 if (error_url != url) |
644 return false; | 689 return false; |
645 | 690 |
646 // The first iteration of the timer is started by OnFinishLoad calling | 691 // The first iteration of the timer is started by OnFinishLoad calling |
647 // MaybeStartAutoReloadTimer, but since error pages for subsequent loads are | 692 // MaybeStartAutoReloadTimer, but since error pages for subsequent loads are |
648 // suppressed in this function, subsequent iterations of the timer have to be | 693 // suppressed in this function, subsequent iterations of the timer have to be |
649 // started here. | 694 // started here. |
650 MaybeStartAutoReloadTimer(); | 695 MaybeStartAutoReloadTimer(); |
651 return true; | 696 return true; |
652 } | 697 } |
698 | |
699 void NetErrorHelperCore::ExecuteButtonPress(Button button) { | |
700 switch (button) { | |
701 case RELOAD_BUTTON: | |
702 chrome_common_net::RecordEvent( | |
703 chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_CLICKED); | |
704 navigation_from_button_ = RELOAD_BUTTON; | |
705 Reload(); | |
706 return; | |
707 case LOAD_STALE_BUTTON: | |
708 chrome_common_net::RecordEvent( | |
709 chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_CLICKED); | |
710 navigation_from_button_ = LOAD_STALE_BUTTON; | |
711 delegate_->LoadPageFromCache( | |
712 committed_error_page_info_->error.unreachableURL); | |
713 return; | |
714 case MORE_BUTTON: | |
715 // Visual effects on page are handled in Javascript code. | |
716 chrome_common_net::RecordEvent( | |
717 chrome_common_net::NETWORK_ERROR_PAGE_MORE_BUTTON_CLICKED); | |
718 return; | |
719 case NO_BUTTON: | |
720 NOTREACHED(); | |
721 return; | |
722 } | |
723 } | |
724 | |
OLD | NEW |