OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/page_load_metrics/browser/metrics_web_contents_observer.h" | 5 #include "components/page_load_metrics/browser/metrics_web_contents_observer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/ptr_util.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
15 #include "base/metrics/user_metrics.h" | 15 #include "base/metrics/user_metrics.h" |
16 #include "components/page_load_metrics/browser/page_load_metrics_util.h" | 16 #include "components/page_load_metrics/browser/page_load_metrics_util.h" |
17 #include "components/page_load_metrics/common/page_load_metrics_messages.h" | 17 #include "components/page_load_metrics/common/page_load_metrics_messages.h" |
18 #include "components/page_load_metrics/common/page_load_timing.h" | 18 #include "components/page_load_metrics/common/page_load_timing.h" |
19 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/navigation_details.h" | 20 #include "content/public/browser/navigation_details.h" |
21 #include "content/public/browser/navigation_handle.h" | 21 #include "content/public/browser/navigation_handle.h" |
22 #include "content/public/browser/render_frame_host.h" | 22 #include "content/public/browser/render_frame_host.h" |
23 #include "content/public/browser/web_contents.h" | 23 #include "content/public/browser/web_contents.h" |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 return true; | 359 return true; |
360 } | 360 } |
361 return false; | 361 return false; |
362 } | 362 } |
363 | 363 |
364 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { | 364 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { |
365 renderer_tracked_ = renderer_tracked; | 365 renderer_tracked_ = renderer_tracked; |
366 } | 366 } |
367 | 367 |
368 void PageLoadTracker::AddObserver( | 368 void PageLoadTracker::AddObserver( |
369 scoped_ptr<PageLoadMetricsObserver> observer) { | 369 std::unique_ptr<PageLoadMetricsObserver> observer) { |
370 observers_.push_back(std::move(observer)); | 370 observers_.push_back(std::move(observer)); |
371 } | 371 } |
372 | 372 |
373 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { | 373 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { |
374 base::TimeDelta first_background_time; | 374 base::TimeDelta first_background_time; |
375 base::TimeDelta first_foreground_time; | 375 base::TimeDelta first_foreground_time; |
376 base::TimeDelta time_to_abort; | 376 base::TimeDelta time_to_abort; |
377 base::TimeDelta time_to_commit; | 377 base::TimeDelta time_to_commit; |
378 if (!background_time_.is_null()) | 378 if (!background_time_.is_null()) |
379 first_background_time = background_time_ - navigation_start_; | 379 first_background_time = background_time_ - navigation_start_; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 abort_time_ = base::TimeTicks(); | 452 abort_time_ = base::TimeTicks(); |
453 return; | 453 return; |
454 } | 454 } |
455 abort_type_ = abort_type; | 455 abort_type_ = abort_type; |
456 abort_time_ = timestamp; | 456 abort_time_ = timestamp; |
457 } | 457 } |
458 | 458 |
459 // static | 459 // static |
460 MetricsWebContentsObserver::MetricsWebContentsObserver( | 460 MetricsWebContentsObserver::MetricsWebContentsObserver( |
461 content::WebContents* web_contents, | 461 content::WebContents* web_contents, |
462 scoped_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) | 462 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) |
463 : content::WebContentsObserver(web_contents), | 463 : content::WebContentsObserver(web_contents), |
464 in_foreground_(false), | 464 in_foreground_(false), |
465 embedder_interface_(std::move(embedder_interface)) {} | 465 embedder_interface_(std::move(embedder_interface)) {} |
466 | 466 |
467 MetricsWebContentsObserver* MetricsWebContentsObserver::CreateForWebContents( | 467 MetricsWebContentsObserver* MetricsWebContentsObserver::CreateForWebContents( |
468 content::WebContents* web_contents, | 468 content::WebContents* web_contents, |
469 scoped_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) { | 469 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) { |
470 DCHECK(web_contents); | 470 DCHECK(web_contents); |
471 | 471 |
472 MetricsWebContentsObserver* metrics = FromWebContents(web_contents); | 472 MetricsWebContentsObserver* metrics = FromWebContents(web_contents); |
473 if (!metrics) { | 473 if (!metrics) { |
474 metrics = new MetricsWebContentsObserver(web_contents, | 474 metrics = new MetricsWebContentsObserver(web_contents, |
475 std::move(embedder_interface)); | 475 std::move(embedder_interface)); |
476 web_contents->SetUserData(UserDataKey(), metrics); | 476 web_contents->SetUserData(UserDataKey(), metrics); |
477 } | 477 } |
478 return metrics; | 478 return metrics; |
479 } | 479 } |
(...skipping 15 matching lines...) Expand all Loading... |
495 return handled; | 495 return handled; |
496 } | 496 } |
497 | 497 |
498 void MetricsWebContentsObserver::DidStartNavigation( | 498 void MetricsWebContentsObserver::DidStartNavigation( |
499 content::NavigationHandle* navigation_handle) { | 499 content::NavigationHandle* navigation_handle) { |
500 if (!navigation_handle->IsInMainFrame()) | 500 if (!navigation_handle->IsInMainFrame()) |
501 return; | 501 return; |
502 if (embedder_interface_->IsPrerendering(web_contents())) | 502 if (embedder_interface_->IsPrerendering(web_contents())) |
503 return; | 503 return; |
504 | 504 |
505 scoped_ptr<PageLoadTracker> last_aborted = | 505 std::unique_ptr<PageLoadTracker> last_aborted = |
506 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle); | 506 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle); |
507 | 507 |
508 int chain_size_same_url = 0; | 508 int chain_size_same_url = 0; |
509 int chain_size = 0; | 509 int chain_size = 0; |
510 if (last_aborted) { | 510 if (last_aborted) { |
511 if (last_aborted->MatchesOriginalNavigation(navigation_handle)) { | 511 if (last_aborted->MatchesOriginalNavigation(navigation_handle)) { |
512 chain_size_same_url = last_aborted->aborted_chain_size_same_url() + 1; | 512 chain_size_same_url = last_aborted->aborted_chain_size_same_url() + 1; |
513 } else if (last_aborted->aborted_chain_size_same_url() > 0) { | 513 } else if (last_aborted->aborted_chain_size_same_url() > 0) { |
514 LogAbortChainSameURLHistogram( | 514 LogAbortChainSameURLHistogram( |
515 last_aborted->aborted_chain_size_same_url()); | 515 last_aborted->aborted_chain_size_same_url()); |
516 } | 516 } |
517 chain_size = last_aborted->aborted_chain_size() + 1; | 517 chain_size = last_aborted->aborted_chain_size() + 1; |
518 } | 518 } |
519 | 519 |
520 // We can have two provisional loads in some cases. E.g. a same-site | 520 // We can have two provisional loads in some cases. E.g. a same-site |
521 // navigation can have a concurrent cross-process navigation started | 521 // navigation can have a concurrent cross-process navigation started |
522 // from the omnibox. | 522 // from the omnibox. |
523 DCHECK_GT(2ul, provisional_loads_.size()); | 523 DCHECK_GT(2ul, provisional_loads_.size()); |
524 // Passing raw pointers to observers_ and embedder_interface_ is safe because | 524 // Passing raw pointers to observers_ and embedder_interface_ is safe because |
525 // the MetricsWebContentsObserver owns them both list and they are torn down | 525 // the MetricsWebContentsObserver owns them both list and they are torn down |
526 // after the PageLoadTracker. The PageLoadTracker does not hold on to | 526 // after the PageLoadTracker. The PageLoadTracker does not hold on to |
527 // committed_load_ or navigation_handle beyond the scope of the constructor. | 527 // committed_load_ or navigation_handle beyond the scope of the constructor. |
528 provisional_loads_.insert(std::make_pair( | 528 provisional_loads_.insert(std::make_pair( |
529 navigation_handle, | 529 navigation_handle, |
530 make_scoped_ptr(new PageLoadTracker( | 530 base::WrapUnique(new PageLoadTracker( |
531 in_foreground_, embedder_interface_.get(), committed_load_.get(), | 531 in_foreground_, embedder_interface_.get(), committed_load_.get(), |
532 navigation_handle, chain_size, chain_size_same_url)))); | 532 navigation_handle, chain_size, chain_size_same_url)))); |
533 } | 533 } |
534 | 534 |
535 void MetricsWebContentsObserver::DidFinishNavigation( | 535 void MetricsWebContentsObserver::DidFinishNavigation( |
536 content::NavigationHandle* navigation_handle) { | 536 content::NavigationHandle* navigation_handle) { |
537 if (!navigation_handle->IsInMainFrame()) | 537 if (!navigation_handle->IsInMainFrame()) |
538 return; | 538 return; |
539 | 539 |
540 scoped_ptr<PageLoadTracker> finished_nav( | 540 std::unique_ptr<PageLoadTracker> finished_nav( |
541 std::move(provisional_loads_[navigation_handle])); | 541 std::move(provisional_loads_[navigation_handle])); |
542 provisional_loads_.erase(navigation_handle); | 542 provisional_loads_.erase(navigation_handle); |
543 | 543 |
544 // There's a chance a navigation could have started before we were added to a | 544 // There's a chance a navigation could have started before we were added to a |
545 // tab. Bail out early if this is the case. | 545 // tab. Bail out early if this is the case. |
546 if (!finished_nav) | 546 if (!finished_nav) |
547 return; | 547 return; |
548 | 548 |
549 // Handle a pre-commit error here. Navigations that result in an error page | 549 // Handle a pre-commit error here. Navigations that result in an error page |
550 // will be ignored. Note that downloads/204s will result in HasCommitted() | 550 // will be ignored. Note that downloads/204s will result in HasCommitted() |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 for (const auto& kv : provisional_loads_) { | 666 for (const auto& kv : provisional_loads_) { |
667 kv.second->NotifyAbort(abort_type, timestamp); | 667 kv.second->NotifyAbort(abort_type, timestamp); |
668 } | 668 } |
669 for (const auto& tracker : aborted_provisional_loads_) { | 669 for (const auto& tracker : aborted_provisional_loads_) { |
670 if (tracker->IsLikelyProvisionalAbort(timestamp)) | 670 if (tracker->IsLikelyProvisionalAbort(timestamp)) |
671 tracker->UpdateAbort(abort_type, timestamp); | 671 tracker->UpdateAbort(abort_type, timestamp); |
672 } | 672 } |
673 aborted_provisional_loads_.clear(); | 673 aborted_provisional_loads_.clear(); |
674 } | 674 } |
675 | 675 |
676 scoped_ptr<PageLoadTracker> | 676 std::unique_ptr<PageLoadTracker> |
677 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( | 677 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( |
678 content::NavigationHandle* new_navigation) { | 678 content::NavigationHandle* new_navigation) { |
679 // If there are multiple aborted loads that can be attributed to this one, | 679 // If there are multiple aborted loads that can be attributed to this one, |
680 // just count the latest one for simplicity. Other loads will fall into the | 680 // just count the latest one for simplicity. Other loads will fall into the |
681 // OTHER bucket, though there shouldn't be very many. | 681 // OTHER bucket, though there shouldn't be very many. |
682 if (aborted_provisional_loads_.size() == 0) | 682 if (aborted_provisional_loads_.size() == 0) |
683 return nullptr; | 683 return nullptr; |
684 if (aborted_provisional_loads_.size() > 1) | 684 if (aborted_provisional_loads_.size() > 1) |
685 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); | 685 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); |
686 | 686 |
687 scoped_ptr<PageLoadTracker> last_aborted_load = | 687 std::unique_ptr<PageLoadTracker> last_aborted_load = |
688 std::move(aborted_provisional_loads_.back()); | 688 std::move(aborted_provisional_loads_.back()); |
689 aborted_provisional_loads_.pop_back(); | 689 aborted_provisional_loads_.pop_back(); |
690 | 690 |
691 base::TimeTicks timestamp = new_navigation->NavigationStart(); | 691 base::TimeTicks timestamp = new_navigation->NavigationStart(); |
692 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) | 692 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) |
693 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp); | 693 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp); |
694 | 694 |
695 aborted_provisional_loads_.clear(); | 695 aborted_provisional_loads_.clear(); |
696 return last_aborted_load; | 696 return last_aborted_load; |
697 } | 697 } |
(...skipping 28 matching lines...) Expand all Loading... |
726 | 726 |
727 if (!committed_load_->UpdateTiming(timing, metadata)) { | 727 if (!committed_load_->UpdateTiming(timing, metadata)) { |
728 // If the page load tracker cannot update its timing, something is wrong | 728 // If the page load tracker cannot update its timing, something is wrong |
729 // with the IPC (it's from another load, or it's invalid in some other way). | 729 // with the IPC (it's from another load, or it's invalid in some other way). |
730 // We expect this to be a rare occurrence. | 730 // We expect this to be a rare occurrence. |
731 RecordInternalError(ERR_BAD_TIMING_IPC); | 731 RecordInternalError(ERR_BAD_TIMING_IPC); |
732 } | 732 } |
733 } | 733 } |
734 | 734 |
735 } // namespace page_load_metrics | 735 } // namespace page_load_metrics |
OLD | NEW |