Chromium Code Reviews| 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 (started_in_foreground_) { | |
|
Charlie Harrison
2017/02/17 22:36:49
I kinda think we should just set page_end_time_ =
Bryan McQuade
2017/02/18 00:30:15
Agree, done. I kept the error counter since I do w
| |
| 323 DCHECK(!page_end_time_.is_null()); | |
| 324 if (page_end_time_.is_null()) | |
| 325 RecordInternalError(ERR_NO_PAGE_LOAD_END_TIME); | |
| 326 } | |
| 327 | |
| 322 if (!did_commit_) { | 328 if (!did_commit_) { |
| 323 if (!failed_provisional_load_info_) | 329 if (!failed_provisional_load_info_) |
| 324 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); | 330 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); |
| 325 | 331 |
| 326 // Don't include any aborts that resulted in a new navigation, as the chain | 332 // Don't include any aborts that resulted in a new navigation, as the chain |
| 327 // length will be included in the aborter PageLoadTracker. | 333 // length will be included in the aborter PageLoadTracker. |
| 328 if (abort_type_ != ABORT_RELOAD && abort_type_ != ABORT_FORWARD_BACK && | 334 if (page_end_reason_ != END_RELOAD && |
| 329 abort_type_ != ABORT_NEW_NAVIGATION) { | 335 page_end_reason_ != END_FORWARD_BACK && |
| 336 page_end_reason_ != END_NEW_NAVIGATION) { | |
| 330 LogAbortChainHistograms(nullptr); | 337 LogAbortChainHistograms(nullptr); |
| 331 } | 338 } |
| 332 } else if (timing_.IsEmpty()) { | 339 } else if (timing_.IsEmpty()) { |
| 333 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 340 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
| 334 } | 341 } |
| 335 | 342 |
| 336 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 343 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 337 for (const auto& observer : observers_) { | 344 for (const auto& observer : observers_) { |
| 338 if (failed_provisional_load_info_) { | 345 if (failed_provisional_load_info_) { |
| 339 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); | 346 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 360 | 367 |
| 361 // The following is only executed for committing trackers. | 368 // The following is only executed for committing trackers. |
| 362 DCHECK(did_commit_); | 369 DCHECK(did_commit_); |
| 363 | 370 |
| 364 // Note that histograms could be separated out by this commit's transition | 371 // Note that histograms could be separated out by this commit's transition |
| 365 // type, but for simplicity they will all be bucketed together. | 372 // type, but for simplicity they will all be bucketed together. |
| 366 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_); | 373 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_); |
| 367 | 374 |
| 368 ui::PageTransition committed_transition = | 375 ui::PageTransition committed_transition = |
| 369 final_navigation->GetPageTransition(); | 376 final_navigation->GetPageTransition(); |
| 370 switch (AbortTypeForPageTransition(committed_transition)) { | 377 switch (EndReasonForPageTransition(committed_transition)) { |
| 371 case ABORT_RELOAD: | 378 case END_RELOAD: |
| 372 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeReload, | 379 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeReload, |
| 373 aborted_chain_size_); | 380 aborted_chain_size_); |
| 374 return; | 381 return; |
| 375 case ABORT_FORWARD_BACK: | 382 case END_FORWARD_BACK: |
| 376 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeForwardBack, | 383 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeForwardBack, |
| 377 aborted_chain_size_); | 384 aborted_chain_size_); |
| 378 return; | 385 return; |
| 379 // TODO(csharrison): Refactor this code so it is based on the WillStart* | 386 // 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 | 387 // 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, | 388 // 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 | 389 // merge client redirects with new navigations, which was (basically) the |
| 383 // previous behavior. | 390 // previous behavior. |
| 384 case ABORT_CLIENT_REDIRECT: | 391 case END_CLIENT_REDIRECT: |
| 385 case ABORT_NEW_NAVIGATION: | 392 case END_NEW_NAVIGATION: |
| 386 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeNewNavigation, | 393 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeNewNavigation, |
| 387 aborted_chain_size_); | 394 aborted_chain_size_); |
| 388 return; | 395 return; |
| 389 default: | 396 default: |
| 390 NOTREACHED() | 397 NOTREACHED() |
| 391 << "LogAbortChainHistograms received unexpected ui::PageTransition: " | 398 << "LogAbortChainHistograms received unexpected ui::PageTransition: " |
| 392 << committed_transition; | 399 << committed_transition; |
| 393 return; | 400 return; |
| 394 } | 401 } |
| 395 } | 402 } |
| 396 | 403 |
| 397 void PageLoadTracker::WebContentsHidden() { | 404 void PageLoadTracker::WebContentsHidden() { |
| 398 // Only log the first time we background in a given page load. | 405 // Only log the first time we background in a given page load. |
| 399 if (background_time_.is_null()) { | 406 if (background_time_.is_null()) { |
| 400 // Make sure we either started in the foreground and haven't been | 407 // Make sure we either started in the foreground and haven't been |
| 401 // foregrounded yet, or started in the background and have already been | 408 // foregrounded yet, or started in the background and have already been |
| 402 // foregrounded. | 409 // foregrounded. |
| 403 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | 410 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); |
| 404 background_time_ = base::TimeTicks::Now(); | 411 background_time_ = base::TimeTicks::Now(); |
| 405 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | 412 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 } | 413 } |
| 413 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 414 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 414 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); | 415 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); |
| 415 } | 416 } |
| 416 | 417 |
| 417 void PageLoadTracker::WebContentsShown() { | 418 void PageLoadTracker::WebContentsShown() { |
| 418 // Only log the first time we foreground in a given page load. | 419 // Only log the first time we foreground in a given page load. |
| 419 if (foreground_time_.is_null()) { | 420 if (foreground_time_.is_null()) { |
| 420 // Make sure we either started in the background and haven't been | 421 // Make sure we either started in the background and haven't been |
| 421 // backgrounded yet, or started in the foreground and have already been | 422 // backgrounded yet, or started in the foreground and have already been |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 447 url_ = navigation_handle->GetURL(); | 448 url_ = navigation_handle->GetURL(); |
| 448 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. | 449 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. |
| 449 page_transition_ = navigation_handle->GetPageTransition(); | 450 page_transition_ = navigation_handle->GetPageTransition(); |
| 450 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); | 451 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); |
| 451 | 452 |
| 452 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); | 453 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); |
| 453 LogAbortChainHistograms(navigation_handle); | 454 LogAbortChainHistograms(navigation_handle); |
| 454 } | 455 } |
| 455 | 456 |
| 456 void PageLoadTracker::FailedProvisionalLoad( | 457 void PageLoadTracker::FailedProvisionalLoad( |
| 457 content::NavigationHandle* navigation_handle) { | 458 content::NavigationHandle* navigation_handle, |
| 459 base::TimeTicks failed_load_time) { | |
| 458 DCHECK(!failed_provisional_load_info_); | 460 DCHECK(!failed_provisional_load_info_); |
| 459 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 461 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( |
| 460 base::TimeTicks::Now() - navigation_handle->NavigationStart(), | 462 failed_load_time - navigation_handle->NavigationStart(), |
| 461 navigation_handle->GetNetErrorCode())); | 463 navigation_handle->GetNetErrorCode())); |
| 462 } | 464 } |
| 463 | 465 |
| 464 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { | 466 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { |
| 465 url_ = navigation_handle->GetURL(); | 467 url_ = navigation_handle->GetURL(); |
| 466 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); | 468 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); |
| 467 } | 469 } |
| 468 | 470 |
| 469 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { | 471 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { |
| 470 input_tracker_.OnInputEvent(event); | 472 input_tracker_.OnInputEvent(event); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 | 579 |
| 578 if (!event_time->is_null() && *event_time < navigation_start_) { | 580 if (!event_time->is_null() && *event_time < navigation_start_) { |
| 579 RecordInternalError(ERR_INTER_PROCESS_TIME_TICK_SKEW); | 581 RecordInternalError(ERR_INTER_PROCESS_TIME_TICK_SKEW); |
| 580 *event_time = navigation_start_; | 582 *event_time = navigation_start_; |
| 581 } | 583 } |
| 582 } | 584 } |
| 583 | 585 |
| 584 PageLoadExtraInfo PageLoadTracker::ComputePageLoadExtraInfo() { | 586 PageLoadExtraInfo PageLoadTracker::ComputePageLoadExtraInfo() { |
| 585 base::Optional<base::TimeDelta> first_background_time; | 587 base::Optional<base::TimeDelta> first_background_time; |
| 586 base::Optional<base::TimeDelta> first_foreground_time; | 588 base::Optional<base::TimeDelta> first_foreground_time; |
| 587 base::Optional<base::TimeDelta> time_to_abort; | 589 base::Optional<base::TimeDelta> page_end_time; |
| 588 | 590 |
| 589 if (!background_time_.is_null()) { | 591 if (!background_time_.is_null()) { |
| 590 DCHECK_GE(background_time_, navigation_start_); | 592 DCHECK_GE(background_time_, navigation_start_); |
| 591 first_background_time = background_time_ - navigation_start_; | 593 first_background_time = background_time_ - navigation_start_; |
| 592 } | 594 } |
| 593 | 595 |
| 594 if (!foreground_time_.is_null()) { | 596 if (!foreground_time_.is_null()) { |
| 595 DCHECK_GE(foreground_time_, navigation_start_); | 597 DCHECK_GE(foreground_time_, navigation_start_); |
| 596 first_foreground_time = foreground_time_ - navigation_start_; | 598 first_foreground_time = foreground_time_ - navigation_start_; |
| 597 } | 599 } |
| 598 | 600 |
| 599 if (abort_type_ != ABORT_NONE) { | 601 if (page_end_reason_ != END_NONE) { |
| 600 DCHECK_GE(abort_time_, navigation_start_); | 602 DCHECK_GE(page_end_time_, navigation_start_); |
| 601 time_to_abort = abort_time_ - navigation_start_; | 603 page_end_time = page_end_time_ - navigation_start_; |
| 602 } else { | 604 } else { |
| 603 DCHECK(abort_time_.is_null()); | 605 DCHECK(page_end_time_.is_null()); |
| 604 } | 606 } |
| 605 | 607 |
| 606 // abort_type_ == ABORT_NONE implies abort_user_initiated_info_ is not user | 608 // page_end_reason_ == END_NONE implies page_end_user_initiated_info_ is not |
| 607 // initiated. | 609 // user initiated. |
| 608 DCHECK(abort_type_ != ABORT_NONE || | 610 DCHECK(page_end_reason_ != END_NONE || |
| 609 (!abort_user_initiated_info_.browser_initiated && | 611 (!page_end_user_initiated_info_.browser_initiated && |
| 610 !abort_user_initiated_info_.user_gesture && | 612 !page_end_user_initiated_info_.user_gesture && |
| 611 !abort_user_initiated_info_.user_input_event)); | 613 !page_end_user_initiated_info_.user_input_event)); |
| 612 return PageLoadExtraInfo( | 614 return PageLoadExtraInfo( |
| 613 first_background_time, first_foreground_time, started_in_foreground_, | 615 first_background_time, first_foreground_time, started_in_foreground_, |
| 614 user_initiated_info_, url(), start_url_, did_commit_, abort_type_, | 616 user_initiated_info_, url(), start_url_, did_commit_, page_end_reason_, |
| 615 abort_user_initiated_info_, time_to_abort, metadata_); | 617 page_end_user_initiated_info_, page_end_time, metadata_); |
| 616 } | 618 } |
| 617 | 619 |
| 618 bool PageLoadTracker::HasMatchingNavigationRequestID( | 620 bool PageLoadTracker::HasMatchingNavigationRequestID( |
| 619 const content::GlobalRequestID& request_id) const { | 621 const content::GlobalRequestID& request_id) const { |
| 620 DCHECK(request_id != content::GlobalRequestID()); | 622 DCHECK(request_id != content::GlobalRequestID()); |
| 621 return navigation_request_id_.has_value() && | 623 return navigation_request_id_.has_value() && |
| 622 navigation_request_id_.value() == request_id; | 624 navigation_request_id_.value() == request_id; |
| 623 } | 625 } |
| 624 | 626 |
| 625 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 627 void PageLoadTracker::NotifyPageEnd(PageEndReason page_end_reason, |
| 626 UserInitiatedInfo user_initiated_info, | 628 UserInitiatedInfo user_initiated_info, |
| 627 base::TimeTicks timestamp, | 629 base::TimeTicks timestamp, |
| 628 bool is_certainly_browser_timestamp) { | 630 bool is_certainly_browser_timestamp) { |
| 629 DCHECK_NE(abort_type, ABORT_NONE); | 631 DCHECK_NE(page_end_reason, END_NONE); |
| 630 // Use UpdateAbort to update an already notified PageLoadTracker. | 632 // Use UpdatePageEnd to update an already notified PageLoadTracker. |
| 631 if (abort_type_ != ABORT_NONE) | 633 if (page_end_reason_ != END_NONE) |
| 632 return; | 634 return; |
| 633 | 635 |
| 634 UpdateAbortInternal(abort_type, user_initiated_info, timestamp, | 636 UpdatePageEndInternal(page_end_reason, user_initiated_info, timestamp, |
| 635 is_certainly_browser_timestamp); | 637 is_certainly_browser_timestamp); |
| 636 } | 638 } |
| 637 | 639 |
| 638 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, | 640 void PageLoadTracker::UpdatePageEnd(PageEndReason page_end_reason, |
| 639 UserInitiatedInfo user_initiated_info, | 641 UserInitiatedInfo user_initiated_info, |
| 640 base::TimeTicks timestamp, | 642 base::TimeTicks timestamp, |
| 641 bool is_certainly_browser_timestamp) { | 643 bool is_certainly_browser_timestamp) { |
| 642 DCHECK_NE(abort_type, ABORT_NONE); | 644 DCHECK_NE(page_end_reason, END_NONE); |
| 643 DCHECK_NE(abort_type, ABORT_OTHER); | 645 DCHECK_NE(page_end_reason, END_OTHER); |
| 644 DCHECK_EQ(abort_type_, ABORT_OTHER); | 646 DCHECK_EQ(page_end_reason_, END_OTHER); |
| 647 DCHECK(!page_end_time_.is_null()); | |
| 648 if (page_end_time_.is_null() || page_end_reason_ != END_OTHER) | |
| 649 return; | |
| 645 | 650 |
| 646 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 651 // 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 | 652 // than the timestamp that aborted the load. Taking the minimum gives the |
| 648 // closest user initiated time known. | 653 // closest user initiated time known. |
| 649 UpdateAbortInternal(abort_type, user_initiated_info, | 654 UpdatePageEndInternal(page_end_reason, user_initiated_info, |
| 650 std::min(abort_time_, timestamp), | 655 std::min(page_end_time_, timestamp), |
| 651 is_certainly_browser_timestamp); | 656 is_certainly_browser_timestamp); |
| 652 } | 657 } |
| 653 | 658 |
| 654 bool PageLoadTracker::IsLikelyProvisionalAbort( | 659 bool PageLoadTracker::IsLikelyProvisionalAbort( |
| 655 base::TimeTicks abort_cause_time) const { | 660 base::TimeTicks abort_cause_time) const { |
| 656 // Note that |abort_cause_time - abort_time| can be negative. | 661 // Note that |abort_cause_time - page_end_time_| can be negative. |
| 657 return abort_type_ == ABORT_OTHER && | 662 return page_end_reason_ == END_OTHER && |
| 658 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 663 (abort_cause_time - page_end_time_).InMilliseconds() < 100; |
| 659 } | 664 } |
| 660 | 665 |
| 661 bool PageLoadTracker::MatchesOriginalNavigation( | 666 bool PageLoadTracker::MatchesOriginalNavigation( |
| 662 content::NavigationHandle* navigation_handle) { | 667 content::NavigationHandle* navigation_handle) { |
| 663 // Neither navigation should have committed. | 668 // Neither navigation should have committed. |
| 664 DCHECK(!navigation_handle->HasCommitted()); | 669 DCHECK(!navigation_handle->HasCommitted()); |
| 665 DCHECK(!did_commit_); | 670 DCHECK(!did_commit_); |
| 666 return navigation_handle->GetURL() == start_url_; | 671 return navigation_handle->GetURL() == start_url_; |
| 667 } | 672 } |
| 668 | 673 |
| 669 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 674 void PageLoadTracker::UpdatePageEndInternal( |
| 670 UserInitiatedInfo user_initiated_info, | 675 PageEndReason page_end_reason, |
| 671 base::TimeTicks timestamp, | 676 UserInitiatedInfo user_initiated_info, |
| 672 bool is_certainly_browser_timestamp) { | 677 base::TimeTicks timestamp, |
| 678 bool is_certainly_browser_timestamp) { | |
| 673 // When a provisional navigation commits, that navigation's start time is | 679 // When a provisional navigation commits, that navigation's start time is |
| 674 // interpreted as the abort time for other provisional loads in the tab. | 680 // 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 | 681 // However, this only makes sense if the committed load started after the |
| 676 // aborted provisional loads started. Thus we ignore cases where the committed | 682 // aborted provisional loads started. Thus we ignore cases where the committed |
| 677 // load started before the aborted provisional load, as this would result in | 683 // 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 | 684 // 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 | 685 // 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 | 686 // instead report the actual cause of an aborted navigation. See crbug/571647 |
| 681 // for details. | 687 // for details. |
| 682 if (timestamp < navigation_start_) { | 688 if (timestamp < navigation_start_) { |
| 683 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 689 RecordInternalError(ERR_END_BEFORE_NAVIGATION_START); |
| 684 abort_type_ = ABORT_NONE; | 690 page_end_reason_ = END_NONE; |
| 685 abort_time_ = base::TimeTicks(); | 691 page_end_time_ = base::TimeTicks(); |
| 686 return; | 692 return; |
| 687 } | 693 } |
| 688 abort_type_ = abort_type; | 694 page_end_reason_ = page_end_reason; |
| 689 abort_time_ = timestamp; | 695 page_end_time_ = timestamp; |
| 690 // A client redirect can never be user initiated. Due to the way Blink | 696 // 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 | 697 // implements user gesture tracking, where all events that occur within 1 |
| 692 // second after a user interaction are considered to be triggered by user | 698 // second after a user interaction are considered to be triggered by user |
| 693 // activation (based on HTML spec: | 699 // activation (based on HTML spec: |
| 694 // https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-a ctivation), | 700 // 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 | 701 // 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 | 702 // explicitly filter these types of aborts out when deciding if the abort was |
| 697 // user initiated. | 703 // user initiated. |
| 698 if (abort_type != ABORT_CLIENT_REDIRECT) | 704 if (page_end_reason != END_CLIENT_REDIRECT) |
| 699 abort_user_initiated_info_ = user_initiated_info; | 705 page_end_user_initiated_info_ = user_initiated_info; |
| 700 | 706 |
| 701 if (is_certainly_browser_timestamp) { | 707 if (is_certainly_browser_timestamp) { |
| 702 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 708 ClampBrowserTimestampIfInterProcessTimeTickSkew(&page_end_time_); |
| 703 } | 709 } |
| 704 } | 710 } |
| 705 | 711 |
| 706 } // namespace page_load_metrics | 712 } // namespace page_load_metrics |
| OLD | NEW |