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

Side by Side Diff: chrome/renderer/net/net_error_helper_core.cc

Issue 207553008: Surface button for loading stale cache copy on net error page. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync'd to r264192. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 ?
380 chrome_common_net::NET_ERROR_PAGE_RELOAD_BUTTON_ERROR :
381 chrome_common_net::NET_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::NET_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::NET_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::NET_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
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_) {
mmenke 2014/04/17 14:39:25 This should have an "&& frame_type == MAIN_FRAME".
Randy Smith (Not in Mondays) 2014/04/17 16:04:54 Done.
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
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
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::NET_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::NET_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::NET_ERROR_PAGE_MORE_BUTTON_CLICKED);
718 return;
719 case NO_BUTTON:
720 NOTREACHED();
721 return;
722 }
723 }
724
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698