| 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 "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | 5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <ostream> | 8 #include <ostream> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 PageLoadMetricsEmbedderInterface* embedder_interface, | 244 PageLoadMetricsEmbedderInterface* embedder_interface, |
| 245 const GURL& currently_committed_url, | 245 const GURL& currently_committed_url, |
| 246 content::NavigationHandle* navigation_handle, | 246 content::NavigationHandle* navigation_handle, |
| 247 int aborted_chain_size, | 247 int aborted_chain_size, |
| 248 int aborted_chain_size_same_url) | 248 int aborted_chain_size_same_url) |
| 249 : did_stop_tracking_(false), | 249 : did_stop_tracking_(false), |
| 250 navigation_start_(navigation_handle->NavigationStart()), | 250 navigation_start_(navigation_handle->NavigationStart()), |
| 251 url_(navigation_handle->GetURL()), | 251 url_(navigation_handle->GetURL()), |
| 252 abort_type_(ABORT_NONE), | 252 abort_type_(ABORT_NONE), |
| 253 started_in_foreground_(in_foreground), | 253 started_in_foreground_(in_foreground), |
| 254 page_transition_(navigation_handle->GetPageTransition()), |
| 254 aborted_chain_size_(aborted_chain_size), | 255 aborted_chain_size_(aborted_chain_size), |
| 255 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 256 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
| 256 embedder_interface_(embedder_interface) { | 257 embedder_interface_(embedder_interface) { |
| 257 DCHECK(!navigation_handle->HasCommitted()); | 258 DCHECK(!navigation_handle->HasCommitted()); |
| 258 embedder_interface_->RegisterObservers(this); | 259 embedder_interface_->RegisterObservers(this); |
| 259 for (const auto& observer : observers_) { | 260 for (const auto& observer : observers_) { |
| 260 observer->OnStart(navigation_handle, currently_committed_url, | 261 observer->OnStart(navigation_handle, currently_committed_url, |
| 261 started_in_foreground_); | 262 started_in_foreground_); |
| 262 } | 263 } |
| 263 } | 264 } |
| 264 | 265 |
| 265 PageLoadTracker::~PageLoadTracker() { | 266 PageLoadTracker::~PageLoadTracker() { |
| 266 if (did_stop_tracking_) | 267 if (did_stop_tracking_) |
| 267 return; | 268 return; |
| 268 | 269 |
| 269 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 270 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 270 DCHECK_NE(static_cast<bool>(info.time_to_commit), | 271 DCHECK_NE(static_cast<bool>(info.time_to_commit), |
| 271 static_cast<bool>(failed_provisional_load_info_)); | 272 static_cast<bool>(failed_provisional_load_info_)); |
| 272 if (info.time_to_commit && timing_.IsEmpty()) { | 273 if (info.time_to_commit && timing_.IsEmpty()) { |
| 273 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 274 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
| 274 const base::TimeTicks commit_time = | 275 const base::TimeTicks commit_time = |
| 275 navigation_start_ + info.time_to_commit.value(); | 276 navigation_start_ + info.time_to_commit.value(); |
| 276 PAGE_LOAD_HISTOGRAM(internal::kCommitToCompleteNoTimingIPCs, | 277 PAGE_LOAD_HISTOGRAM(internal::kCommitToCompleteNoTimingIPCs, |
| 277 base::TimeTicks::Now() - commit_time); | 278 base::TimeTicks::Now() - commit_time); |
| 278 } | 279 } |
| 279 // Recall that trackers that are given ABORT_UNKNOWN_NAVIGATION have their | 280 |
| 280 // chain length added to the next navigation. Take care not to double count | 281 // Don't include any aborts that resulted in a new navigation, as the chain |
| 281 // them. Also do not double count committed loads, which call this already. | 282 // length will be included in the aborter PageLoadTracker. |
| 282 if (commit_time_.is_null() && abort_type_ != ABORT_UNKNOWN_NAVIGATION) | 283 if (commit_time_.is_null() && abort_type_ != ABORT_RELOAD && |
| 284 abort_type_ != ABORT_FORWARD_BACK && |
| 285 abort_type_ != ABORT_NEW_NAVIGATION) { |
| 283 LogAbortChainHistograms(nullptr); | 286 LogAbortChainHistograms(nullptr); |
| 287 } |
| 284 | 288 |
| 285 for (const auto& observer : observers_) { | 289 for (const auto& observer : observers_) { |
| 286 if (failed_provisional_load_info_) { | 290 if (failed_provisional_load_info_) { |
| 287 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); | 291 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); |
| 288 } else { | 292 } else { |
| 289 observer->OnComplete(timing_, info); | 293 observer->OnComplete(timing_, info); |
| 290 } | 294 } |
| 291 } | 295 } |
| 292 } | 296 } |
| 293 | 297 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 for (const auto& observer : observers_) | 369 for (const auto& observer : observers_) |
| 366 observer->OnShown(); | 370 observer->OnShown(); |
| 367 } | 371 } |
| 368 | 372 |
| 369 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 373 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { |
| 370 // TODO(bmcquade): To improve accuracy, consider adding commit time to | 374 // TODO(bmcquade): To improve accuracy, consider adding commit time to |
| 371 // NavigationHandle. Taking a timestamp here should be close enough for now. | 375 // NavigationHandle. Taking a timestamp here should be close enough for now. |
| 372 commit_time_ = base::TimeTicks::Now(); | 376 commit_time_ = base::TimeTicks::Now(); |
| 373 ClampBrowserTimestampIfInterProcessTimeTickSkew(&commit_time_); | 377 ClampBrowserTimestampIfInterProcessTimeTickSkew(&commit_time_); |
| 374 url_ = navigation_handle->GetURL(); | 378 url_ = navigation_handle->GetURL(); |
| 379 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. |
| 380 page_transition_ = navigation_handle->GetPageTransition(); |
| 375 for (const auto& observer : observers_) { | 381 for (const auto& observer : observers_) { |
| 376 observer->OnCommit(navigation_handle); | 382 observer->OnCommit(navigation_handle); |
| 377 } | 383 } |
| 378 LogAbortChainHistograms(navigation_handle); | 384 LogAbortChainHistograms(navigation_handle); |
| 379 } | 385 } |
| 380 | 386 |
| 381 void PageLoadTracker::FailedProvisionalLoad( | 387 void PageLoadTracker::FailedProvisionalLoad( |
| 382 content::NavigationHandle* navigation_handle) { | 388 content::NavigationHandle* navigation_handle) { |
| 383 DCHECK(!failed_provisional_load_info_); | 389 DCHECK(!failed_provisional_load_info_); |
| 384 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 390 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 DCHECK_EQ(abort_type_, ABORT_OTHER); | 545 DCHECK_EQ(abort_type_, ABORT_OTHER); |
| 540 | 546 |
| 541 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 547 // For some aborts (e.g. navigations), the initiated timestamp can be earlier |
| 542 // than the timestamp that aborted the load. Taking the minimum gives the | 548 // than the timestamp that aborted the load. Taking the minimum gives the |
| 543 // closest user initiated time known. | 549 // closest user initiated time known. |
| 544 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp), | 550 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp), |
| 545 is_certainly_browser_timestamp); | 551 is_certainly_browser_timestamp); |
| 546 } | 552 } |
| 547 | 553 |
| 548 bool PageLoadTracker::IsLikelyProvisionalAbort( | 554 bool PageLoadTracker::IsLikelyProvisionalAbort( |
| 549 base::TimeTicks abort_cause_time) { | 555 base::TimeTicks abort_cause_time) const { |
| 550 // Note that |abort_cause_time - abort_time| can be negative. | 556 // Note that |abort_cause_time - abort_time| can be negative. |
| 551 return abort_type_ == ABORT_OTHER && | 557 return abort_type_ == ABORT_OTHER && |
| 552 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 558 (abort_cause_time - abort_time_).InMilliseconds() < 100; |
| 553 } | 559 } |
| 554 | 560 |
| 555 bool PageLoadTracker::MatchesOriginalNavigation( | 561 bool PageLoadTracker::MatchesOriginalNavigation( |
| 556 content::NavigationHandle* navigation_handle) { | 562 content::NavigationHandle* navigation_handle) { |
| 557 // Neither navigation should have committed. | 563 // Neither navigation should have committed. |
| 558 DCHECK(!navigation_handle->HasCommitted()); | 564 DCHECK(!navigation_handle->HasCommitted()); |
| 559 DCHECK(commit_time_.is_null()); | 565 DCHECK(commit_time_.is_null()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 646 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 641 bool handled = true; | 647 bool handled = true; |
| 642 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message, | 648 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message, |
| 643 render_frame_host) | 649 render_frame_host) |
| 644 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) | 650 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) |
| 645 IPC_MESSAGE_UNHANDLED(handled = false) | 651 IPC_MESSAGE_UNHANDLED(handled = false) |
| 646 IPC_END_MESSAGE_MAP() | 652 IPC_END_MESSAGE_MAP() |
| 647 return handled; | 653 return handled; |
| 648 } | 654 } |
| 649 | 655 |
| 650 void MetricsWebContentsObserver::DidStartNavigation( | 656 void MetricsWebContentsObserver::WillStartNavigationRequest( |
| 651 content::NavigationHandle* navigation_handle) { | 657 content::NavigationHandle* navigation_handle) { |
| 652 if (!navigation_handle->IsInMainFrame()) | 658 if (!navigation_handle->IsInMainFrame()) |
| 653 return; | 659 return; |
| 654 | 660 |
| 655 std::unique_ptr<PageLoadTracker> last_aborted = | 661 std::unique_ptr<PageLoadTracker> last_aborted = |
| 656 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle); | 662 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle); |
| 657 | 663 |
| 658 int chain_size_same_url = 0; | 664 int chain_size_same_url = 0; |
| 659 int chain_size = 0; | 665 int chain_size = 0; |
| 660 if (last_aborted) { | 666 if (last_aborted) { |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 } | 865 } |
| 860 | 866 |
| 861 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { | 867 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { |
| 862 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now(), true); | 868 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now(), true); |
| 863 } | 869 } |
| 864 | 870 |
| 865 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( | 871 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( |
| 866 UserAbortType abort_type, | 872 UserAbortType abort_type, |
| 867 base::TimeTicks timestamp, | 873 base::TimeTicks timestamp, |
| 868 bool is_certainly_browser_timestamp) { | 874 bool is_certainly_browser_timestamp) { |
| 869 if (committed_load_) | 875 if (committed_load_) { |
| 870 committed_load_->NotifyAbort(abort_type, timestamp, | 876 committed_load_->NotifyAbort(abort_type, timestamp, |
| 871 is_certainly_browser_timestamp); | 877 is_certainly_browser_timestamp); |
| 878 } |
| 872 for (const auto& kv : provisional_loads_) { | 879 for (const auto& kv : provisional_loads_) { |
| 873 kv.second->NotifyAbort(abort_type, timestamp, | 880 kv.second->NotifyAbort(abort_type, timestamp, |
| 874 is_certainly_browser_timestamp); | 881 is_certainly_browser_timestamp); |
| 875 } | 882 } |
| 876 for (const auto& tracker : aborted_provisional_loads_) { | 883 for (const auto& tracker : aborted_provisional_loads_) { |
| 877 if (tracker->IsLikelyProvisionalAbort(timestamp)) | 884 if (tracker->IsLikelyProvisionalAbort(timestamp)) { |
| 878 tracker->UpdateAbort(abort_type, timestamp, | 885 tracker->UpdateAbort(abort_type, timestamp, |
| 879 is_certainly_browser_timestamp); | 886 is_certainly_browser_timestamp); |
| 887 } |
| 880 } | 888 } |
| 881 aborted_provisional_loads_.clear(); | 889 aborted_provisional_loads_.clear(); |
| 882 } | 890 } |
| 883 | 891 |
| 884 std::unique_ptr<PageLoadTracker> | 892 std::unique_ptr<PageLoadTracker> |
| 885 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( | 893 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( |
| 886 content::NavigationHandle* new_navigation) { | 894 content::NavigationHandle* new_navigation) { |
| 887 // If there are multiple aborted loads that can be attributed to this one, | 895 // If there are multiple aborted loads that can be attributed to this one, |
| 888 // just count the latest one for simplicity. Other loads will fall into the | 896 // just count the latest one for simplicity. Other loads will fall into the |
| 889 // OTHER bucket, though there shouldn't be very many. | 897 // OTHER bucket, though there shouldn't be very many. |
| 890 if (aborted_provisional_loads_.size() == 0) | 898 if (aborted_provisional_loads_.size() == 0) |
| 891 return nullptr; | 899 return nullptr; |
| 892 if (aborted_provisional_loads_.size() > 1) | 900 if (aborted_provisional_loads_.size() > 1) |
| 893 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); | 901 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); |
| 894 | 902 |
| 895 std::unique_ptr<PageLoadTracker> last_aborted_load = | 903 std::unique_ptr<PageLoadTracker> last_aborted_load = |
| 896 std::move(aborted_provisional_loads_.back()); | 904 std::move(aborted_provisional_loads_.back()); |
| 897 aborted_provisional_loads_.pop_back(); | 905 aborted_provisional_loads_.pop_back(); |
| 898 | 906 |
| 899 base::TimeTicks timestamp = new_navigation->NavigationStart(); | 907 base::TimeTicks timestamp = new_navigation->NavigationStart(); |
| 900 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) | 908 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) { |
| 901 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp, false); | 909 last_aborted_load->UpdateAbort( |
| 910 AbortTypeForPageTransition(new_navigation->GetPageTransition()), |
| 911 timestamp, false); |
| 912 } |
| 902 | 913 |
| 903 aborted_provisional_loads_.clear(); | 914 aborted_provisional_loads_.clear(); |
| 904 return last_aborted_load; | 915 return last_aborted_load; |
| 905 } | 916 } |
| 906 | 917 |
| 907 void MetricsWebContentsObserver::OnTimingUpdated( | 918 void MetricsWebContentsObserver::OnTimingUpdated( |
| 908 content::RenderFrameHost* render_frame_host, | 919 content::RenderFrameHost* render_frame_host, |
| 909 const PageLoadTiming& timing, | 920 const PageLoadTiming& timing, |
| 910 const PageLoadMetadata& metadata) { | 921 const PageLoadMetadata& metadata) { |
| 911 bool error = false; | 922 bool error = false; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 if (navigation_handle->IsSamePage() || navigation_handle->IsErrorPage()) | 962 if (navigation_handle->IsSamePage() || navigation_handle->IsErrorPage()) |
| 952 return false; | 963 return false; |
| 953 const std::string& mime_type = web_contents()->GetContentsMimeType(); | 964 const std::string& mime_type = web_contents()->GetContentsMimeType(); |
| 954 if (mime_type != "text/html" && mime_type != "application/xhtml+xml") | 965 if (mime_type != "text/html" && mime_type != "application/xhtml+xml") |
| 955 return false; | 966 return false; |
| 956 } | 967 } |
| 957 return true; | 968 return true; |
| 958 } | 969 } |
| 959 | 970 |
| 960 } // namespace page_load_metrics | 971 } // namespace page_load_metrics |
| OLD | NEW |