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