Chromium Code Reviews| 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" |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 return params.release(); | 246 return params.release(); |
| 247 } | 247 } |
| 248 | 248 |
| 249 } // namespace | 249 } // namespace |
| 250 | 250 |
| 251 struct NetErrorHelperCore::ErrorPageInfo { | 251 struct NetErrorHelperCore::ErrorPageInfo { |
| 252 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) | 252 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) |
| 253 : error(error), | 253 : error(error), |
| 254 was_failed_post(was_failed_post), | 254 was_failed_post(was_failed_post), |
| 255 needs_dns_updates(false), | 255 needs_dns_updates(false), |
| 256 reload_button_in_page(false), | |
| 257 load_stale_button_in_page(false), | |
| 256 is_finished_loading(false) { | 258 is_finished_loading(false) { |
| 257 } | 259 } |
| 258 | 260 |
| 259 // Information about the failed page load. | 261 // Information about the failed page load. |
| 260 blink::WebURLError error; | 262 blink::WebURLError error; |
| 261 bool was_failed_post; | 263 bool was_failed_post; |
| 262 | 264 |
| 263 // Information about the status of the error page. | 265 // Information about the status of the error page. |
| 264 | 266 |
| 265 // True if a page is a DNS error page and has not yet received a final DNS | 267 // True if a page is a DNS error page and has not yet received a final DNS |
| 266 // probe status. | 268 // probe status. |
| 267 bool needs_dns_updates; | 269 bool needs_dns_updates; |
| 268 | 270 |
| 269 // Navigation correction service url, which will be used in response to | 271 // Navigation correction service url, which will be used in response to |
| 270 // certain types of network errors. This is also stored by the | 272 // certain types of network errors. This is also stored by the |
| 271 // NetErrorHelperCore itself, but it stored here as well in case its modified | 273 // 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 | 274 // 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. | 275 // fetched, or if there's already a fetch in progress. |
| 274 GURL navigation_correction_url; | 276 GURL navigation_correction_url; |
| 275 | 277 |
| 276 // Request body to use when requesting corrections from a web service. | 278 // Request body to use when requesting corrections from a web service. |
| 277 // TODO(mmenke): Investigate loading the error page at the same time as | 279 // TODO(mmenke): Investigate loading the error page at the same time as |
| 278 // the blank page is loading, to get rid of these. | 280 // the blank page is loading, to get rid of these. |
| 279 std::string navigation_correction_request_body; | 281 std::string navigation_correction_request_body; |
| 280 | 282 |
| 283 // Track if specific buttons are included in an error page, for statistics. | |
| 284 bool reload_button_in_page; | |
| 285 bool load_stale_button_in_page; | |
| 286 | |
| 281 // True if a page has completed loading, at which point it can receive | 287 // True if a page has completed loading, at which point it can receive |
| 282 // updates. | 288 // updates. |
| 283 bool is_finished_loading; | 289 bool is_finished_loading; |
| 284 }; | 290 }; |
| 285 | 291 |
| 286 bool NetErrorHelperCore::IsReloadableError( | 292 bool NetErrorHelperCore::IsReloadableError( |
| 287 const NetErrorHelperCore::ErrorPageInfo& info) { | 293 const NetErrorHelperCore::ErrorPageInfo& info) { |
| 288 return info.error.domain.utf8() == net::kErrorDomain && | 294 return info.error.domain.utf8() == net::kErrorDomain && |
| 289 info.error.reason != net::ERR_ABORTED && | 295 info.error.reason != net::ERR_ABORTED && |
| 290 !info.was_failed_post; | 296 !info.was_failed_post; |
| 291 } | 297 } |
| 292 | 298 |
| 293 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 299 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) |
| 294 : delegate_(delegate), | 300 : delegate_(delegate), |
| 295 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), | 301 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), |
| 296 auto_reload_enabled_(false), | 302 auto_reload_enabled_(false), |
| 297 auto_reload_timer_(new base::Timer(false, false)), | 303 auto_reload_timer_(new base::Timer(false, false)), |
| 298 // TODO(ellyjones): Make online_ accurate at object creation. | 304 // TODO(ellyjones): Make online_ accurate at object creation. |
| 299 online_(true), | 305 online_(true), |
| 300 auto_reload_count_(0), | 306 auto_reload_count_(0), |
| 301 can_auto_reload_page_(false) { | 307 can_auto_reload_page_(false), |
| 308 navigation_from_button_(NO_BUTTON) { | |
| 302 } | 309 } |
| 303 | 310 |
| 304 NetErrorHelperCore::~NetErrorHelperCore() { | 311 NetErrorHelperCore::~NetErrorHelperCore() { |
| 305 if (committed_error_page_info_ && can_auto_reload_page_) { | 312 if (committed_error_page_info_ && can_auto_reload_page_) { |
| 306 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", | 313 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", |
| 307 -committed_error_page_info_->error.reason, | 314 -committed_error_page_info_->error.reason, |
| 308 net::GetAllErrorCodesForUma()); | 315 net::GetAllErrorCodesForUma()); |
| 309 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); | 316 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); |
| 310 } | 317 } |
| 311 } | 318 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 } else { | 356 } else { |
| 350 // If an error load is starting, the resulting error page is autoreloadable. | 357 // If an error load is starting, the resulting error page is autoreloadable. |
| 351 can_auto_reload_page_ = IsReloadableError(*pending_error_page_info_); | 358 can_auto_reload_page_ = IsReloadableError(*pending_error_page_info_); |
| 352 } | 359 } |
| 353 } | 360 } |
| 354 | 361 |
| 355 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 362 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { |
| 356 if (frame_type != MAIN_FRAME) | 363 if (frame_type != MAIN_FRAME) |
| 357 return; | 364 return; |
| 358 | 365 |
| 366 // Track if an error occurred due to a page button press. | |
| 367 if (committed_error_page_info_ && pending_error_page_info_ && | |
| 368 navigation_from_button_ != NO_BUTTON) { | |
| 369 DCHECK(navigation_from_button_ == RELOAD_BUTTON || | |
| 370 navigation_from_button_ == LOAD_STALE_BUTTON); | |
| 371 chrome_common_net::RecordEvent( | |
| 372 navigation_from_button_ == RELOAD_BUTTON ? | |
| 373 chrome_common_net::RELOAD_BUTTON_ERROR_EVENT : | |
| 374 chrome_common_net::LOAD_STALE_BUTTON_ERROR_EVENT); | |
| 375 } | |
| 376 navigation_from_button_ = NO_BUTTON; | |
|
mmenke
2014/04/09 15:59:26
Problem: Navigate to foo.com/, get an error. Cli
Randy Smith (Not in Mondays)
2014/04/10 21:51:01
Good point. I added in a test to make sure it was
mmenke
2014/04/11 19:42:32
This still isn't perfect, but it's probably good e
Randy Smith (Not in Mondays)
2014/04/14 22:02:13
I've added a comment, but I'd like to get a design
davidben
2014/04/15 22:04:38
Hrm. So I don't entirely follow what's going on he
| |
| 377 | |
| 359 if (committed_error_page_info_ && !pending_error_page_info_ && | 378 if (committed_error_page_info_ && !pending_error_page_info_ && |
| 360 can_auto_reload_page_) { | 379 can_auto_reload_page_) { |
| 361 int reason = committed_error_page_info_->error.reason; | 380 int reason = committed_error_page_info_->error.reason; |
| 362 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", | 381 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", |
| 363 -reason, | 382 -reason, |
| 364 net::GetAllErrorCodesForUma()); | 383 net::GetAllErrorCodesForUma()); |
| 365 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_); | 384 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_); |
| 366 if (auto_reload_count_ == 1) { | 385 if (auto_reload_count_ == 1) { |
| 367 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", | 386 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", |
| 368 -reason, | 387 -reason, |
| 369 net::GetAllErrorCodesForUma()); | 388 net::GetAllErrorCodesForUma()); |
| 370 } | 389 } |
| 371 } | 390 } |
| 372 | 391 |
| 373 committed_error_page_info_.reset(pending_error_page_info_.release()); | 392 committed_error_page_info_.reset(pending_error_page_info_.release()); |
| 374 } | 393 } |
| 375 | 394 |
| 376 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 395 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
| 377 if (frame_type != MAIN_FRAME) | 396 if (frame_type != MAIN_FRAME) |
| 378 return; | 397 return; |
| 379 | 398 |
| 380 if (!committed_error_page_info_) { | 399 if (!committed_error_page_info_) { |
| 381 auto_reload_count_ = 0; | 400 auto_reload_count_ = 0; |
| 382 return; | 401 return; |
| 383 } | 402 } |
| 384 | 403 |
| 385 committed_error_page_info_->is_finished_loading = true; | 404 committed_error_page_info_->is_finished_loading = true; |
| 386 | 405 |
| 387 // Only enable stale cache JS bindings if this wasn't a post. | 406 chrome_common_net::RecordEvent(chrome_common_net::PAGE_SHOWN_EVENT); |
| 388 if (!committed_error_page_info_->was_failed_post) { | 407 if (committed_error_page_info_->reload_button_in_page) |
| 389 delegate_->EnableStaleLoadBindings( | 408 chrome_common_net::RecordEvent( |
| 390 committed_error_page_info_->error.unreachableURL); | 409 chrome_common_net::RELOAD_BUTTON_SHOWN_EVENT); |
| 391 } | 410 if (committed_error_page_info_->load_stale_button_in_page) |
| 411 chrome_common_net::RecordEvent( | |
| 412 chrome_common_net::LOAD_STALE_BUTTON_SHOWN_EVENT); | |
|
mmenke
2014/04/09 15:59:26
nit: Use braces on multi-line if's (x2).
Randy Smith (Not in Mondays)
2014/04/10 21:51:01
Done.
| |
| 413 | |
| 414 delegate_->EnablePageHelperFunctions( | |
| 415 committed_error_page_info_->error.unreachableURL); | |
| 392 | 416 |
| 393 if (committed_error_page_info_->navigation_correction_url.is_valid()) { | 417 if (committed_error_page_info_->navigation_correction_url.is_valid()) { |
| 394 // If there is another pending error page load, |fix_url| should have been | 418 // If there is another pending error page load, |fix_url| should have been |
| 395 // cleared. | 419 // cleared. |
| 396 DCHECK(!pending_error_page_info_); | 420 DCHECK(!pending_error_page_info_); |
| 397 DCHECK(!committed_error_page_info_->needs_dns_updates); | 421 DCHECK(!committed_error_page_info_->needs_dns_updates); |
| 398 delegate_->FetchNavigationCorrections( | 422 delegate_->FetchNavigationCorrections( |
| 399 committed_error_page_info_->navigation_correction_url, | 423 committed_error_page_info_->navigation_correction_url, |
| 400 committed_error_page_info_->navigation_correction_request_body); | 424 committed_error_page_info_->navigation_correction_request_body); |
| 401 } else if (auto_reload_enabled_ && | 425 } 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)); | 483 pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post)); |
| 460 // Skip DNS logic if suggestions were received from a remote server. | 484 // Skip DNS logic if suggestions were received from a remote server. |
| 461 if (IsDnsError(error) && !params) { | 485 if (IsDnsError(error) && !params) { |
| 462 // This is not strictly necessary, but waiting for a new status to be | 486 // 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 | 487 // sent as a result of the DidFinishLoading call keeps the histograms |
| 464 // consistent with older versions of the code, at no real cost. | 488 // consistent with older versions of the code, at no real cost. |
| 465 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; | 489 last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE; |
| 466 | 490 |
| 467 delegate_->GenerateLocalizedErrorPage( | 491 delegate_->GenerateLocalizedErrorPage( |
| 468 GetUpdatedError(error), is_failed_post, params.Pass(), | 492 GetUpdatedError(error), is_failed_post, params.Pass(), |
| 493 &pending_error_page_info_->reload_button_in_page, | |
| 494 &pending_error_page_info_->load_stale_button_in_page, | |
| 469 error_html); | 495 error_html); |
| 470 pending_error_page_info_->needs_dns_updates = true; | 496 pending_error_page_info_->needs_dns_updates = true; |
| 471 return; | 497 return; |
| 472 } | 498 } |
| 473 } | 499 } |
| 474 | 500 |
| 475 delegate_->GenerateLocalizedErrorPage(error, is_failed_post, | 501 bool reload_button_in_page = false; |
| 476 params.Pass(), error_html); | 502 bool load_stale_button_in_page = false; |
| 503 delegate_->GenerateLocalizedErrorPage( | |
| 504 error, is_failed_post, params.Pass(), | |
| 505 &reload_button_in_page, &load_stale_button_in_page, error_html); | |
| 506 if (pending_error_page_info_.get()) { | |
|
mmenke
2014/04/09 15:59:26
nit: .get() not needed.
Randy Smith (Not in Mondays)
2014/04/10 21:51:01
Done.
| |
| 507 pending_error_page_info_->reload_button_in_page = reload_button_in_page; | |
| 508 pending_error_page_info_->load_stale_button_in_page = | |
| 509 load_stale_button_in_page; | |
| 510 } | |
| 477 } | 511 } |
| 478 | 512 |
| 479 void NetErrorHelperCore::OnNetErrorInfo( | 513 void NetErrorHelperCore::OnNetErrorInfo( |
| 480 chrome_common_net::DnsProbeStatus status) { | 514 chrome_common_net::DnsProbeStatus status) { |
| 481 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); | 515 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status); |
| 482 | 516 |
| 483 last_probe_status_ = status; | 517 last_probe_status_ = status; |
| 484 | 518 |
| 485 if (!committed_error_page_info_ || | 519 if (!committed_error_page_info_ || |
| 486 !committed_error_page_info_->needs_dns_updates || | 520 !committed_error_page_info_->needs_dns_updates || |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 511 | 545 |
| 512 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", | 546 UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus", |
| 513 last_probe_status_, | 547 last_probe_status_, |
| 514 chrome_common_net::DNS_PROBE_MAX); | 548 chrome_common_net::DNS_PROBE_MAX); |
| 515 // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a | 549 // 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 | 550 // final status code. Once one is reached, the page does not need further |
| 517 // updates. | 551 // updates. |
| 518 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) | 552 if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) |
| 519 committed_error_page_info_->needs_dns_updates = false; | 553 committed_error_page_info_->needs_dns_updates = false; |
| 520 | 554 |
| 555 // We don't worry about the button display statistics here because | |
| 556 // the presentation of the reload and load stale buttons can't be | |
| 557 // changed by a DNS error update. | |
|
mmenke
2014/04/09 15:59:26
nit: Don't use we in comments.
Randy Smith (Not in Mondays)
2014/04/10 21:51:01
Done.
| |
| 521 delegate_->UpdateErrorPage( | 558 delegate_->UpdateErrorPage( |
| 522 GetUpdatedError(committed_error_page_info_->error), | 559 GetUpdatedError(committed_error_page_info_->error), |
| 523 committed_error_page_info_->was_failed_post); | 560 committed_error_page_info_->was_failed_post); |
| 524 } | 561 } |
| 525 | 562 |
| 526 void NetErrorHelperCore::OnNavigationCorrectionsFetched( | 563 void NetErrorHelperCore::OnNavigationCorrectionsFetched( |
| 527 const std::string& corrections, | 564 const std::string& corrections, |
| 528 const std::string& accept_languages, | 565 const std::string& accept_languages, |
| 529 bool is_rtl) { | 566 bool is_rtl) { |
| 530 // Loading suggestions only starts when a blank error page finishes loading, | 567 // 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) | 680 if (error_url != url) |
| 644 return false; | 681 return false; |
| 645 | 682 |
| 646 // The first iteration of the timer is started by OnFinishLoad calling | 683 // The first iteration of the timer is started by OnFinishLoad calling |
| 647 // MaybeStartAutoReloadTimer, but since error pages for subsequent loads are | 684 // MaybeStartAutoReloadTimer, but since error pages for subsequent loads are |
| 648 // suppressed in this function, subsequent iterations of the timer have to be | 685 // suppressed in this function, subsequent iterations of the timer have to be |
| 649 // started here. | 686 // started here. |
| 650 MaybeStartAutoReloadTimer(); | 687 MaybeStartAutoReloadTimer(); |
| 651 return true; | 688 return true; |
| 652 } | 689 } |
| 690 | |
| 691 void NetErrorHelperCore::ExecuteButtonPress(Button button) { | |
| 692 switch (button) { | |
| 693 case RELOAD_BUTTON: | |
| 694 chrome_common_net::RecordEvent( | |
| 695 chrome_common_net::RELOAD_BUTTON_CLICKED_EVENT); | |
| 696 navigation_from_button_ = RELOAD_BUTTON; | |
| 697 Reload(); | |
| 698 return; | |
| 699 case LOAD_STALE_BUTTON: | |
| 700 chrome_common_net::RecordEvent( | |
| 701 chrome_common_net::LOAD_STALE_BUTTON_CLICKED_EVENT); | |
| 702 navigation_from_button_ = LOAD_STALE_BUTTON; | |
| 703 delegate_->LoadPageFromCache( | |
| 704 committed_error_page_info_->error.unreachableURL); | |
| 705 return; | |
| 706 case MORE_BUTTON: | |
| 707 // Visual effects on page are handled in Javascript code. | |
| 708 chrome_common_net::RecordEvent( | |
| 709 chrome_common_net::MORE_BUTTON_CLICKED_EVENT); | |
| 710 return; | |
| 711 case NO_BUTTON: | |
| 712 NOTREACHED(); | |
| 713 return; | |
| 714 } | |
| 715 } | |
| 716 | |
| OLD | NEW |