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 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 observer->OnLoadingBehaviorObserved(extra_info); | 280 observer->OnLoadingBehaviorObserved(extra_info); |
281 } | 281 } |
282 | 282 |
283 } // namespace | 283 } // namespace |
284 | 284 |
285 PageLoadTracker::PageLoadTracker( | 285 PageLoadTracker::PageLoadTracker( |
286 bool in_foreground, | 286 bool in_foreground, |
287 PageLoadMetricsEmbedderInterface* embedder_interface, | 287 PageLoadMetricsEmbedderInterface* embedder_interface, |
288 const GURL& currently_committed_url, | 288 const GURL& currently_committed_url, |
289 content::NavigationHandle* navigation_handle, | 289 content::NavigationHandle* navigation_handle, |
| 290 UserInitiatedInfo user_initiated_info, |
290 int aborted_chain_size, | 291 int aborted_chain_size, |
291 int aborted_chain_size_same_url) | 292 int aborted_chain_size_same_url) |
292 : did_stop_tracking_(false), | 293 : did_stop_tracking_(false), |
293 app_entered_background_(false), | 294 app_entered_background_(false), |
294 navigation_start_(navigation_handle->NavigationStart()), | 295 navigation_start_(navigation_handle->NavigationStart()), |
295 start_url_(navigation_handle->GetURL()), | 296 start_url_(navigation_handle->GetURL()), |
296 abort_type_(ABORT_NONE), | 297 abort_type_(ABORT_NONE), |
297 abort_user_initiated_(false), | 298 abort_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), |
298 started_in_foreground_(in_foreground), | 299 started_in_foreground_(in_foreground), |
299 page_transition_(navigation_handle->GetPageTransition()), | 300 page_transition_(navigation_handle->GetPageTransition()), |
300 num_cache_requests_(0), | 301 num_cache_requests_(0), |
301 num_network_requests_(0), | 302 num_network_requests_(0), |
302 user_initiated_(IsNavigationUserInitiated(navigation_handle)), | 303 user_initiated_info_(user_initiated_info), |
303 aborted_chain_size_(aborted_chain_size), | 304 aborted_chain_size_(aborted_chain_size), |
304 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 305 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
305 embedder_interface_(embedder_interface) { | 306 embedder_interface_(embedder_interface) { |
306 DCHECK(!navigation_handle->HasCommitted()); | 307 DCHECK(!navigation_handle->HasCommitted()); |
307 if (embedder_interface_->IsPrerendering( | 308 if (embedder_interface_->IsPrerendering( |
308 navigation_handle->GetWebContents())) { | 309 navigation_handle->GetWebContents())) { |
309 DCHECK(!started_in_foreground_); | 310 DCHECK(!started_in_foreground_); |
310 // For the time being, we do not track prerenders. See crbug.com/648338 for | 311 // For the time being, we do not track prerenders. See crbug.com/648338 for |
311 // details. | 312 // details. |
312 StopTracking(); | 313 StopTracking(); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 // Make sure we either started in the foreground and haven't been | 408 // Make sure we either started in the foreground and haven't been |
408 // foregrounded yet, or started in the background and have already been | 409 // foregrounded yet, or started in the background and have already been |
409 // foregrounded. | 410 // foregrounded. |
410 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | 411 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); |
411 background_time_ = base::TimeTicks::Now(); | 412 background_time_ = base::TimeTicks::Now(); |
412 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | 413 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); |
413 // Though most cases where a tab is backgrounded are user initiated, we | 414 // Though most cases where a tab is backgrounded are user initiated, we |
414 // can't be certain that we were backgrounded due to a user action. For | 415 // can't be certain that we were backgrounded due to a user action. For |
415 // example, on Android, the screen times out after a period of inactivity, | 416 // example, on Android, the screen times out after a period of inactivity, |
416 // resulting in a non-user-initiated backgrounding. | 417 // resulting in a non-user-initiated backgrounding. |
417 const bool abort_is_user_initiated = false; | 418 NotifyAbort(ABORT_BACKGROUND, UserInitiatedInfo::NotUserInitiated(), |
418 NotifyAbort(ABORT_BACKGROUND, abort_is_user_initiated, background_time_, | 419 background_time_, true); |
419 true); | |
420 } | 420 } |
421 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 421 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
422 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); | 422 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); |
423 } | 423 } |
424 | 424 |
425 void PageLoadTracker::WebContentsShown() { | 425 void PageLoadTracker::WebContentsShown() { |
426 // Only log the first time we foreground in a given page load. | 426 // Only log the first time we foreground in a given page load. |
427 if (foreground_time_.is_null()) { | 427 if (foreground_time_.is_null()) { |
428 // Make sure we either started in the background and haven't been | 428 // Make sure we either started in the background and haven't been |
429 // backgrounded yet, or started in the foreground and have already been | 429 // backgrounded yet, or started in the foreground and have already been |
430 // backgrounded. | 430 // backgrounded. |
431 DCHECK_NE(started_in_foreground_, background_time_.is_null()); | 431 DCHECK_NE(started_in_foreground_, background_time_.is_null()); |
432 foreground_time_ = base::TimeTicks::Now(); | 432 foreground_time_ = base::TimeTicks::Now(); |
433 ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); | 433 ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); |
434 } | 434 } |
435 | 435 |
436 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnShown); | 436 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnShown); |
437 } | 437 } |
438 | 438 |
439 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 439 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { |
440 committed_url_ = navigation_handle->GetURL(); | 440 committed_url_ = navigation_handle->GetURL(); |
441 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. | 441 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. |
442 page_transition_ = navigation_handle->GetPageTransition(); | 442 page_transition_ = navigation_handle->GetPageTransition(); |
443 user_initiated_ = IsNavigationUserInitiated(navigation_handle); | 443 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); |
444 | 444 |
445 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); | 445 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); |
446 LogAbortChainHistograms(navigation_handle); | 446 LogAbortChainHistograms(navigation_handle); |
447 } | 447 } |
448 | 448 |
449 void PageLoadTracker::FailedProvisionalLoad( | 449 void PageLoadTracker::FailedProvisionalLoad( |
450 content::NavigationHandle* navigation_handle) { | 450 content::NavigationHandle* navigation_handle) { |
451 DCHECK(!failed_provisional_load_info_); | 451 DCHECK(!failed_provisional_load_info_); |
452 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 452 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( |
453 base::TimeTicks::Now() - navigation_handle->NavigationStart(), | 453 base::TimeTicks::Now() - navigation_handle->NavigationStart(), |
454 navigation_handle->GetNetErrorCode())); | 454 navigation_handle->GetNetErrorCode())); |
455 } | 455 } |
456 | 456 |
457 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { | 457 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { |
458 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); | 458 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); |
459 } | 459 } |
460 | 460 |
461 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { | 461 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { |
| 462 input_tracker_.OnInputEvent(event); |
462 for (const auto& observer : observers_) { | 463 for (const auto& observer : observers_) { |
463 observer->OnUserInput(event); | 464 observer->OnUserInput(event); |
464 } | 465 } |
465 } | 466 } |
466 | 467 |
467 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { | 468 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { |
468 if (!app_entered_background_) { | 469 if (!app_entered_background_) { |
469 RecordAppBackgroundPageLoadCompleted(false); | 470 RecordAppBackgroundPageLoadCompleted(false); |
470 app_entered_background_ = true; | 471 app_entered_background_ = true; |
471 } | 472 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 first_foreground_time = foreground_time_ - navigation_start_; | 589 first_foreground_time = foreground_time_ - navigation_start_; |
589 } | 590 } |
590 | 591 |
591 if (abort_type_ != ABORT_NONE) { | 592 if (abort_type_ != ABORT_NONE) { |
592 DCHECK_GE(abort_time_, navigation_start_); | 593 DCHECK_GE(abort_time_, navigation_start_); |
593 time_to_abort = abort_time_ - navigation_start_; | 594 time_to_abort = abort_time_ - navigation_start_; |
594 } else { | 595 } else { |
595 DCHECK(abort_time_.is_null()); | 596 DCHECK(abort_time_.is_null()); |
596 } | 597 } |
597 | 598 |
598 // abort_type_ == ABORT_NONE implies !abort_user_initiated_. | 599 // abort_type_ == ABORT_NONE implies abort_user_initiated_info_ is not user |
599 DCHECK(abort_type_ != ABORT_NONE || !abort_user_initiated_); | 600 // initiated. |
| 601 DCHECK(abort_type_ != ABORT_NONE || |
| 602 (!abort_user_initiated_info_.browser_initiated && |
| 603 !abort_user_initiated_info_.user_gesture && |
| 604 !abort_user_initiated_info_.user_input_event)); |
600 return PageLoadExtraInfo( | 605 return PageLoadExtraInfo( |
601 first_background_time, first_foreground_time, started_in_foreground_, | 606 first_background_time, first_foreground_time, started_in_foreground_, |
602 user_initiated_, committed_url_, start_url_, abort_type_, | 607 user_initiated_info_, committed_url_, start_url_, abort_type_, |
603 abort_user_initiated_, time_to_abort, num_cache_requests_, | 608 abort_user_initiated_info_, time_to_abort, num_cache_requests_, |
604 num_network_requests_, metadata_); | 609 num_network_requests_, metadata_); |
605 } | 610 } |
606 | 611 |
607 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 612 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, |
608 bool user_initiated, | 613 UserInitiatedInfo user_initiated_info, |
609 base::TimeTicks timestamp, | 614 base::TimeTicks timestamp, |
610 bool is_certainly_browser_timestamp) { | 615 bool is_certainly_browser_timestamp) { |
611 DCHECK_NE(abort_type, ABORT_NONE); | 616 DCHECK_NE(abort_type, ABORT_NONE); |
612 // Use UpdateAbort to update an already notified PageLoadTracker. | 617 // Use UpdateAbort to update an already notified PageLoadTracker. |
613 if (abort_type_ != ABORT_NONE) | 618 if (abort_type_ != ABORT_NONE) |
614 return; | 619 return; |
615 | 620 |
616 UpdateAbortInternal(abort_type, user_initiated, timestamp, | 621 UpdateAbortInternal(abort_type, user_initiated_info, timestamp, |
617 is_certainly_browser_timestamp); | 622 is_certainly_browser_timestamp); |
618 } | 623 } |
619 | 624 |
620 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, | 625 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, |
621 bool user_initiated, | 626 UserInitiatedInfo user_initiated_info, |
622 base::TimeTicks timestamp, | 627 base::TimeTicks timestamp, |
623 bool is_certainly_browser_timestamp) { | 628 bool is_certainly_browser_timestamp) { |
624 DCHECK_NE(abort_type, ABORT_NONE); | 629 DCHECK_NE(abort_type, ABORT_NONE); |
625 DCHECK_NE(abort_type, ABORT_OTHER); | 630 DCHECK_NE(abort_type, ABORT_OTHER); |
626 DCHECK_EQ(abort_type_, ABORT_OTHER); | 631 DCHECK_EQ(abort_type_, ABORT_OTHER); |
627 | 632 |
628 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 633 // For some aborts (e.g. navigations), the initiated timestamp can be earlier |
629 // than the timestamp that aborted the load. Taking the minimum gives the | 634 // than the timestamp that aborted the load. Taking the minimum gives the |
630 // closest user initiated time known. | 635 // closest user initiated time known. |
631 UpdateAbortInternal(abort_type, user_initiated, | 636 UpdateAbortInternal(abort_type, user_initiated_info, |
632 std::min(abort_time_, timestamp), | 637 std::min(abort_time_, timestamp), |
633 is_certainly_browser_timestamp); | 638 is_certainly_browser_timestamp); |
634 } | 639 } |
635 | 640 |
636 bool PageLoadTracker::IsLikelyProvisionalAbort( | 641 bool PageLoadTracker::IsLikelyProvisionalAbort( |
637 base::TimeTicks abort_cause_time) const { | 642 base::TimeTicks abort_cause_time) const { |
638 // Note that |abort_cause_time - abort_time| can be negative. | 643 // Note that |abort_cause_time - abort_time| can be negative. |
639 return abort_type_ == ABORT_OTHER && | 644 return abort_type_ == ABORT_OTHER && |
640 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 645 (abort_cause_time - abort_time_).InMilliseconds() < 100; |
641 } | 646 } |
642 | 647 |
643 bool PageLoadTracker::MatchesOriginalNavigation( | 648 bool PageLoadTracker::MatchesOriginalNavigation( |
644 content::NavigationHandle* navigation_handle) { | 649 content::NavigationHandle* navigation_handle) { |
645 // Neither navigation should have committed. | 650 // Neither navigation should have committed. |
646 DCHECK(!navigation_handle->HasCommitted()); | 651 DCHECK(!navigation_handle->HasCommitted()); |
647 DCHECK(committed_url_.is_empty()); | 652 DCHECK(committed_url_.is_empty()); |
648 return navigation_handle->GetURL() == start_url_; | 653 return navigation_handle->GetURL() == start_url_; |
649 } | 654 } |
650 | 655 |
651 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 656 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, |
652 bool user_initiated, | 657 UserInitiatedInfo user_initiated_info, |
653 base::TimeTicks timestamp, | 658 base::TimeTicks timestamp, |
654 bool is_certainly_browser_timestamp) { | 659 bool is_certainly_browser_timestamp) { |
655 // When a provisional navigation commits, that navigation's start time is | 660 // When a provisional navigation commits, that navigation's start time is |
656 // interpreted as the abort time for other provisional loads in the tab. | 661 // interpreted as the abort time for other provisional loads in the tab. |
657 // However, this only makes sense if the committed load started after the | 662 // However, this only makes sense if the committed load started after the |
658 // aborted provisional loads started. Thus we ignore cases where the committed | 663 // aborted provisional loads started. Thus we ignore cases where the committed |
659 // load started before the aborted provisional load, as this would result in | 664 // load started before the aborted provisional load, as this would result in |
660 // recording a negative time-to-abort. The real issue here is that we have to | 665 // recording a negative time-to-abort. The real issue here is that we have to |
661 // infer the cause of aborts. It would be better if the navigation code could | 666 // infer the cause of aborts. It would be better if the navigation code could |
662 // instead report the actual cause of an aborted navigation. See crbug/571647 | 667 // instead report the actual cause of an aborted navigation. See crbug/571647 |
663 // for details. | 668 // for details. |
664 if (timestamp < navigation_start_) { | 669 if (timestamp < navigation_start_) { |
665 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 670 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); |
666 abort_type_ = ABORT_NONE; | 671 abort_type_ = ABORT_NONE; |
667 abort_time_ = base::TimeTicks(); | 672 abort_time_ = base::TimeTicks(); |
668 return; | 673 return; |
669 } | 674 } |
670 abort_type_ = abort_type; | 675 abort_type_ = abort_type; |
671 abort_time_ = timestamp; | 676 abort_time_ = timestamp; |
672 // A client redirect can never be user initiated. Due to the way Blink | 677 // A client redirect can never be user initiated. Due to the way Blink |
673 // implements user gesture tracking, where all events that occur within 1 | 678 // implements user gesture tracking, where all events that occur within 1 |
674 // second after a user interaction are considered to be triggered by user | 679 // second after a user interaction are considered to be triggered by user |
675 // activation (based on HTML spec: | 680 // activation (based on HTML spec: |
676 // https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-a
ctivation), | 681 // https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-a
ctivation), |
677 // these navs may sometimes be reported as user initiated by Blink. Thus, we | 682 // these navs may sometimes be reported as user initiated by Blink. Thus, we |
678 // explicitly filter these types of aborts out when deciding if the abort was | 683 // explicitly filter these types of aborts out when deciding if the abort was |
679 // user initiated. | 684 // user initiated. |
680 abort_user_initiated_ = user_initiated && abort_type != ABORT_CLIENT_REDIRECT; | 685 if (abort_type != ABORT_CLIENT_REDIRECT) |
| 686 abort_user_initiated_info_ = user_initiated_info; |
681 | 687 |
682 if (is_certainly_browser_timestamp) { | 688 if (is_certainly_browser_timestamp) { |
683 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 689 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); |
684 } | 690 } |
685 } | 691 } |
686 | 692 |
687 } // namespace page_load_metrics | 693 } // namespace page_load_metrics |
OLD | NEW |