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 |