| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 "PageLoad.Internal.PageLoadCompleted.AfterAppBackground"; | 57 "PageLoad.Internal.PageLoadCompleted.AfterAppBackground"; |
| 58 | 58 |
| 59 } // namespace internal | 59 } // namespace internal |
| 60 | 60 |
| 61 void RecordInternalError(InternalErrorLoadEvent event) { | 61 void RecordInternalError(InternalErrorLoadEvent event) { |
| 62 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY); | 62 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY); |
| 63 } | 63 } |
| 64 | 64 |
| 65 // TODO(csharrison): Add a case for client side redirects, which is what JS | 65 // TODO(csharrison): Add a case for client side redirects, which is what JS |
| 66 // initiated window.location / window.history navigations get set to. | 66 // initiated window.location / window.history navigations get set to. |
| 67 UserAbortType AbortTypeForPageTransition(ui::PageTransition transition) { | 67 PageEndReason EndReasonForPageTransition(ui::PageTransition transition) { |
| 68 if (transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) { | 68 if (transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) { |
| 69 return ABORT_CLIENT_REDIRECT; | 69 return END_CLIENT_REDIRECT; |
| 70 } | 70 } |
| 71 if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD)) | 71 if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD)) |
| 72 return ABORT_RELOAD; | 72 return END_RELOAD; |
| 73 if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) | 73 if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) |
| 74 return ABORT_FORWARD_BACK; | 74 return END_FORWARD_BACK; |
| 75 if (ui::PageTransitionIsNewNavigation(transition)) | 75 if (ui::PageTransitionIsNewNavigation(transition)) |
| 76 return ABORT_NEW_NAVIGATION; | 76 return END_NEW_NAVIGATION; |
| 77 NOTREACHED() | 77 NOTREACHED() |
| 78 << "AbortTypeForPageTransition received unexpected ui::PageTransition: " | 78 << "EndReasonForPageTransition received unexpected ui::PageTransition: " |
| 79 << transition; | 79 << transition; |
| 80 return ABORT_OTHER; | 80 return END_OTHER; |
| 81 } | 81 } |
| 82 | 82 |
| 83 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url) { | 83 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url) { |
| 84 if (aborted_chain_size_same_url > 0) { | 84 if (aborted_chain_size_same_url > 0) { |
| 85 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeSameURL, | 85 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeSameURL, |
| 86 aborted_chain_size_same_url); | 86 aborted_chain_size_same_url); |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 bool IsNavigationUserInitiated(content::NavigationHandle* handle) { | 90 bool IsNavigationUserInitiated(content::NavigationHandle* handle) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 content::NavigationHandle* navigation_handle, | 290 content::NavigationHandle* navigation_handle, |
| 291 UserInitiatedInfo user_initiated_info, | 291 UserInitiatedInfo user_initiated_info, |
| 292 int aborted_chain_size, | 292 int aborted_chain_size, |
| 293 int aborted_chain_size_same_url) | 293 int aborted_chain_size_same_url) |
| 294 : did_stop_tracking_(false), | 294 : did_stop_tracking_(false), |
| 295 app_entered_background_(false), | 295 app_entered_background_(false), |
| 296 navigation_start_(navigation_handle->NavigationStart()), | 296 navigation_start_(navigation_handle->NavigationStart()), |
| 297 url_(navigation_handle->GetURL()), | 297 url_(navigation_handle->GetURL()), |
| 298 start_url_(navigation_handle->GetURL()), | 298 start_url_(navigation_handle->GetURL()), |
| 299 did_commit_(false), | 299 did_commit_(false), |
| 300 abort_type_(ABORT_NONE), | 300 page_end_reason_(END_NONE), |
| 301 abort_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), | 301 page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), |
| 302 started_in_foreground_(in_foreground), | 302 started_in_foreground_(in_foreground), |
| 303 page_transition_(navigation_handle->GetPageTransition()), | 303 page_transition_(navigation_handle->GetPageTransition()), |
| 304 user_initiated_info_(user_initiated_info), | 304 user_initiated_info_(user_initiated_info), |
| 305 aborted_chain_size_(aborted_chain_size), | 305 aborted_chain_size_(aborted_chain_size), |
| 306 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 306 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
| 307 embedder_interface_(embedder_interface) { | 307 embedder_interface_(embedder_interface) { |
| 308 DCHECK(!navigation_handle->HasCommitted()); | 308 DCHECK(!navigation_handle->HasCommitted()); |
| 309 embedder_interface_->RegisterObservers(this); | 309 embedder_interface_->RegisterObservers(this); |
| 310 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, | 310 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, |
| 311 currently_committed_url, started_in_foreground_); | 311 currently_committed_url, started_in_foreground_); |
| 312 } | 312 } |
| 313 | 313 |
| 314 PageLoadTracker::~PageLoadTracker() { | 314 PageLoadTracker::~PageLoadTracker() { |
| 315 if (app_entered_background_) { | 315 if (app_entered_background_) { |
| 316 RecordAppBackgroundPageLoadCompleted(true); | 316 RecordAppBackgroundPageLoadCompleted(true); |
| 317 } | 317 } |
| 318 | 318 |
| 319 if (did_stop_tracking_) | 319 if (did_stop_tracking_) |
| 320 return; | 320 return; |
| 321 | 321 |
| 322 if (page_end_time_.is_null()) { |
| 323 RecordInternalError(ERR_NO_PAGE_LOAD_END_TIME); |
| 324 page_end_time_ = base::TimeTicks::Now(); |
| 325 } |
| 326 |
| 322 if (!did_commit_) { | 327 if (!did_commit_) { |
| 323 if (!failed_provisional_load_info_) | 328 if (!failed_provisional_load_info_) |
| 324 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); | 329 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); |
| 325 | 330 |
| 326 // Don't include any aborts that resulted in a new navigation, as the chain | 331 // Don't include any aborts that resulted in a new navigation, as the chain |
| 327 // length will be included in the aborter PageLoadTracker. | 332 // length will be included in the aborter PageLoadTracker. |
| 328 if (abort_type_ != ABORT_RELOAD && abort_type_ != ABORT_FORWARD_BACK && | 333 if (page_end_reason_ != END_RELOAD && |
| 329 abort_type_ != ABORT_NEW_NAVIGATION) { | 334 page_end_reason_ != END_FORWARD_BACK && |
| 335 page_end_reason_ != END_NEW_NAVIGATION) { |
| 330 LogAbortChainHistograms(nullptr); | 336 LogAbortChainHistograms(nullptr); |
| 331 } | 337 } |
| 332 } else if (timing_.IsEmpty()) { | 338 } else if (timing_.IsEmpty()) { |
| 333 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 339 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
| 334 } | 340 } |
| 335 | 341 |
| 336 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 342 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 337 for (const auto& observer : observers_) { | 343 for (const auto& observer : observers_) { |
| 338 if (failed_provisional_load_info_) { | 344 if (failed_provisional_load_info_) { |
| 339 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); | 345 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 360 | 366 |
| 361 // The following is only executed for committing trackers. | 367 // The following is only executed for committing trackers. |
| 362 DCHECK(did_commit_); | 368 DCHECK(did_commit_); |
| 363 | 369 |
| 364 // Note that histograms could be separated out by this commit's transition | 370 // Note that histograms could be separated out by this commit's transition |
| 365 // type, but for simplicity they will all be bucketed together. | 371 // type, but for simplicity they will all be bucketed together. |
| 366 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_); | 372 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_); |
| 367 | 373 |
| 368 ui::PageTransition committed_transition = | 374 ui::PageTransition committed_transition = |
| 369 final_navigation->GetPageTransition(); | 375 final_navigation->GetPageTransition(); |
| 370 switch (AbortTypeForPageTransition(committed_transition)) { | 376 switch (EndReasonForPageTransition(committed_transition)) { |
| 371 case ABORT_RELOAD: | 377 case END_RELOAD: |
| 372 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeReload, | 378 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeReload, |
| 373 aborted_chain_size_); | 379 aborted_chain_size_); |
| 374 return; | 380 return; |
| 375 case ABORT_FORWARD_BACK: | 381 case END_FORWARD_BACK: |
| 376 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeForwardBack, | 382 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeForwardBack, |
| 377 aborted_chain_size_); | 383 aborted_chain_size_); |
| 378 return; | 384 return; |
| 379 // TODO(csharrison): Refactor this code so it is based on the WillStart* | 385 // TODO(csharrison): Refactor this code so it is based on the WillStart* |
| 380 // code path instead of the committed load code path. Then, for every abort | 386 // code path instead of the committed load code path. Then, for every abort |
| 381 // chain, log a histogram of the counts of each of these metrics. For now, | 387 // chain, log a histogram of the counts of each of these metrics. For now, |
| 382 // merge client redirects with new navigations, which was (basically) the | 388 // merge client redirects with new navigations, which was (basically) the |
| 383 // previous behavior. | 389 // previous behavior. |
| 384 case ABORT_CLIENT_REDIRECT: | 390 case END_CLIENT_REDIRECT: |
| 385 case ABORT_NEW_NAVIGATION: | 391 case END_NEW_NAVIGATION: |
| 386 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeNewNavigation, | 392 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeNewNavigation, |
| 387 aborted_chain_size_); | 393 aborted_chain_size_); |
| 388 return; | 394 return; |
| 389 default: | 395 default: |
| 390 NOTREACHED() | 396 NOTREACHED() |
| 391 << "LogAbortChainHistograms received unexpected ui::PageTransition: " | 397 << "LogAbortChainHistograms received unexpected ui::PageTransition: " |
| 392 << committed_transition; | 398 << committed_transition; |
| 393 return; | 399 return; |
| 394 } | 400 } |
| 395 } | 401 } |
| 396 | 402 |
| 397 void PageLoadTracker::WebContentsHidden() { | 403 void PageLoadTracker::WebContentsHidden() { |
| 398 // Only log the first time we background in a given page load. | 404 // Only log the first time we background in a given page load. |
| 399 if (background_time_.is_null()) { | 405 if (background_time_.is_null()) { |
| 400 // Make sure we either started in the foreground and haven't been | 406 // Make sure we either started in the foreground and haven't been |
| 401 // foregrounded yet, or started in the background and have already been | 407 // foregrounded yet, or started in the background and have already been |
| 402 // foregrounded. | 408 // foregrounded. |
| 403 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | 409 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); |
| 404 background_time_ = base::TimeTicks::Now(); | 410 background_time_ = base::TimeTicks::Now(); |
| 405 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | 411 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); |
| 406 // Though most cases where a tab is backgrounded are user initiated, we | |
| 407 // can't be certain that we were backgrounded due to a user action. For | |
| 408 // example, on Android, the screen times out after a period of inactivity, | |
| 409 // resulting in a non-user-initiated backgrounding. | |
| 410 NotifyAbort(ABORT_BACKGROUND, UserInitiatedInfo::NotUserInitiated(), | |
| 411 background_time_, true); | |
| 412 } | 412 } |
| 413 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 413 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 414 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); | 414 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); |
| 415 } | 415 } |
| 416 | 416 |
| 417 void PageLoadTracker::WebContentsShown() { | 417 void PageLoadTracker::WebContentsShown() { |
| 418 // Only log the first time we foreground in a given page load. | 418 // Only log the first time we foreground in a given page load. |
| 419 if (foreground_time_.is_null()) { | 419 if (foreground_time_.is_null()) { |
| 420 // Make sure we either started in the background and haven't been | 420 // Make sure we either started in the background and haven't been |
| 421 // backgrounded yet, or started in the foreground and have already been | 421 // backgrounded yet, or started in the foreground and have already been |
| (...skipping 25 matching lines...) Expand all Loading... |
| 447 url_ = navigation_handle->GetURL(); | 447 url_ = navigation_handle->GetURL(); |
| 448 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. | 448 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. |
| 449 page_transition_ = navigation_handle->GetPageTransition(); | 449 page_transition_ = navigation_handle->GetPageTransition(); |
| 450 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); | 450 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); |
| 451 | 451 |
| 452 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); | 452 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); |
| 453 LogAbortChainHistograms(navigation_handle); | 453 LogAbortChainHistograms(navigation_handle); |
| 454 } | 454 } |
| 455 | 455 |
| 456 void PageLoadTracker::FailedProvisionalLoad( | 456 void PageLoadTracker::FailedProvisionalLoad( |
| 457 content::NavigationHandle* navigation_handle) { | 457 content::NavigationHandle* navigation_handle, |
| 458 base::TimeTicks failed_load_time) { |
| 458 DCHECK(!failed_provisional_load_info_); | 459 DCHECK(!failed_provisional_load_info_); |
| 459 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 460 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( |
| 460 base::TimeTicks::Now() - navigation_handle->NavigationStart(), | 461 failed_load_time - navigation_handle->NavigationStart(), |
| 461 navigation_handle->GetNetErrorCode())); | 462 navigation_handle->GetNetErrorCode())); |
| 462 } | 463 } |
| 463 | 464 |
| 464 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { | 465 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { |
| 465 url_ = navigation_handle->GetURL(); | 466 url_ = navigation_handle->GetURL(); |
| 466 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); | 467 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); |
| 467 } | 468 } |
| 468 | 469 |
| 469 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { | 470 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { |
| 470 input_tracker_.OnInputEvent(event); | 471 input_tracker_.OnInputEvent(event); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 | 578 |
| 578 if (!event_time->is_null() && *event_time < navigation_start_) { | 579 if (!event_time->is_null() && *event_time < navigation_start_) { |
| 579 RecordInternalError(ERR_INTER_PROCESS_TIME_TICK_SKEW); | 580 RecordInternalError(ERR_INTER_PROCESS_TIME_TICK_SKEW); |
| 580 *event_time = navigation_start_; | 581 *event_time = navigation_start_; |
| 581 } | 582 } |
| 582 } | 583 } |
| 583 | 584 |
| 584 PageLoadExtraInfo PageLoadTracker::ComputePageLoadExtraInfo() { | 585 PageLoadExtraInfo PageLoadTracker::ComputePageLoadExtraInfo() { |
| 585 base::Optional<base::TimeDelta> first_background_time; | 586 base::Optional<base::TimeDelta> first_background_time; |
| 586 base::Optional<base::TimeDelta> first_foreground_time; | 587 base::Optional<base::TimeDelta> first_foreground_time; |
| 587 base::Optional<base::TimeDelta> time_to_abort; | 588 base::Optional<base::TimeDelta> page_end_time; |
| 588 | 589 |
| 589 if (!background_time_.is_null()) { | 590 if (!background_time_.is_null()) { |
| 590 DCHECK_GE(background_time_, navigation_start_); | 591 DCHECK_GE(background_time_, navigation_start_); |
| 591 first_background_time = background_time_ - navigation_start_; | 592 first_background_time = background_time_ - navigation_start_; |
| 592 } | 593 } |
| 593 | 594 |
| 594 if (!foreground_time_.is_null()) { | 595 if (!foreground_time_.is_null()) { |
| 595 DCHECK_GE(foreground_time_, navigation_start_); | 596 DCHECK_GE(foreground_time_, navigation_start_); |
| 596 first_foreground_time = foreground_time_ - navigation_start_; | 597 first_foreground_time = foreground_time_ - navigation_start_; |
| 597 } | 598 } |
| 598 | 599 |
| 599 if (abort_type_ != ABORT_NONE) { | 600 if (page_end_reason_ != END_NONE) { |
| 600 DCHECK_GE(abort_time_, navigation_start_); | 601 DCHECK_GE(page_end_time_, navigation_start_); |
| 601 time_to_abort = abort_time_ - navigation_start_; | 602 page_end_time = page_end_time_ - navigation_start_; |
| 602 } else { | 603 } else { |
| 603 DCHECK(abort_time_.is_null()); | 604 DCHECK(page_end_time_.is_null()); |
| 604 } | 605 } |
| 605 | 606 |
| 606 // abort_type_ == ABORT_NONE implies abort_user_initiated_info_ is not user | 607 // page_end_reason_ == END_NONE implies page_end_user_initiated_info_ is not |
| 607 // initiated. | 608 // user initiated. |
| 608 DCHECK(abort_type_ != ABORT_NONE || | 609 DCHECK(page_end_reason_ != END_NONE || |
| 609 (!abort_user_initiated_info_.browser_initiated && | 610 (!page_end_user_initiated_info_.browser_initiated && |
| 610 !abort_user_initiated_info_.user_gesture && | 611 !page_end_user_initiated_info_.user_gesture && |
| 611 !abort_user_initiated_info_.user_input_event)); | 612 !page_end_user_initiated_info_.user_input_event)); |
| 612 return PageLoadExtraInfo( | 613 return PageLoadExtraInfo( |
| 613 first_background_time, first_foreground_time, started_in_foreground_, | 614 first_background_time, first_foreground_time, started_in_foreground_, |
| 614 user_initiated_info_, url(), start_url_, did_commit_, abort_type_, | 615 user_initiated_info_, url(), start_url_, did_commit_, page_end_reason_, |
| 615 abort_user_initiated_info_, time_to_abort, metadata_); | 616 page_end_user_initiated_info_, page_end_time, metadata_); |
| 616 } | 617 } |
| 617 | 618 |
| 618 bool PageLoadTracker::HasMatchingNavigationRequestID( | 619 bool PageLoadTracker::HasMatchingNavigationRequestID( |
| 619 const content::GlobalRequestID& request_id) const { | 620 const content::GlobalRequestID& request_id) const { |
| 620 DCHECK(request_id != content::GlobalRequestID()); | 621 DCHECK(request_id != content::GlobalRequestID()); |
| 621 return navigation_request_id_.has_value() && | 622 return navigation_request_id_.has_value() && |
| 622 navigation_request_id_.value() == request_id; | 623 navigation_request_id_.value() == request_id; |
| 623 } | 624 } |
| 624 | 625 |
| 625 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 626 void PageLoadTracker::NotifyPageEnd(PageEndReason page_end_reason, |
| 626 UserInitiatedInfo user_initiated_info, | 627 UserInitiatedInfo user_initiated_info, |
| 627 base::TimeTicks timestamp, | 628 base::TimeTicks timestamp, |
| 628 bool is_certainly_browser_timestamp) { | 629 bool is_certainly_browser_timestamp) { |
| 629 DCHECK_NE(abort_type, ABORT_NONE); | 630 DCHECK_NE(page_end_reason, END_NONE); |
| 630 // Use UpdateAbort to update an already notified PageLoadTracker. | 631 // Use UpdatePageEnd to update an already notified PageLoadTracker. |
| 631 if (abort_type_ != ABORT_NONE) | 632 if (page_end_reason_ != END_NONE) |
| 632 return; | 633 return; |
| 633 | 634 |
| 634 UpdateAbortInternal(abort_type, user_initiated_info, timestamp, | 635 UpdatePageEndInternal(page_end_reason, user_initiated_info, timestamp, |
| 635 is_certainly_browser_timestamp); | 636 is_certainly_browser_timestamp); |
| 636 } | 637 } |
| 637 | 638 |
| 638 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, | 639 void PageLoadTracker::UpdatePageEnd(PageEndReason page_end_reason, |
| 639 UserInitiatedInfo user_initiated_info, | 640 UserInitiatedInfo user_initiated_info, |
| 640 base::TimeTicks timestamp, | 641 base::TimeTicks timestamp, |
| 641 bool is_certainly_browser_timestamp) { | 642 bool is_certainly_browser_timestamp) { |
| 642 DCHECK_NE(abort_type, ABORT_NONE); | 643 DCHECK_NE(page_end_reason, END_NONE); |
| 643 DCHECK_NE(abort_type, ABORT_OTHER); | 644 DCHECK_NE(page_end_reason, END_OTHER); |
| 644 DCHECK_EQ(abort_type_, ABORT_OTHER); | 645 DCHECK_EQ(page_end_reason_, END_OTHER); |
| 646 DCHECK(!page_end_time_.is_null()); |
| 647 if (page_end_time_.is_null() || page_end_reason_ != END_OTHER) |
| 648 return; |
| 645 | 649 |
| 646 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 650 // For some aborts (e.g. navigations), the initiated timestamp can be earlier |
| 647 // than the timestamp that aborted the load. Taking the minimum gives the | 651 // than the timestamp that aborted the load. Taking the minimum gives the |
| 648 // closest user initiated time known. | 652 // closest user initiated time known. |
| 649 UpdateAbortInternal(abort_type, user_initiated_info, | 653 UpdatePageEndInternal(page_end_reason, user_initiated_info, |
| 650 std::min(abort_time_, timestamp), | 654 std::min(page_end_time_, timestamp), |
| 651 is_certainly_browser_timestamp); | 655 is_certainly_browser_timestamp); |
| 652 } | 656 } |
| 653 | 657 |
| 654 bool PageLoadTracker::IsLikelyProvisionalAbort( | 658 bool PageLoadTracker::IsLikelyProvisionalAbort( |
| 655 base::TimeTicks abort_cause_time) const { | 659 base::TimeTicks abort_cause_time) const { |
| 656 // Note that |abort_cause_time - abort_time| can be negative. | 660 // Note that |abort_cause_time - page_end_time_| can be negative. |
| 657 return abort_type_ == ABORT_OTHER && | 661 return page_end_reason_ == END_OTHER && |
| 658 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 662 (abort_cause_time - page_end_time_).InMilliseconds() < 100; |
| 659 } | 663 } |
| 660 | 664 |
| 661 bool PageLoadTracker::MatchesOriginalNavigation( | 665 bool PageLoadTracker::MatchesOriginalNavigation( |
| 662 content::NavigationHandle* navigation_handle) { | 666 content::NavigationHandle* navigation_handle) { |
| 663 // Neither navigation should have committed. | 667 // Neither navigation should have committed. |
| 664 DCHECK(!navigation_handle->HasCommitted()); | 668 DCHECK(!navigation_handle->HasCommitted()); |
| 665 DCHECK(!did_commit_); | 669 DCHECK(!did_commit_); |
| 666 return navigation_handle->GetURL() == start_url_; | 670 return navigation_handle->GetURL() == start_url_; |
| 667 } | 671 } |
| 668 | 672 |
| 669 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 673 void PageLoadTracker::UpdatePageEndInternal( |
| 670 UserInitiatedInfo user_initiated_info, | 674 PageEndReason page_end_reason, |
| 671 base::TimeTicks timestamp, | 675 UserInitiatedInfo user_initiated_info, |
| 672 bool is_certainly_browser_timestamp) { | 676 base::TimeTicks timestamp, |
| 677 bool is_certainly_browser_timestamp) { |
| 673 // When a provisional navigation commits, that navigation's start time is | 678 // When a provisional navigation commits, that navigation's start time is |
| 674 // interpreted as the abort time for other provisional loads in the tab. | 679 // interpreted as the abort time for other provisional loads in the tab. |
| 675 // However, this only makes sense if the committed load started after the | 680 // However, this only makes sense if the committed load started after the |
| 676 // aborted provisional loads started. Thus we ignore cases where the committed | 681 // aborted provisional loads started. Thus we ignore cases where the committed |
| 677 // load started before the aborted provisional load, as this would result in | 682 // load started before the aborted provisional load, as this would result in |
| 678 // recording a negative time-to-abort. The real issue here is that we have to | 683 // recording a negative time-to-abort. The real issue here is that we have to |
| 679 // infer the cause of aborts. It would be better if the navigation code could | 684 // infer the cause of aborts. It would be better if the navigation code could |
| 680 // instead report the actual cause of an aborted navigation. See crbug/571647 | 685 // instead report the actual cause of an aborted navigation. See crbug/571647 |
| 681 // for details. | 686 // for details. |
| 682 if (timestamp < navigation_start_) { | 687 if (timestamp < navigation_start_) { |
| 683 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 688 RecordInternalError(ERR_END_BEFORE_NAVIGATION_START); |
| 684 abort_type_ = ABORT_NONE; | 689 page_end_reason_ = END_NONE; |
| 685 abort_time_ = base::TimeTicks(); | 690 page_end_time_ = base::TimeTicks(); |
| 686 return; | 691 return; |
| 687 } | 692 } |
| 688 abort_type_ = abort_type; | 693 page_end_reason_ = page_end_reason; |
| 689 abort_time_ = timestamp; | 694 page_end_time_ = timestamp; |
| 690 // A client redirect can never be user initiated. Due to the way Blink | 695 // A client redirect can never be user initiated. Due to the way Blink |
| 691 // implements user gesture tracking, where all events that occur within 1 | 696 // implements user gesture tracking, where all events that occur within 1 |
| 692 // second after a user interaction are considered to be triggered by user | 697 // second after a user interaction are considered to be triggered by user |
| 693 // activation (based on HTML spec: | 698 // activation (based on HTML spec: |
| 694 // https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-a
ctivation), | 699 // https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-a
ctivation), |
| 695 // these navs may sometimes be reported as user initiated by Blink. Thus, we | 700 // these navs may sometimes be reported as user initiated by Blink. Thus, we |
| 696 // explicitly filter these types of aborts out when deciding if the abort was | 701 // explicitly filter these types of aborts out when deciding if the abort was |
| 697 // user initiated. | 702 // user initiated. |
| 698 if (abort_type != ABORT_CLIENT_REDIRECT) | 703 if (page_end_reason != END_CLIENT_REDIRECT) |
| 699 abort_user_initiated_info_ = user_initiated_info; | 704 page_end_user_initiated_info_ = user_initiated_info; |
| 700 | 705 |
| 701 if (is_certainly_browser_timestamp) { | 706 if (is_certainly_browser_timestamp) { |
| 702 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 707 ClampBrowserTimestampIfInterProcessTimeTickSkew(&page_end_time_); |
| 703 } | 708 } |
| 704 } | 709 } |
| 705 | 710 |
| 706 } // namespace page_load_metrics | 711 } // namespace page_load_metrics |
| OLD | NEW |