 Chromium Code Reviews
 Chromium Code Reviews Issue 2481013007:
  Improve tracking of user initiated page loads.  (Closed)
    
  
    Issue 2481013007:
  Improve tracking of user initiated page loads.  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/page_load_tracker.h" | 5 #include "chrome/browser/page_load_metrics/page_load_tracker.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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 } | 80 } | 
| 81 | 81 | 
| 82 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url) { | 82 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url) { | 
| 83 if (aborted_chain_size_same_url > 0) { | 83 if (aborted_chain_size_same_url > 0) { | 
| 84 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeSameURL, | 84 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeSameURL, | 
| 85 aborted_chain_size_same_url); | 85 aborted_chain_size_same_url); | 
| 86 } | 86 } | 
| 87 } | 87 } | 
| 88 | 88 | 
| 89 // TODO(crbug.com/617904): Browser initiated navigations should have | 89 // TODO(crbug.com/617904): Browser initiated navigations should have | 
| 90 // HasUserGesture() set to true. Update this once we get enough data from just | 90 // HasUserGesture() set to true. In the meantime, we consider all | 
| 91 // renderer initiated aborts. | 91 // browser-initiated navigations to be user initiated. | 
| 92 bool IsNavigationUserInitiated(content::NavigationHandle* handle) { | 92 bool IsNavigationUserInitiated(content::NavigationHandle* handle) { | 
| 93 return handle->HasUserGesture(); | 93 return handle->HasUserGesture() || !handle->IsRendererInitiated(); | 
| 94 } | 94 } | 
| 95 | 95 | 
| 96 namespace { | 96 namespace { | 
| 97 | 97 | 
| 98 // Helper to allow use of Optional<> values in LOG() messages. | 98 // Helper to allow use of Optional<> values in LOG() messages. | 
| 99 std::ostream& operator<<(std::ostream& os, | 99 std::ostream& operator<<(std::ostream& os, | 
| 100 const base::Optional<base::TimeDelta>& opt) { | 100 const base::Optional<base::TimeDelta>& opt) { | 
| 101 if (opt) | 101 if (opt) | 
| 102 os << opt.value(); | 102 os << opt.value(); | 
| 103 else | 103 else | 
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 PageLoadMetricsEmbedderInterface* embedder_interface, | 282 PageLoadMetricsEmbedderInterface* embedder_interface, | 
| 283 const GURL& currently_committed_url, | 283 const GURL& currently_committed_url, | 
| 284 content::NavigationHandle* navigation_handle, | 284 content::NavigationHandle* navigation_handle, | 
| 285 int aborted_chain_size, | 285 int aborted_chain_size, | 
| 286 int aborted_chain_size_same_url) | 286 int aborted_chain_size_same_url) | 
| 287 : did_stop_tracking_(false), | 287 : did_stop_tracking_(false), | 
| 288 app_entered_background_(false), | 288 app_entered_background_(false), | 
| 289 navigation_start_(navigation_handle->NavigationStart()), | 289 navigation_start_(navigation_handle->NavigationStart()), | 
| 290 start_url_(navigation_handle->GetURL()), | 290 start_url_(navigation_handle->GetURL()), | 
| 291 abort_type_(ABORT_NONE), | 291 abort_type_(ABORT_NONE), | 
| 292 abort_user_initiated_(false), | |
| 293 started_in_foreground_(in_foreground), | 292 started_in_foreground_(in_foreground), | 
| 294 page_transition_(navigation_handle->GetPageTransition()), | 293 page_transition_(navigation_handle->GetPageTransition()), | 
| 295 num_cache_requests_(0), | 294 num_cache_requests_(0), | 
| 296 num_network_requests_(0), | 295 num_network_requests_(0), | 
| 297 user_gesture_(IsNavigationUserInitiated(navigation_handle)), | 296 user_initiated_(IsNavigationUserInitiated(navigation_handle)), | 
| 298 aborted_chain_size_(aborted_chain_size), | 297 aborted_chain_size_(aborted_chain_size), | 
| 299 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 298 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 
| 300 embedder_interface_(embedder_interface) { | 299 embedder_interface_(embedder_interface) { | 
| 301 DCHECK(!navigation_handle->HasCommitted()); | 300 DCHECK(!navigation_handle->HasCommitted()); | 
| 302 if (embedder_interface_->IsPrerendering( | 301 if (embedder_interface_->IsPrerendering( | 
| 303 navigation_handle->GetWebContents())) { | 302 navigation_handle->GetWebContents())) { | 
| 304 DCHECK(!started_in_foreground_); | 303 DCHECK(!started_in_foreground_); | 
| 305 // For the time being, we do not track prerenders. See crbug.com/648338 for | 304 // For the time being, we do not track prerenders. See crbug.com/648338 for | 
| 306 // details. | 305 // details. | 
| 307 StopTracking(); | 306 StopTracking(); | 
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); | 427 ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); | 
| 429 } | 428 } | 
| 430 | 429 | 
| 431 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnShown); | 430 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnShown); | 
| 432 } | 431 } | 
| 433 | 432 | 
| 434 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 433 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 
| 435 committed_url_ = navigation_handle->GetURL(); | 434 committed_url_ = navigation_handle->GetURL(); | 
| 436 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. | 435 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. | 
| 437 page_transition_ = navigation_handle->GetPageTransition(); | 436 page_transition_ = navigation_handle->GetPageTransition(); | 
| 438 user_gesture_ = navigation_handle->HasUserGesture(); | 437 user_initiated_ = IsNavigationUserInitiated(navigation_handle); | 
| 439 | 438 | 
| 440 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); | 439 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); | 
| 441 LogAbortChainHistograms(navigation_handle); | 440 LogAbortChainHistograms(navigation_handle); | 
| 442 } | 441 } | 
| 443 | 442 | 
| 444 void PageLoadTracker::FailedProvisionalLoad( | 443 void PageLoadTracker::FailedProvisionalLoad( | 
| 445 content::NavigationHandle* navigation_handle) { | 444 content::NavigationHandle* navigation_handle) { | 
| 446 DCHECK(!failed_provisional_load_info_); | 445 DCHECK(!failed_provisional_load_info_); | 
| 447 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 446 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 
| 448 base::TimeTicks::Now() - navigation_handle->NavigationStart(), | 447 base::TimeTicks::Now() - navigation_handle->NavigationStart(), | 
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 583 first_foreground_time = foreground_time_ - navigation_start_; | 582 first_foreground_time = foreground_time_ - navigation_start_; | 
| 584 } | 583 } | 
| 585 | 584 | 
| 586 if (abort_type_ != ABORT_NONE) { | 585 if (abort_type_ != ABORT_NONE) { | 
| 587 DCHECK_GE(abort_time_, navigation_start_); | 586 DCHECK_GE(abort_time_, navigation_start_); | 
| 588 time_to_abort = abort_time_ - navigation_start_; | 587 time_to_abort = abort_time_ - navigation_start_; | 
| 589 } else { | 588 } else { | 
| 590 DCHECK(abort_time_.is_null()); | 589 DCHECK(abort_time_.is_null()); | 
| 591 } | 590 } | 
| 592 | 591 | 
| 593 // abort_type_ == ABORT_NONE implies !abort_user_initiated_. | |
| 594 DCHECK(abort_type_ != ABORT_NONE || !abort_user_initiated_); | |
| 595 return PageLoadExtraInfo( | 592 return PageLoadExtraInfo( | 
| 596 first_background_time, first_foreground_time, started_in_foreground_, | 593 first_background_time, first_foreground_time, started_in_foreground_, | 
| 597 user_gesture_, committed_url_, start_url_, abort_type_, | 594 user_initiated_, committed_url_, start_url_, abort_type_, time_to_abort, | 
| 598 abort_user_initiated_, time_to_abort, num_cache_requests_, | 595 num_cache_requests_, num_network_requests_, metadata_); | 
| 599 num_network_requests_, metadata_); | |
| 600 } | 596 } | 
| 601 | 597 | 
| 602 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 598 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 
| 603 bool user_initiated, | 599 bool user_initiated, | 
| 604 base::TimeTicks timestamp, | 600 base::TimeTicks timestamp, | 
| 605 bool is_certainly_browser_timestamp) { | 601 bool is_certainly_browser_timestamp) { | 
| 606 DCHECK_NE(abort_type, ABORT_NONE); | 602 DCHECK_NE(abort_type, ABORT_NONE); | 
| 607 // Use UpdateAbort to update an already notified PageLoadTracker. | 603 // Use UpdateAbort to update an already notified PageLoadTracker. | 
| 608 if (abort_type_ != ABORT_NONE) | 604 if (abort_type_ != ABORT_NONE) | 
| 609 return; | 605 return; | 
| (...skipping 27 matching lines...) Expand all Loading... | |
| 637 | 633 | 
| 638 bool PageLoadTracker::MatchesOriginalNavigation( | 634 bool PageLoadTracker::MatchesOriginalNavigation( | 
| 639 content::NavigationHandle* navigation_handle) { | 635 content::NavigationHandle* navigation_handle) { | 
| 640 // Neither navigation should have committed. | 636 // Neither navigation should have committed. | 
| 641 DCHECK(!navigation_handle->HasCommitted()); | 637 DCHECK(!navigation_handle->HasCommitted()); | 
| 642 DCHECK(committed_url_.is_empty()); | 638 DCHECK(committed_url_.is_empty()); | 
| 643 return navigation_handle->GetURL() == start_url_; | 639 return navigation_handle->GetURL() == start_url_; | 
| 644 } | 640 } | 
| 645 | 641 | 
| 646 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 642 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 
| 647 bool user_initiated, | 643 bool user_initiated, | 
| 
Charlie Harrison
2016/11/10 14:02:01
This is my main worry. We thread user_initiated th
 
Bryan McQuade
2016/11/10 15:35:41
Ah, I see now that this is whether the nav that ab
 | |
| 648 base::TimeTicks timestamp, | 644 base::TimeTicks timestamp, | 
| 649 bool is_certainly_browser_timestamp) { | 645 bool is_certainly_browser_timestamp) { | 
| 650 // When a provisional navigation commits, that navigation's start time is | 646 // When a provisional navigation commits, that navigation's start time is | 
| 651 // interpreted as the abort time for other provisional loads in the tab. | 647 // interpreted as the abort time for other provisional loads in the tab. | 
| 652 // However, this only makes sense if the committed load started after the | 648 // However, this only makes sense if the committed load started after the | 
| 653 // aborted provisional loads started. Thus we ignore cases where the committed | 649 // aborted provisional loads started. Thus we ignore cases where the committed | 
| 654 // load started before the aborted provisional load, as this would result in | 650 // load started before the aborted provisional load, as this would result in | 
| 655 // recording a negative time-to-abort. The real issue here is that we have to | 651 // recording a negative time-to-abort. The real issue here is that we have to | 
| 656 // infer the cause of aborts. It would be better if the navigation code could | 652 // infer the cause of aborts. It would be better if the navigation code could | 
| 657 // instead report the actual cause of an aborted navigation. See crbug/571647 | 653 // instead report the actual cause of an aborted navigation. See crbug/571647 | 
| 658 // for details. | 654 // for details. | 
| 659 if (timestamp < navigation_start_) { | 655 if (timestamp < navigation_start_) { | 
| 660 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 656 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 
| 661 abort_type_ = ABORT_NONE; | 657 abort_type_ = ABORT_NONE; | 
| 662 abort_time_ = base::TimeTicks(); | 658 abort_time_ = base::TimeTicks(); | 
| 663 return; | 659 return; | 
| 664 } | 660 } | 
| 665 abort_type_ = abort_type; | 661 abort_type_ = abort_type; | 
| 666 abort_time_ = timestamp; | 662 abort_time_ = timestamp; | 
| 667 abort_user_initiated_ = user_initiated && abort_type != ABORT_CLIENT_REDIRECT; | |
| 668 | 663 | 
| 669 if (is_certainly_browser_timestamp) { | 664 if (is_certainly_browser_timestamp) { | 
| 670 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 665 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 
| 671 } | 666 } | 
| 672 } | 667 } | 
| 673 | 668 | 
| 674 } // namespace page_load_metrics | 669 } // namespace page_load_metrics | 
| OLD | NEW |