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 |