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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 bool in_foreground, | 287 bool in_foreground, |
| 288 PageLoadMetricsEmbedderInterface* embedder_interface, | 288 PageLoadMetricsEmbedderInterface* embedder_interface, |
| 289 const GURL& currently_committed_url, | 289 const GURL& currently_committed_url, |
| 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 start_url_(navigation_handle->GetURL()), | 297 url_(navigation_handle->GetURL()), |
|
jkarlin
2017/02/15 19:55:36
Can we set start_url_ here as well? It imposes log
Bryan McQuade
2017/02/15 20:27:10
Done
| |
| 298 did_commit_(false), | |
| 298 abort_type_(ABORT_NONE), | 299 abort_type_(ABORT_NONE), |
| 299 abort_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), | 300 abort_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), |
| 300 started_in_foreground_(in_foreground), | 301 started_in_foreground_(in_foreground), |
| 301 page_transition_(navigation_handle->GetPageTransition()), | 302 page_transition_(navigation_handle->GetPageTransition()), |
| 302 user_initiated_info_(user_initiated_info), | 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 embedder_interface_->RegisterObservers(this); | 308 embedder_interface_->RegisterObservers(this); |
| 308 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, | 309 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, |
| 309 currently_committed_url, started_in_foreground_); | 310 currently_committed_url, started_in_foreground_); |
| 310 } | 311 } |
| 311 | 312 |
| 312 PageLoadTracker::~PageLoadTracker() { | 313 PageLoadTracker::~PageLoadTracker() { |
| 313 if (app_entered_background_) { | 314 if (app_entered_background_) { |
| 314 RecordAppBackgroundPageLoadCompleted(true); | 315 RecordAppBackgroundPageLoadCompleted(true); |
| 315 } | 316 } |
| 316 | 317 |
| 317 if (did_stop_tracking_) | 318 if (did_stop_tracking_) |
| 318 return; | 319 return; |
| 319 | 320 |
| 320 if (committed_url_.is_empty()) { | 321 if (!did_commit_) { |
| 321 if (!failed_provisional_load_info_) | 322 if (!failed_provisional_load_info_) |
| 322 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); | 323 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); |
| 323 | 324 |
| 324 // Don't include any aborts that resulted in a new navigation, as the chain | 325 // Don't include any aborts that resulted in a new navigation, as the chain |
| 325 // length will be included in the aborter PageLoadTracker. | 326 // length will be included in the aborter PageLoadTracker. |
| 326 if (abort_type_ != ABORT_RELOAD && abort_type_ != ABORT_FORWARD_BACK && | 327 if (abort_type_ != ABORT_RELOAD && abort_type_ != ABORT_FORWARD_BACK && |
| 327 abort_type_ != ABORT_NEW_NAVIGATION) { | 328 abort_type_ != ABORT_NEW_NAVIGATION) { |
| 328 LogAbortChainHistograms(nullptr); | 329 LogAbortChainHistograms(nullptr); |
| 329 } | 330 } |
| 330 } else if (timing_.IsEmpty()) { | 331 } else if (timing_.IsEmpty()) { |
| 331 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 332 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
| 332 } | 333 } |
| 333 | 334 |
| 334 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 335 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 335 for (const auto& observer : observers_) { | 336 for (const auto& observer : observers_) { |
| 336 if (failed_provisional_load_info_) { | 337 if (failed_provisional_load_info_) { |
| 337 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); | 338 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); |
| 338 } else if (!info.committed_url.is_empty()) { | 339 } else if (did_commit_) { |
| 339 observer->OnComplete(timing_, info); | 340 observer->OnComplete(timing_, info); |
| 340 } | 341 } |
| 341 } | 342 } |
| 342 } | 343 } |
| 343 | 344 |
| 344 void PageLoadTracker::LogAbortChainHistograms( | 345 void PageLoadTracker::LogAbortChainHistograms( |
| 345 content::NavigationHandle* final_navigation) { | 346 content::NavigationHandle* final_navigation) { |
| 346 if (aborted_chain_size_ == 0) | 347 if (aborted_chain_size_ == 0) |
| 347 return; | 348 return; |
| 348 // Note that this could be broken out by this navigation's abort type, if more | 349 // Note that this could be broken out by this navigation's abort type, if more |
| 349 // granularity is needed. Add one to the chain size to count the current | 350 // granularity is needed. Add one to the chain size to count the current |
| 350 // navigation. In the other cases, the current navigation is the final | 351 // navigation. In the other cases, the current navigation is the final |
| 351 // navigation (which commits). | 352 // navigation (which commits). |
| 352 if (!final_navigation) { | 353 if (!final_navigation) { |
| 353 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeNoCommit, | 354 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeNoCommit, |
| 354 aborted_chain_size_ + 1); | 355 aborted_chain_size_ + 1); |
| 355 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_ + 1); | 356 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_ + 1); |
| 356 return; | 357 return; |
| 357 } | 358 } |
| 358 | 359 |
| 359 // The following is only executed for committing trackers. | 360 // The following is only executed for committing trackers. |
| 360 DCHECK(!committed_url_.is_empty()); | 361 DCHECK(did_commit_); |
| 361 | 362 |
| 362 // Note that histograms could be separated out by this commit's transition | 363 // Note that histograms could be separated out by this commit's transition |
| 363 // type, but for simplicity they will all be bucketed together. | 364 // type, but for simplicity they will all be bucketed together. |
| 364 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_); | 365 LogAbortChainSameURLHistogram(aborted_chain_size_same_url_); |
| 365 | 366 |
| 366 ui::PageTransition committed_transition = | 367 ui::PageTransition committed_transition = |
| 367 final_navigation->GetPageTransition(); | 368 final_navigation->GetPageTransition(); |
| 368 switch (AbortTypeForPageTransition(committed_transition)) { | 369 switch (AbortTypeForPageTransition(committed_transition)) { |
| 369 case ABORT_RELOAD: | 370 case ABORT_RELOAD: |
| 370 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeReload, | 371 UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeReload, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 // crbug.com/680841 for details. | 434 // crbug.com/680841 for details. |
| 434 if (content::IsBrowserSideNavigationEnabled() && | 435 if (content::IsBrowserSideNavigationEnabled() && |
| 435 navigation_handle->GetGlobalRequestID() == content::GlobalRequestID()) | 436 navigation_handle->GetGlobalRequestID() == content::GlobalRequestID()) |
| 436 return; | 437 return; |
| 437 | 438 |
| 438 DCHECK(!navigation_request_id_.has_value()); | 439 DCHECK(!navigation_request_id_.has_value()); |
| 439 navigation_request_id_ = navigation_handle->GetGlobalRequestID(); | 440 navigation_request_id_ = navigation_handle->GetGlobalRequestID(); |
| 440 DCHECK(navigation_request_id_.value() != content::GlobalRequestID()); | 441 DCHECK(navigation_request_id_.value() != content::GlobalRequestID()); |
| 441 } | 442 } |
| 442 | 443 |
| 444 void PageLoadTracker::MaybeUpdateURL( | |
| 445 content::NavigationHandle* navigation_handle) { | |
| 446 if (navigation_handle->GetURL() == url_) | |
| 447 return; | |
| 448 if (start_url_.is_empty()) | |
| 449 start_url_ = url_; | |
|
jkarlin
2017/02/15 19:55:36
This can be removed with above change.
Bryan McQuade
2017/02/15 20:27:10
Done
| |
| 450 url_ = navigation_handle->GetURL(); | |
| 451 } | |
| 452 | |
| 443 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 453 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { |
| 444 committed_url_ = navigation_handle->GetURL(); | 454 did_commit_ = true; |
| 455 MaybeUpdateURL(navigation_handle); | |
| 445 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. | 456 // Some transitions (like CLIENT_REDIRECT) are only known at commit time. |
| 446 page_transition_ = navigation_handle->GetPageTransition(); | 457 page_transition_ = navigation_handle->GetPageTransition(); |
| 447 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); | 458 user_initiated_info_.user_gesture = navigation_handle->HasUserGesture(); |
| 448 | 459 |
| 449 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); | 460 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnCommit, navigation_handle); |
| 450 LogAbortChainHistograms(navigation_handle); | 461 LogAbortChainHistograms(navigation_handle); |
| 451 } | 462 } |
| 452 | 463 |
| 453 void PageLoadTracker::FailedProvisionalLoad( | 464 void PageLoadTracker::FailedProvisionalLoad( |
| 454 content::NavigationHandle* navigation_handle) { | 465 content::NavigationHandle* navigation_handle) { |
| 455 DCHECK(!failed_provisional_load_info_); | 466 DCHECK(!failed_provisional_load_info_); |
| 456 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( | 467 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( |
| 457 base::TimeTicks::Now() - navigation_handle->NavigationStart(), | 468 base::TimeTicks::Now() - navigation_handle->NavigationStart(), |
| 458 navigation_handle->GetNetErrorCode())); | 469 navigation_handle->GetNetErrorCode())); |
| 459 } | 470 } |
| 460 | 471 |
| 461 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { | 472 void PageLoadTracker::Redirect(content::NavigationHandle* navigation_handle) { |
| 473 MaybeUpdateURL(navigation_handle); | |
| 462 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); | 474 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnRedirect, navigation_handle); |
| 463 } | 475 } |
| 464 | 476 |
| 465 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { | 477 void PageLoadTracker::OnInputEvent(const blink::WebInputEvent& event) { |
| 466 input_tracker_.OnInputEvent(event); | 478 input_tracker_.OnInputEvent(event); |
| 467 for (const auto& observer : observers_) { | 479 for (const auto& observer : observers_) { |
| 468 observer->OnUserInput(event); | 480 observer->OnUserInput(event); |
| 469 } | 481 } |
| 470 } | 482 } |
| 471 | 483 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 // different start time from an earlier struct is considered invalid. | 516 // different start time from an earlier struct is considered invalid. |
| 505 bool valid_timing_descendent = | 517 bool valid_timing_descendent = |
| 506 timing_.navigation_start.is_null() || | 518 timing_.navigation_start.is_null() || |
| 507 timing_.navigation_start == new_timing.navigation_start; | 519 timing_.navigation_start == new_timing.navigation_start; |
| 508 // Ensure flags sent previously are still present in the new metadata fields. | 520 // Ensure flags sent previously are still present in the new metadata fields. |
| 509 bool valid_behavior_descendent = | 521 bool valid_behavior_descendent = |
| 510 (metadata_.behavior_flags & new_metadata.behavior_flags) == | 522 (metadata_.behavior_flags & new_metadata.behavior_flags) == |
| 511 metadata_.behavior_flags; | 523 metadata_.behavior_flags; |
| 512 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent && | 524 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent && |
| 513 valid_behavior_descendent) { | 525 valid_behavior_descendent) { |
| 514 DCHECK(!committed_url_.is_empty()); // OnCommit() must be called first. | 526 DCHECK(did_commit_); // OnCommit() must be called first. |
| 515 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() | 527 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() |
| 516 // must be called before DispatchObserverTimingCallbacks, but its | 528 // must be called before DispatchObserverTimingCallbacks, but its |
| 517 // implementation depends on the state of metadata_, so we need to update | 529 // implementation depends on the state of metadata_, so we need to update |
| 518 // metadata_ before calling GetPageLoadMetricsInfo. Thus, we make a copy of | 530 // metadata_ before calling GetPageLoadMetricsInfo. Thus, we make a copy of |
| 519 // timing here, update timing_ and metadata_, and then proceed to dispatch | 531 // timing here, update timing_ and metadata_, and then proceed to dispatch |
| 520 // the observer timing callbacks. | 532 // the observer timing callbacks. |
| 521 const PageLoadTiming last_timing = timing_; | 533 const PageLoadTiming last_timing = timing_; |
| 522 timing_ = new_timing; | 534 timing_ = new_timing; |
| 523 | 535 |
| 524 const PageLoadMetadata last_metadata = metadata_; | 536 const PageLoadMetadata last_metadata = metadata_; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 } | 612 } |
| 601 | 613 |
| 602 // abort_type_ == ABORT_NONE implies abort_user_initiated_info_ is not user | 614 // abort_type_ == ABORT_NONE implies abort_user_initiated_info_ is not user |
| 603 // initiated. | 615 // initiated. |
| 604 DCHECK(abort_type_ != ABORT_NONE || | 616 DCHECK(abort_type_ != ABORT_NONE || |
| 605 (!abort_user_initiated_info_.browser_initiated && | 617 (!abort_user_initiated_info_.browser_initiated && |
| 606 !abort_user_initiated_info_.user_gesture && | 618 !abort_user_initiated_info_.user_gesture && |
| 607 !abort_user_initiated_info_.user_input_event)); | 619 !abort_user_initiated_info_.user_input_event)); |
| 608 return PageLoadExtraInfo( | 620 return PageLoadExtraInfo( |
| 609 first_background_time, first_foreground_time, started_in_foreground_, | 621 first_background_time, first_foreground_time, started_in_foreground_, |
| 610 user_initiated_info_, committed_url_, start_url_, abort_type_, | 622 user_initiated_info_, url(), start_url(), did_commit_, abort_type_, |
| 611 abort_user_initiated_info_, time_to_abort, metadata_); | 623 abort_user_initiated_info_, time_to_abort, metadata_); |
| 612 } | 624 } |
| 613 | 625 |
| 614 bool PageLoadTracker::HasMatchingNavigationRequestID( | 626 bool PageLoadTracker::HasMatchingNavigationRequestID( |
| 615 const content::GlobalRequestID& request_id) const { | 627 const content::GlobalRequestID& request_id) const { |
| 616 DCHECK(request_id != content::GlobalRequestID()); | 628 DCHECK(request_id != content::GlobalRequestID()); |
| 617 return navigation_request_id_.has_value() && | 629 return navigation_request_id_.has_value() && |
| 618 navigation_request_id_.value() == request_id; | 630 navigation_request_id_.value() == request_id; |
| 619 } | 631 } |
| 620 | 632 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 651 base::TimeTicks abort_cause_time) const { | 663 base::TimeTicks abort_cause_time) const { |
| 652 // Note that |abort_cause_time - abort_time| can be negative. | 664 // Note that |abort_cause_time - abort_time| can be negative. |
| 653 return abort_type_ == ABORT_OTHER && | 665 return abort_type_ == ABORT_OTHER && |
| 654 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 666 (abort_cause_time - abort_time_).InMilliseconds() < 100; |
| 655 } | 667 } |
| 656 | 668 |
| 657 bool PageLoadTracker::MatchesOriginalNavigation( | 669 bool PageLoadTracker::MatchesOriginalNavigation( |
| 658 content::NavigationHandle* navigation_handle) { | 670 content::NavigationHandle* navigation_handle) { |
| 659 // Neither navigation should have committed. | 671 // Neither navigation should have committed. |
| 660 DCHECK(!navigation_handle->HasCommitted()); | 672 DCHECK(!navigation_handle->HasCommitted()); |
| 661 DCHECK(committed_url_.is_empty()); | 673 DCHECK(!did_commit_); |
| 662 return navigation_handle->GetURL() == start_url_; | 674 return navigation_handle->GetURL() == start_url(); |
| 663 } | 675 } |
| 664 | 676 |
| 665 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 677 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, |
| 666 UserInitiatedInfo user_initiated_info, | 678 UserInitiatedInfo user_initiated_info, |
| 667 base::TimeTicks timestamp, | 679 base::TimeTicks timestamp, |
| 668 bool is_certainly_browser_timestamp) { | 680 bool is_certainly_browser_timestamp) { |
| 669 // When a provisional navigation commits, that navigation's start time is | 681 // When a provisional navigation commits, that navigation's start time is |
| 670 // interpreted as the abort time for other provisional loads in the tab. | 682 // interpreted as the abort time for other provisional loads in the tab. |
| 671 // However, this only makes sense if the committed load started after the | 683 // However, this only makes sense if the committed load started after the |
| 672 // aborted provisional loads started. Thus we ignore cases where the committed | 684 // aborted provisional loads started. Thus we ignore cases where the committed |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 693 // user initiated. | 705 // user initiated. |
| 694 if (abort_type != ABORT_CLIENT_REDIRECT) | 706 if (abort_type != ABORT_CLIENT_REDIRECT) |
| 695 abort_user_initiated_info_ = user_initiated_info; | 707 abort_user_initiated_info_ = user_initiated_info; |
| 696 | 708 |
| 697 if (is_certainly_browser_timestamp) { | 709 if (is_certainly_browser_timestamp) { |
| 698 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | 710 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); |
| 699 } | 711 } |
| 700 } | 712 } |
| 701 | 713 |
| 702 } // namespace page_load_metrics | 714 } // namespace page_load_metrics |
| OLD | NEW |