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" | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |