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/logging.h" |
16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
17 #include "base/strings/string16.h" | 17 #include "base/strings/string16.h" |
18 #include "base/values.h" | 18 #include "base/values.h" |
19 #include "chrome/common/localized_error.h" | 19 #include "chrome/common/localized_error.h" |
20 #include "content/public/common/url_constants.h" | |
20 #include "grit/generated_resources.h" | 21 #include "grit/generated_resources.h" |
21 #include "net/base/escape.h" | 22 #include "net/base/escape.h" |
22 #include "net/base/net_errors.h" | 23 #include "net/base/net_errors.h" |
23 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" |
24 #include "third_party/WebKit/public/platform/WebString.h" | 25 #include "third_party/WebKit/public/platform/WebString.h" |
25 #include "third_party/WebKit/public/platform/WebURLError.h" | 26 #include "third_party/WebKit/public/platform/WebURLError.h" |
26 #include "ui/base/l10n/l10n_util.h" | 27 #include "ui/base/l10n/l10n_util.h" |
27 #include "url/gurl.h" | 28 #include "url/gurl.h" |
28 | 29 |
29 namespace { | 30 namespace { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 } | 241 } |
241 } | 242 } |
242 | 243 |
243 if (params->override_suggestions->empty() && | 244 if (params->override_suggestions->empty() && |
244 !params->search_url.is_valid()) { | 245 !params->search_url.is_valid()) { |
245 return NULL; | 246 return NULL; |
246 } | 247 } |
247 return params.release(); | 248 return params.release(); |
248 } | 249 } |
249 | 250 |
251 void ReportAutoReloadSuccess(const blink::WebURLError& error, size_t count) { | |
252 if (error.domain.utf8() != net::kErrorDomain) | |
253 return; | |
254 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", | |
255 -error.reason, | |
256 net::GetAllErrorCodesForUma()); | |
257 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", count); | |
258 if (count == 1) { | |
259 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", | |
260 -error.reason, | |
261 net::GetAllErrorCodesForUma()); | |
262 } | |
263 } | |
264 | |
265 void ReportAutoReloadFailure(const blink::WebURLError& error, size_t count) { | |
266 if (error.domain.utf8() != net::kErrorDomain) | |
267 return; | |
268 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", | |
269 -error.reason, | |
270 net::GetAllErrorCodesForUma()); | |
271 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", count); | |
272 } | |
273 | |
250 } // namespace | 274 } // namespace |
251 | 275 |
252 struct NetErrorHelperCore::ErrorPageInfo { | 276 struct NetErrorHelperCore::ErrorPageInfo { |
253 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) | 277 ErrorPageInfo(blink::WebURLError error, bool was_failed_post) |
254 : error(error), | 278 : error(error), |
255 was_failed_post(was_failed_post), | 279 was_failed_post(was_failed_post), |
256 needs_dns_updates(false), | 280 needs_dns_updates(false), |
257 reload_button_in_page(false), | 281 reload_button_in_page(false), |
258 load_stale_button_in_page(false), | 282 load_stale_button_in_page(false), |
259 is_finished_loading(false) { | 283 is_finished_loading(false), |
284 auto_reload_triggered(false) { | |
260 } | 285 } |
261 | 286 |
262 // Information about the failed page load. | 287 // Information about the failed page load. |
263 blink::WebURLError error; | 288 blink::WebURLError error; |
264 bool was_failed_post; | 289 bool was_failed_post; |
265 | 290 |
266 // Information about the status of the error page. | 291 // Information about the status of the error page. |
267 | 292 |
268 // True if a page is a DNS error page and has not yet received a final DNS | 293 // True if a page is a DNS error page and has not yet received a final DNS |
269 // probe status. | 294 // probe status. |
(...skipping 11 matching lines...) Expand all Loading... | |
281 // the blank page is loading, to get rid of these. | 306 // the blank page is loading, to get rid of these. |
282 std::string navigation_correction_request_body; | 307 std::string navigation_correction_request_body; |
283 | 308 |
284 // Track if specific buttons are included in an error page, for statistics. | 309 // Track if specific buttons are included in an error page, for statistics. |
285 bool reload_button_in_page; | 310 bool reload_button_in_page; |
286 bool load_stale_button_in_page; | 311 bool load_stale_button_in_page; |
287 | 312 |
288 // True if a page has completed loading, at which point it can receive | 313 // True if a page has completed loading, at which point it can receive |
289 // updates. | 314 // updates. |
290 bool is_finished_loading; | 315 bool is_finished_loading; |
316 | |
317 // True if the auto-reload timer has fired and a reload is or has been in | |
318 // flight. | |
319 bool auto_reload_triggered; | |
291 }; | 320 }; |
292 | 321 |
293 bool NetErrorHelperCore::IsReloadableError( | 322 bool NetErrorHelperCore::IsReloadableError( |
294 const NetErrorHelperCore::ErrorPageInfo& info) { | 323 const NetErrorHelperCore::ErrorPageInfo& info) { |
295 return info.error.domain.utf8() == net::kErrorDomain && | 324 return info.error.domain.utf8() == net::kErrorDomain && |
296 info.error.reason != net::ERR_ABORTED && | 325 info.error.reason != net::ERR_ABORTED && |
297 !info.was_failed_post; | 326 !info.was_failed_post; |
298 } | 327 } |
299 | 328 |
300 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 329 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) |
301 : delegate_(delegate), | 330 : delegate_(delegate), |
302 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), | 331 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), |
303 auto_reload_enabled_(false), | 332 auto_reload_enabled_(false), |
304 auto_reload_timer_(new base::Timer(false, false)), | 333 auto_reload_timer_(new base::Timer(false, false)), |
305 // TODO(ellyjones): Make online_ accurate at object creation. | 334 // TODO(ellyjones): Make online_ accurate at object creation. |
306 online_(true), | 335 online_(true), |
307 auto_reload_count_(0), | 336 auto_reload_count_(0), |
308 can_auto_reload_page_(false), | 337 can_auto_reload_page_(false), |
309 navigation_from_button_(NO_BUTTON) { | 338 navigation_from_button_(NO_BUTTON) { |
310 } | 339 } |
311 | 340 |
312 NetErrorHelperCore::~NetErrorHelperCore() { | 341 NetErrorHelperCore::~NetErrorHelperCore() { |
313 if (committed_error_page_info_ && can_auto_reload_page_) { | 342 if (committed_error_page_info_ && can_auto_reload_page_) { |
314 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", | 343 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", |
Randy Smith (Not in Mondays)
2014/04/28 21:05:52
Why isn't this using the helper functions? That v
| |
315 -committed_error_page_info_->error.reason, | 344 -committed_error_page_info_->error.reason, |
316 net::GetAllErrorCodesForUma()); | 345 net::GetAllErrorCodesForUma()); |
317 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); | 346 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); |
318 } | 347 } |
319 } | 348 } |
320 | 349 |
321 void NetErrorHelperCore::CancelPendingFetches() { | 350 void NetErrorHelperCore::CancelPendingFetches() { |
322 // Cancel loading the alternate error page, and prevent any pending error page | 351 // Cancel loading the alternate error page, and prevent any pending error page |
323 // load from starting a new error page load. Swapping in the error page when | 352 // load from starting a new error page load. Swapping in the error page when |
324 // it's finished loading could abort the navigation, otherwise. | 353 // it's finished loading could abort the navigation, otherwise. |
325 if (committed_error_page_info_ && can_auto_reload_page_) { | |
326 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", | |
327 -committed_error_page_info_->error.reason, | |
328 net::GetAllErrorCodesForUma()); | |
329 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); | |
330 } | |
331 if (committed_error_page_info_) { | 354 if (committed_error_page_info_) { |
332 committed_error_page_info_->navigation_correction_url = GURL(); | 355 committed_error_page_info_->navigation_correction_url = GURL(); |
333 committed_error_page_info_->navigation_correction_request_body.clear(); | 356 committed_error_page_info_->navigation_correction_request_body.clear(); |
334 } | 357 } |
335 if (pending_error_page_info_) { | 358 if (pending_error_page_info_) { |
336 pending_error_page_info_->navigation_correction_url = GURL(); | 359 pending_error_page_info_->navigation_correction_url = GURL(); |
337 pending_error_page_info_->navigation_correction_request_body.clear(); | 360 pending_error_page_info_->navigation_correction_request_body.clear(); |
338 } | 361 } |
339 delegate_->CancelFetchNavigationCorrections(); | 362 delegate_->CancelFetchNavigationCorrections(); |
340 auto_reload_timer_->Stop(); | 363 auto_reload_timer_->Stop(); |
341 can_auto_reload_page_ = false; | 364 can_auto_reload_page_ = false; |
342 } | 365 } |
343 | 366 |
344 void NetErrorHelperCore::OnStop() { | 367 void NetErrorHelperCore::OnStop() { |
368 if (committed_error_page_info_ && | |
369 (committed_error_page_info_->auto_reload_triggered || | |
370 auto_reload_timer_->IsRunning())) { | |
371 ReportAutoReloadFailure(committed_error_page_info_->error, | |
372 auto_reload_count_); | |
373 } | |
345 CancelPendingFetches(); | 374 CancelPendingFetches(); |
346 auto_reload_count_ = 0; | 375 auto_reload_count_ = 0; |
347 } | 376 } |
348 | 377 |
349 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { | 378 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { |
350 if (frame_type != MAIN_FRAME) | 379 if (frame_type != MAIN_FRAME) |
351 return; | 380 return; |
352 | 381 |
353 // If there's no pending error page information associated with the page load, | 382 // If there's no pending error page information associated with the page load, |
354 // or the new page is not an error page, then reset pending error page state. | 383 // or the new page is not an error page, then reset pending error page state. |
355 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { | 384 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { |
356 CancelPendingFetches(); | 385 CancelPendingFetches(); |
357 } else if (auto_reload_enabled_) { | 386 } else if (auto_reload_enabled_) { |
358 // If an error load is starting, the resulting error page is autoreloadable. | 387 // If an error load is starting, the resulting error page is autoreloadable. |
359 can_auto_reload_page_ = IsReloadableError(*pending_error_page_info_); | 388 can_auto_reload_page_ = IsReloadableError(*pending_error_page_info_); |
360 } | 389 } |
361 } | 390 } |
362 | 391 |
363 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 392 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type, const GURL& url) { |
364 if (frame_type != MAIN_FRAME) | 393 if (frame_type != MAIN_FRAME) |
365 return; | 394 return; |
366 | 395 |
367 // Track if an error occurred due to a page button press. | 396 // Track if an error occurred due to a page button press. |
368 // This isn't perfect; if (for instance), the server is slow responding | 397 // 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 | 398 // to a request generated from the page reload button, and the user hits |
370 // the browser reload button, this code will still believe the | 399 // the browser reload button, this code will still believe the |
371 // result is from the page reload button. | 400 // result is from the page reload button. |
372 if (committed_error_page_info_ && pending_error_page_info_ && | 401 if (committed_error_page_info_ && pending_error_page_info_ && |
373 navigation_from_button_ != NO_BUTTON && | 402 navigation_from_button_ != NO_BUTTON && |
374 committed_error_page_info_->error.unreachableURL == | 403 committed_error_page_info_->error.unreachableURL == |
375 pending_error_page_info_->error.unreachableURL) { | 404 pending_error_page_info_->error.unreachableURL) { |
376 DCHECK(navigation_from_button_ == RELOAD_BUTTON || | 405 DCHECK(navigation_from_button_ == RELOAD_BUTTON || |
377 navigation_from_button_ == LOAD_STALE_BUTTON); | 406 navigation_from_button_ == LOAD_STALE_BUTTON); |
378 chrome_common_net::RecordEvent( | 407 chrome_common_net::RecordEvent( |
379 navigation_from_button_ == RELOAD_BUTTON ? | 408 navigation_from_button_ == RELOAD_BUTTON ? |
380 chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_ERROR : | 409 chrome_common_net::NETWORK_ERROR_PAGE_RELOAD_BUTTON_ERROR : |
381 chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_ERROR); | 410 chrome_common_net::NETWORK_ERROR_PAGE_LOAD_STALE_BUTTON_ERROR); |
382 } | 411 } |
383 navigation_from_button_ = NO_BUTTON; | 412 navigation_from_button_ = NO_BUTTON; |
384 | 413 |
385 if (committed_error_page_info_ && !pending_error_page_info_ && | 414 if (committed_error_page_info_ && !pending_error_page_info_ && |
386 can_auto_reload_page_) { | 415 committed_error_page_info_->auto_reload_triggered) { |
mmenke
2014/04/28 20:21:14
Right...So whenever we destroy committed_error_pag
Randy Smith (Not in Mondays)
2014/04/28 21:05:52
Why aren't we recording a failure if we're committ
Elly Fong-Jones
2014/04/30 15:34:08
Done.
Elly Fong-Jones
2014/04/30 15:34:08
Because another error page is just a reload attemp
| |
387 int reason = committed_error_page_info_->error.reason; | 416 const blink::WebURLError& error = committed_error_page_info_->error; |
388 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", | 417 const GURL& error_url = error.unreachableURL; |
mmenke
2014/04/28 20:21:14
Does this work? error.unreachableURL is a WebURL,
Elly Fong-Jones
2014/04/30 15:34:08
Yes, because WebURL has a GURL operator() on it.
| |
389 -reason, | 418 if (url == error_url) |
390 net::GetAllErrorCodesForUma()); | 419 ReportAutoReloadSuccess(error, auto_reload_count_); |
391 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_); | 420 else if (url != GURL(content::kUnreachableWebDataURL)) |
Randy Smith (Not in Mondays)
2014/04/28 21:05:52
What is the purpose of this test?
Elly Fong-Jones
2014/04/30 15:34:08
To avoid logging a failure if we're just loading a
| |
392 if (auto_reload_count_ == 1) { | 421 ReportAutoReloadFailure(error, auto_reload_count_); |
393 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", | |
394 -reason, | |
395 net::GetAllErrorCodesForUma()); | |
396 } | |
397 } | 422 } |
398 | 423 |
399 committed_error_page_info_.reset(pending_error_page_info_.release()); | 424 committed_error_page_info_.reset(pending_error_page_info_.release()); |
400 } | 425 } |
401 | 426 |
402 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 427 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
403 if (frame_type != MAIN_FRAME) | 428 if (frame_type != MAIN_FRAME) |
404 return; | 429 return; |
405 | 430 |
406 if (!committed_error_page_info_) { | 431 if (!committed_error_page_info_) { |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
628 bool NetErrorHelperCore::MaybeStartAutoReloadTimer() { | 653 bool NetErrorHelperCore::MaybeStartAutoReloadTimer() { |
629 if (!committed_error_page_info_ || | 654 if (!committed_error_page_info_ || |
630 !committed_error_page_info_->is_finished_loading || | 655 !committed_error_page_info_->is_finished_loading || |
631 !can_auto_reload_page_ || | 656 !can_auto_reload_page_ || |
632 pending_error_page_info_) { | 657 pending_error_page_info_) { |
633 return false; | 658 return false; |
634 } | 659 } |
635 | 660 |
636 DCHECK(IsReloadableError(*committed_error_page_info_)); | 661 DCHECK(IsReloadableError(*committed_error_page_info_)); |
637 | 662 |
663 committed_error_page_info_->auto_reload_triggered = true; | |
mmenke
2014/04/28 20:21:14
So if we never reload because we're offline, but t
Elly Fong-Jones
2014/04/30 15:34:08
Right.
| |
664 | |
638 if (!online_) | 665 if (!online_) |
639 return false; | 666 return false; |
640 | 667 |
641 StartAutoReloadTimer(); | 668 StartAutoReloadTimer(); |
642 return true; | 669 return true; |
643 } | 670 } |
644 | 671 |
645 void NetErrorHelperCore::StartAutoReloadTimer() { | 672 void NetErrorHelperCore::StartAutoReloadTimer() { |
646 DCHECK(committed_error_page_info_); | 673 DCHECK(committed_error_page_info_); |
647 DCHECK(can_auto_reload_page_); | 674 DCHECK(can_auto_reload_page_); |
648 base::TimeDelta delay = GetAutoReloadTime(auto_reload_count_); | 675 base::TimeDelta delay = GetAutoReloadTime(auto_reload_count_); |
649 auto_reload_count_++; | |
650 auto_reload_timer_->Stop(); | 676 auto_reload_timer_->Stop(); |
651 auto_reload_timer_->Start(FROM_HERE, delay, | 677 auto_reload_timer_->Start(FROM_HERE, delay, |
652 base::Bind(&NetErrorHelperCore::Reload, | 678 base::Bind(&NetErrorHelperCore::AutoReloadTimerFired, |
653 base::Unretained(this))); | 679 base::Unretained(this))); |
654 } | 680 } |
655 | 681 |
682 void NetErrorHelperCore::AutoReloadTimerFired() { | |
683 auto_reload_count_++; | |
684 committed_error_page_info_->auto_reload_triggered = true; | |
mmenke
2014/04/28 20:21:14
This isn't needed any more, is it?
Elly Fong-Jones
2014/04/30 15:34:08
Done.
| |
685 Reload(); | |
686 } | |
687 | |
656 void NetErrorHelperCore::NetworkStateChanged(bool online) { | 688 void NetErrorHelperCore::NetworkStateChanged(bool online) { |
657 online_ = online; | 689 online_ = online; |
658 if (auto_reload_timer_->IsRunning()) { | 690 if (auto_reload_timer_->IsRunning()) { |
659 DCHECK(committed_error_page_info_); | 691 DCHECK(committed_error_page_info_); |
660 // If there's an existing timer running, stop it and reset the retry count. | 692 // If there's an existing timer running, stop it and reset the retry count. |
661 auto_reload_timer_->Stop(); | 693 auto_reload_timer_->Stop(); |
662 auto_reload_count_ = 0; | 694 auto_reload_count_ = 0; |
663 } | 695 } |
664 | 696 |
665 // If the network state changed to online, maybe start auto-reloading again. | 697 // If the network state changed to online, maybe start auto-reloading again. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
715 // Visual effects on page are handled in Javascript code. | 747 // Visual effects on page are handled in Javascript code. |
716 chrome_common_net::RecordEvent( | 748 chrome_common_net::RecordEvent( |
717 chrome_common_net::NETWORK_ERROR_PAGE_MORE_BUTTON_CLICKED); | 749 chrome_common_net::NETWORK_ERROR_PAGE_MORE_BUTTON_CLICKED); |
718 return; | 750 return; |
719 case NO_BUTTON: | 751 case NO_BUTTON: |
720 NOTREACHED(); | 752 NOTREACHED(); |
721 return; | 753 return; |
722 } | 754 } |
723 } | 755 } |
724 | 756 |
OLD | NEW |