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_ |
Charlie Harrison
2016/12/07 15:45:13
nit: Is !abort_user_initiated_info_ even defined?
Bryan McQuade
2016/12/07 16:32:00
Nope, does not compile. This was intended to be ps
| |
599 DCHECK(abort_type_ != ABORT_NONE || !abort_user_initiated_); | 600 DCHECK(abort_type_ != ABORT_NONE || |
601 (!abort_user_initiated_info_.browser_initiated && | |
602 !abort_user_initiated_info_.user_gesture && | |
603 !abort_user_initiated_info_.user_input_event)); | |
600 return PageLoadExtraInfo( | 604 return PageLoadExtraInfo( |
601 first_background_time, first_foreground_time, started_in_foreground_, | 605 first_background_time, first_foreground_time, started_in_foreground_, |
602 user_initiated_, committed_url_, start_url_, abort_type_, | 606 user_initiated_info_, committed_url_, start_url_, abort_type_, |
603 abort_user_initiated_, time_to_abort, num_cache_requests_, | 607 abort_user_initiated_info_, time_to_abort, num_cache_requests_, |
604 num_network_requests_, metadata_); | 608 num_network_requests_, metadata_); |
605 } | 609 } |
606 | 610 |
607 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 611 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, |
608 bool user_initiated, | 612 UserInitiatedInfo user_initiated_info, |
609 base::TimeTicks timestamp, | 613 base::TimeTicks timestamp, |
610 bool is_certainly_browser_timestamp) { | 614 bool is_certainly_browser_timestamp) { |
611 DCHECK_NE(abort_type, ABORT_NONE); | 615 DCHECK_NE(abort_type, ABORT_NONE); |
612 // Use UpdateAbort to update an already notified PageLoadTracker. | 616 // Use UpdateAbort to update an already notified PageLoadTracker. |
613 if (abort_type_ != ABORT_NONE) | 617 if (abort_type_ != ABORT_NONE) |
614 return; | 618 return; |
615 | 619 |
616 UpdateAbortInternal(abort_type, user_initiated, timestamp, | 620 UpdateAbortInternal(abort_type, user_initiated_info, timestamp, |
617 is_certainly_browser_timestamp); | 621 is_certainly_browser_timestamp); |
618 } | 622 } |
619 | 623 |
620 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, | 624 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, |
621 bool user_initiated, | 625 UserInitiatedInfo user_initiated_info, |
622 base::TimeTicks timestamp, | 626 base::TimeTicks timestamp, |
623 bool is_certainly_browser_timestamp) { | 627 bool is_certainly_browser_timestamp) { |
624 DCHECK_NE(abort_type, ABORT_NONE); | 628 DCHECK_NE(abort_type, ABORT_NONE); |
625 DCHECK_NE(abort_type, ABORT_OTHER); | 629 DCHECK_NE(abort_type, ABORT_OTHER); |
626 DCHECK_EQ(abort_type_, ABORT_OTHER); | 630 DCHECK_EQ(abort_type_, ABORT_OTHER); |
627 | 631 |
628 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 632 // 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 | 633 // than the timestamp that aborted the load. Taking the minimum gives the |
630 // closest user initiated time known. | 634 // closest user initiated time known. |
631 UpdateAbortInternal(abort_type, user_initiated, | 635 UpdateAbortInternal(abort_type, user_initiated_info, |
632 std::min(abort_time_, timestamp), | 636 std::min(abort_time_, timestamp), |
633 is_certainly_browser_timestamp); | 637 is_certainly_browser_timestamp); |
634 } | 638 } |
635 | 639 |
636 bool PageLoadTracker::IsLikelyProvisionalAbort( | 640 bool PageLoadTracker::IsLikelyProvisionalAbort( |
637 base::TimeTicks abort_cause_time) const { | 641 base::TimeTicks abort_cause_time) const { |
638 // Note that |abort_cause_time - abort_time| can be negative. | 642 // Note that |abort_cause_time - abort_time| can be negative. |
639 return abort_type_ == ABORT_OTHER && | 643 return abort_type_ == ABORT_OTHER && |
640 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 644 (abort_cause_time - abort_time_).InMilliseconds() < 100; |
641 } | 645 } |
642 | 646 |
643 bool PageLoadTracker::MatchesOriginalNavigation( | 647 bool PageLoadTracker::MatchesOriginalNavigation( |
644 content::NavigationHandle* navigation_handle) { | 648 content::NavigationHandle* navigation_handle) { |
645 // Neither navigation should have committed. | 649 // Neither navigation should have committed. |
646 DCHECK(!navigation_handle->HasCommitted()); | 650 DCHECK(!navigation_handle->HasCommitted()); |
647 DCHECK(committed_url_.is_empty()); | 651 DCHECK(committed_url_.is_empty()); |
648 return navigation_handle->GetURL() == start_url_; | 652 return navigation_handle->GetURL() == start_url_; |
649 } | 653 } |
650 | 654 |
651 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 655 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, |
652 bool user_initiated, | 656 UserInitiatedInfo user_initiated_info, |
653 base::TimeTicks timestamp, | 657 base::TimeTicks timestamp, |
654 bool is_certainly_browser_timestamp) { | 658 bool is_certainly_browser_timestamp) { |
655 // When a provisional navigation commits, that navigation's start time is | 659 // When a provisional navigation commits, that navigation's start time is |
656 // interpreted as the abort time for other provisional loads in the tab. | 660 // 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 | 661 // However, this only makes sense if the committed load started after the |
658 // aborted provisional loads started. Thus we ignore cases where the committed | 662 // aborted provisional loads started. Thus we ignore cases where the committed |
659 // load started before the aborted provisional load, as this would result in | 663 // 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 | 664 // 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 | 665 // 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 | 666 // instead report the actual cause of an aborted navigation. See crbug/571647 |
663 // for details. | 667 // for details. |
664 if (timestamp < navigation_start_) { | 668 if (timestamp < navigation_start_) { |
665 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 669 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); |
666 abort_type_ = ABORT_NONE; | 670 abort_type_ = ABORT_NONE; |
667 abort_time_ = base::TimeTicks(); | 671 abort_time_ = base::TimeTicks(); |
668 return; | 672 return; |
669 } | 673 } |
670 abort_type_ = abort_type; | 674 abort_type_ = abort_type; |
671 abort_time_ = timestamp; | 675 abort_time_ = timestamp; |
672 // A client redirect can never be user initiated. Due to the way Blink | 676 // 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 | 677 // implements user gesture tracking, where all events that occur within 1 |
674 // second after a user interaction are considered to be triggered by user | 678 // second after a user interaction are considered to be triggered by user |
675 // activation (based on HTML spec: | 679 // activation (based on HTML spec: |
676 // https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-a ctivation), | 680 // 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 | 681 // 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 | 682 // explicitly filter these types of aborts out when deciding if the abort was |
679 // user initiated. | 683 // user initiated. |
680 abort_user_initiated_ = user_initiated && abort_type != ABORT_CLIENT_REDIRECT; | 684 if (abort_type != ABORT_CLIENT_REDIRECT) |
685 abort_user_initiated_info_ = user_initiated_info; | |
681 | 686 |
682 if (is_certainly_browser_timestamp) { | 687 if (is_certainly_browser_timestamp) { |
683 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 688 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); |
684 } | 689 } |
685 } | 690 } |
686 | 691 |
687 } // namespace page_load_metrics | 692 } // namespace page_load_metrics |
OLD | NEW |