| 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 |