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

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

Issue 136203009: Support auto-reload on errors. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: placate clang Created 6 years, 9 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
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"
10 #include "base/callback.h"
9 #include "base/i18n/rtl.h" 11 #include "base/i18n/rtl.h"
10 #include "base/json/json_reader.h" 12 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h" 13 #include "base/json/json_writer.h"
14 #include "base/location.h"
12 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
13 #include "base/strings/string16.h" 16 #include "base/strings/string16.h"
14 #include "base/values.h" 17 #include "base/values.h"
15 #include "chrome/common/localized_error.h" 18 #include "chrome/common/localized_error.h"
16 #include "grit/generated_resources.h" 19 #include "grit/generated_resources.h"
17 #include "net/base/escape.h" 20 #include "net/base/escape.h"
18 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
19 #include "net/base/net_util.h" 22 #include "net/base/net_util.h"
20 #include "third_party/WebKit/public/platform/WebString.h" 23 #include "third_party/WebKit/public/platform/WebString.h"
21 #include "third_party/WebKit/public/platform/WebURLError.h" 24 #include "third_party/WebKit/public/platform/WebURLError.h"
(...skipping 16 matching lines...) Expand all
38 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "sitemap"}, 41 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "sitemap"},
39 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "pathParentFolder"}, 42 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "pathParentFolder"},
40 // "siteSearchQuery" is not yet supported. 43 // "siteSearchQuery" is not yet supported.
41 // TODO(mmenke): Figure out what format "siteSearchQuery" uses for its 44 // TODO(mmenke): Figure out what format "siteSearchQuery" uses for its
42 // suggestions. 45 // suggestions.
43 // "webSearchQuery" has special handling. 46 // "webSearchQuery" has special handling.
44 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "contentOverlap"}, 47 {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "contentOverlap"},
45 {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "emphasizedUrlCorrection"}, 48 {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "emphasizedUrlCorrection"},
46 }; 49 };
47 50
51 base::TimeDelta GetAutoReloadTime(size_t reload_count) {
52 static const int kDelaysMs[] = {
53 0, 5000, 30000, 60000, 300000, 600000, 1800000
54 };
55 if (reload_count >= arraysize(kDelaysMs))
56 reload_count = arraysize(kDelaysMs) - 1;
57 return base::TimeDelta::FromMilliseconds(kDelaysMs[reload_count]);
58 }
59
48 // Returns whether |net_error| is a DNS-related error (and therefore whether 60 // Returns whether |net_error| is a DNS-related error (and therefore whether
49 // the tab helper should start a DNS probe after receiving it.) 61 // the tab helper should start a DNS probe after receiving it.)
50 bool IsDnsError(const blink::WebURLError& error) { 62 bool IsDnsError(const blink::WebURLError& error) {
51 return error.domain.utf8() == net::kErrorDomain && 63 return error.domain.utf8() == net::kErrorDomain &&
52 (error.reason == net::ERR_NAME_NOT_RESOLVED || 64 (error.reason == net::ERR_NAME_NOT_RESOLVED ||
53 error.reason == net::ERR_NAME_RESOLUTION_FAILED); 65 error.reason == net::ERR_NAME_RESOLUTION_FAILED);
54 } 66 }
55 67
56 GURL SanitizeURL(const GURL& url) { 68 GURL SanitizeURL(const GURL& url) {
57 GURL::Replacements remove_params; 69 GURL::Replacements remove_params;
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 // Request body to use when requesting corrections from a web service. 276 // Request body to use when requesting corrections from a web service.
265 // TODO(mmenke): Investigate loading the error page at the same time as 277 // TODO(mmenke): Investigate loading the error page at the same time as
266 // the blank page is loading, to get rid of these. 278 // the blank page is loading, to get rid of these.
267 std::string navigation_correction_request_body; 279 std::string navigation_correction_request_body;
268 280
269 // True if a page has completed loading, at which point it can receive 281 // True if a page has completed loading, at which point it can receive
270 // updates. 282 // updates.
271 bool is_finished_loading; 283 bool is_finished_loading;
272 }; 284 };
273 285
286 bool NetErrorHelperCore::IsReloadableError(
287 const NetErrorHelperCore::ErrorPageInfo& info) {
288 return info.error.domain.utf8() == net::kErrorDomain &&
289 info.error.reason != net::ERR_ABORTED &&
290 !info.was_failed_post;
291 }
292
274 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) 293 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate)
275 : delegate_(delegate), 294 : delegate_(delegate),
276 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { 295 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE),
296 auto_reload_enabled_(false),
297 auto_reload_timer_(new MockableOneShotTimer()),
298 online_(true),
299 auto_reload_count_(0),
300 can_auto_reload_page_(false) {
277 } 301 }
278 302
279 NetErrorHelperCore::~NetErrorHelperCore() { 303 NetErrorHelperCore::~NetErrorHelperCore() {
280 } 304 }
281 305
282 void NetErrorHelperCore::OnStop() { 306 void NetErrorHelperCore::CancelPendingFetches() {
283 // On stop, cancel loading navigation corrections, and prevent any 307 // Cancel loading the alternate error page, and prevent any pending error page
284 // pending error page load from starting to load corrections. Swapping in an 308 // load from starting a new error page load. Swapping in the error page when
285 // error page once corrections are received could interrupt a navigation, 309 // it's finished loading could abort the navigation, otherwise.
286 // otherwise. 310 if (committed_error_page_info_ && can_auto_reload_page_) {
311 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop",
312 committed_error_page_info_->error.reason,
mmenke 2014/03/12 19:02:42 I think this should be -committed_error_page_info_
Elly Fong-Jones 2014/03/12 20:10:53 Done.
313 net::GetAllErrorCodesForUma());
314 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_);
mmenke 2014/03/12 19:02:42 Are you going to update histograms.xml in this CL,
mmenke 2014/03/12 19:02:42 If the process or RV is killed by quitting chrome
Elly Fong-Jones 2014/03/12 20:10:53 I was going to avoid that - it adds another layer
Elly Fong-Jones 2014/03/12 20:10:53 Done.
315 }
287 if (committed_error_page_info_) { 316 if (committed_error_page_info_) {
288 committed_error_page_info_->navigation_correction_url = GURL(); 317 committed_error_page_info_->navigation_correction_url = GURL();
289 committed_error_page_info_->navigation_correction_request_body.clear(); 318 committed_error_page_info_->navigation_correction_request_body.clear();
290 } 319 }
291 if (pending_error_page_info_) { 320 if (pending_error_page_info_) {
292 pending_error_page_info_->navigation_correction_url = GURL(); 321 pending_error_page_info_->navigation_correction_url = GURL();
293 pending_error_page_info_->navigation_correction_request_body.clear(); 322 pending_error_page_info_->navigation_correction_request_body.clear();
294 } 323 }
295 delegate_->CancelFetchNavigationCorrections(); 324 delegate_->CancelFetchNavigationCorrections();
325 auto_reload_timer_->Stop();
326 }
327
328 void NetErrorHelperCore::OnStop() {
329 CancelPendingFetches();
330 auto_reload_count_ = 0;
331 can_auto_reload_page_ = false;
296 } 332 }
297 333
298 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { 334 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) {
299 if (frame_type != MAIN_FRAME) 335 if (frame_type != MAIN_FRAME)
300 return; 336 return;
301 337
302 // If there's no pending error page information associated with the page load, 338 // If there's no pending error page information associated with the page load,
303 // or the new page is not an error page, then reset pending error page state. 339 // or the new page is not an error page, then reset pending error page state.
304 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { 340 if (!pending_error_page_info_ || page_type != ERROR_PAGE) {
305 OnStop(); 341 CancelPendingFetches();
342 // If a non-error load is starting, don't try to auto-reload while it is in
343 // flight.
344 can_auto_reload_page_ = false;
mmenke 2014/03/12 19:02:42 May want to do this in CancelPendingFetches(), sin
Elly Fong-Jones 2014/03/12 20:10:53 Done.
345 } else {
346 // If an error load is starting, the resulting error page is autoreloadable.
347 can_auto_reload_page_ = true;
mmenke 2014/03/12 19:02:42 Suggest: can_auto_reload_page_ = IsReloadableErro
Elly Fong-Jones 2014/03/12 20:10:53 Done.
306 } 348 }
307 } 349 }
308 350
309 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { 351 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) {
310 if (frame_type != MAIN_FRAME) 352 if (frame_type != MAIN_FRAME)
311 return; 353 return;
312 354
355 if (committed_error_page_info_ && !pending_error_page_info_ &&
356 can_auto_reload_page_) {
357 int reason = committed_error_page_info_->error.reason;
358 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess",
359 reason,
360 net::GetAllErrorCodesForUma());
361 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_);
362 if (auto_reload_count_ == 1) {
363 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess",
364 reason,
365 net::GetAllErrorCodesForUma());
366 }
367 }
368
313 committed_error_page_info_.reset(pending_error_page_info_.release()); 369 committed_error_page_info_.reset(pending_error_page_info_.release());
314 } 370 }
315 371
316 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { 372 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) {
317 if (frame_type != MAIN_FRAME || !committed_error_page_info_) 373 if (frame_type != MAIN_FRAME)
318 return; 374 return;
319 375
376 if (!committed_error_page_info_) {
377 auto_reload_count_ = 0;
378 return;
379 }
380
320 committed_error_page_info_->is_finished_loading = true; 381 committed_error_page_info_->is_finished_loading = true;
321 382
322 if (committed_error_page_info_->navigation_correction_url.is_valid()) { 383 if (committed_error_page_info_->navigation_correction_url.is_valid()) {
323 // If there is another pending error page load, |fix_url| should have been 384 // If there is another pending error page load, |fix_url| should have been
324 // cleared. 385 // cleared.
325 DCHECK(!pending_error_page_info_); 386 DCHECK(!pending_error_page_info_);
326 DCHECK(!committed_error_page_info_->needs_dns_updates); 387 DCHECK(!committed_error_page_info_->needs_dns_updates);
327 delegate_->FetchNavigationCorrections( 388 delegate_->FetchNavigationCorrections(
328 committed_error_page_info_->navigation_correction_url, 389 committed_error_page_info_->navigation_correction_url,
329 committed_error_page_info_->navigation_correction_request_body); 390 committed_error_page_info_->navigation_correction_request_body);
391 } else if (auto_reload_enabled_ &&
392 IsReloadableError(*committed_error_page_info_)) {
393 can_auto_reload_page_ = true;
mmenke 2014/03/12 19:02:42 Get rid of can_auto_reload_page_, and replace IsRe
Elly Fong-Jones 2014/03/12 20:10:53 Done.
394 MaybeStartAutoReloadTimer();
330 } 395 }
331 396
332 if (!committed_error_page_info_->needs_dns_updates || 397 if (!committed_error_page_info_->needs_dns_updates ||
333 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { 398 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) {
334 return; 399 return;
335 } 400 }
336 DVLOG(1) << "Error page finished loading; sending saved status."; 401 DVLOG(1) << "Error page finished loading; sending saved status.";
337 UpdateErrorPage(); 402 UpdateErrorPage();
338 } 403 }
339 404
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 556
492 blink::WebURLError updated_error; 557 blink::WebURLError updated_error;
493 updated_error.domain = blink::WebString::fromUTF8( 558 updated_error.domain = blink::WebString::fromUTF8(
494 chrome_common_net::kDnsProbeErrorDomain); 559 chrome_common_net::kDnsProbeErrorDomain);
495 updated_error.reason = last_probe_status_; 560 updated_error.reason = last_probe_status_;
496 updated_error.unreachableURL = error.unreachableURL; 561 updated_error.unreachableURL = error.unreachableURL;
497 updated_error.staleCopyInCache = error.staleCopyInCache; 562 updated_error.staleCopyInCache = error.staleCopyInCache;
498 563
499 return updated_error; 564 return updated_error;
500 } 565 }
566
567 void NetErrorHelperCore::Reload() {
568 if (!committed_error_page_info_) {
569 return;
570 }
571 delegate_->ReloadPage();
572 }
573
574 bool NetErrorHelperCore::MaybeStartAutoReloadTimer() {
575 if (!committed_error_page_info_ || !can_auto_reload_page_)
mmenke 2014/03/12 19:02:42 Can't we DCHECK on these now?
Elly Fong-Jones 2014/03/12 20:10:53 No, because this can be called from NetworkStateCh
576 return false;
577
mmenke 2014/03/12 19:02:42 DCHECK(!pending_error_page_info_)? (Logic elsewhe
Elly Fong-Jones 2014/03/12 20:10:53 Done.
578 DCHECK(IsReloadableError(*committed_error_page_info_));
579
580 if (!online_)
581 return false;
582
583 StartAutoReloadTimer();
584 return true;
585 }
586
587 void NetErrorHelperCore::StartAutoReloadTimer() {
588 DCHECK(committed_error_page_info_);
589 DCHECK(can_auto_reload_page_);
590 base::TimeDelta delay = GetAutoReloadTime(auto_reload_count_);
591 auto_reload_count_++;
592 auto_reload_timer_->Stop();
593 auto_reload_timer_->Start(FROM_HERE, delay,
594 base::Bind(&NetErrorHelperCore::Reload,
595 base::Unretained(this)));
596 }
597
598 void NetErrorHelperCore::NetworkStateChanged(bool online) {
599 online_ = online;
600 if (auto_reload_timer_->IsRunning()) {
601 DCHECK(committed_error_page_info_);
602 // If there's an existing timer running, stop it and reset the retry count.
603 auto_reload_timer_->Stop();
604 auto_reload_count_ = 0;
605 }
606
607 // If the network state changed to online, maybe start auto-reloading again.
608 if (online)
609 MaybeStartAutoReloadTimer();
610 }
611
612 bool NetErrorHelperCore::ShouldSuppressErrorPage(FrameType frame_type,
613 const GURL& url) {
614 // Don't suppress child frame errors.
615 if (frame_type != MAIN_FRAME)
616 return false;
617
618 // If |auto_reload_timer_| is still running, this error page isn't from an
619 // auto reload.
620 if (auto_reload_timer_->IsRunning())
621 return false;
622
623 // If there's no committed error page, this error page wasn't from an auto
624 // reload.
625 if (!committed_error_page_info_ || !can_auto_reload_page_)
626 return false;
627
628 GURL error_url = committed_error_page_info_->error.unreachableURL;
mmenke 2014/03/12 19:02:42 Maybe add a TODO about checking the new error code
Elly Fong-Jones 2014/03/12 20:10:53 Done.
629 if (error_url != url)
630 return false;
631
632 MaybeStartAutoReloadTimer();
mmenke 2014/03/12 19:02:42 Think this is worth a comment (Something along the
Elly Fong-Jones 2014/03/12 20:10:53 Done.
633 return true;
634 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698