OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/page_load_metrics/browser/metrics_web_contents_observer.h" | 5 #include "components/page_load_metrics/browser/metrics_web_contents_observer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 embedder_interface_(embedder_interface) { | 253 embedder_interface_(embedder_interface) { |
254 DCHECK(!navigation_handle->HasCommitted()); | 254 DCHECK(!navigation_handle->HasCommitted()); |
255 embedder_interface_->RegisterObservers(this); | 255 embedder_interface_->RegisterObservers(this); |
256 for (const auto& observer : observers_) { | 256 for (const auto& observer : observers_) { |
257 observer->OnStart(navigation_handle, currently_committed_url, | 257 observer->OnStart(navigation_handle, currently_committed_url, |
258 started_in_foreground_); | 258 started_in_foreground_); |
259 } | 259 } |
260 } | 260 } |
261 | 261 |
262 PageLoadTracker::~PageLoadTracker() { | 262 PageLoadTracker::~PageLoadTracker() { |
263 const PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | 263 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
264 if (!info.time_to_commit.is_zero() && renderer_tracked() && | 264 |
265 timing_.IsEmpty()) { | 265 if (info.time_to_commit && renderer_tracked() && timing_.IsEmpty()) { |
266 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 266 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
267 } | 267 } |
268 // Recall that trackers that are given ABORT_UNKNOWN_NAVIGATION have their | 268 // Recall that trackers that are given ABORT_UNKNOWN_NAVIGATION have their |
269 // chain length added to the next navigation. Take care not to double count | 269 // chain length added to the next navigation. Take care not to double count |
270 // them. Also do not double count committed loads, which call this already. | 270 // them. Also do not double count committed loads, which call this already. |
271 if (commit_time_.is_null() && abort_type_ != ABORT_UNKNOWN_NAVIGATION) | 271 if (commit_time_.is_null() && abort_type_ != ABORT_UNKNOWN_NAVIGATION) |
272 LogAbortChainHistograms(nullptr); | 272 LogAbortChainHistograms(nullptr); |
273 | 273 |
274 for (const auto& observer : observers_) { | 274 for (const auto& observer : observers_) { |
275 observer->OnComplete(timing_, info); | 275 observer->OnComplete(timing_, info); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 } | 322 } |
323 | 323 |
324 void PageLoadTracker::WebContentsHidden() { | 324 void PageLoadTracker::WebContentsHidden() { |
325 // Only log the first time we background in a given page load. | 325 // Only log the first time we background in a given page load. |
326 if (background_time_.is_null()) { | 326 if (background_time_.is_null()) { |
327 // Make sure we either started in the foreground and haven't been | 327 // Make sure we either started in the foreground and haven't been |
328 // foregrounded yet, or started in the background and have already been | 328 // foregrounded yet, or started in the background and have already been |
329 // foregrounded. | 329 // foregrounded. |
330 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | 330 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); |
331 background_time_ = base::TimeTicks::Now(); | 331 background_time_ = base::TimeTicks::Now(); |
332 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | |
332 } | 333 } |
333 | 334 |
334 for (const auto& observer : observers_) | 335 for (const auto& observer : observers_) |
335 observer->OnHidden(); | 336 observer->OnHidden(); |
336 } | 337 } |
337 | 338 |
338 void PageLoadTracker::WebContentsShown() { | 339 void PageLoadTracker::WebContentsShown() { |
339 // Only log the first time we foreground in a given page load. | 340 // Only log the first time we foreground in a given page load. |
340 if (foreground_time_.is_null()) { | 341 if (foreground_time_.is_null()) { |
341 // Make sure we either started in the background and haven't been | 342 // Make sure we either started in the background and haven't been |
342 // backgrounded yet, or started in the foreground and have already been | 343 // backgrounded yet, or started in the foreground and have already been |
343 // backgrounded. | 344 // backgrounded. |
344 DCHECK_NE(started_in_foreground_, background_time_.is_null()); | 345 DCHECK_NE(started_in_foreground_, background_time_.is_null()); |
345 foreground_time_ = base::TimeTicks::Now(); | 346 foreground_time_ = base::TimeTicks::Now(); |
347 ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); | |
346 } | 348 } |
347 | 349 |
348 for (const auto& observer : observers_) | 350 for (const auto& observer : observers_) |
349 observer->OnShown(); | 351 observer->OnShown(); |
350 } | 352 } |
351 | 353 |
352 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 354 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { |
353 // TODO(bmcquade): To improve accuracy, consider adding commit time to | 355 // TODO(bmcquade): To improve accuracy, consider adding commit time to |
354 // NavigationHandle. Taking a timestamp here should be close enough for now. | 356 // NavigationHandle. Taking a timestamp here should be close enough for now. |
355 commit_time_ = base::TimeTicks::Now(); | 357 commit_time_ = base::TimeTicks::Now(); |
358 ClampBrowserTimestampIfInterProcessTimeTickSkew(&commit_time_); | |
356 url_ = navigation_handle->GetURL(); | 359 url_ = navigation_handle->GetURL(); |
357 for (const auto& observer : observers_) { | 360 for (const auto& observer : observers_) { |
358 observer->OnCommit(navigation_handle); | 361 observer->OnCommit(navigation_handle); |
359 } | 362 } |
360 LogAbortChainHistograms(navigation_handle); | 363 LogAbortChainHistograms(navigation_handle); |
361 } | 364 } |
362 | 365 |
363 void PageLoadTracker::FailedProvisionalLoad( | 366 void PageLoadTracker::FailedProvisionalLoad( |
364 content::NavigationHandle* navigation_handle) { | 367 content::NavigationHandle* navigation_handle) { |
365 for (const auto& observer : observers_) { | 368 for (const auto& observer : observers_) { |
(...skipping 30 matching lines...) Expand all Loading... | |
396 valid_behavior_descendent) { | 399 valid_behavior_descendent) { |
397 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() | 400 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() |
398 // must be called before DispatchObserverTimingCallbacks, but its | 401 // must be called before DispatchObserverTimingCallbacks, but its |
399 // implementation depends on the state of metadata_, so we need to update | 402 // implementation depends on the state of metadata_, so we need to update |
400 // metadata_ before calling GetPageLoadMetricsInfo. Thus, we make a copy of | 403 // metadata_ before calling GetPageLoadMetricsInfo. Thus, we make a copy of |
401 // timing here, update timing_ and metadata_, and then proceed to dispatch | 404 // timing here, update timing_ and metadata_, and then proceed to dispatch |
402 // the observer timing callbacks. | 405 // the observer timing callbacks. |
403 const PageLoadTiming last_timing = timing_; | 406 const PageLoadTiming last_timing = timing_; |
404 timing_ = new_timing; | 407 timing_ = new_timing; |
405 metadata_ = new_metadata; | 408 metadata_ = new_metadata; |
406 const PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | 409 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
407 for (const auto& observer : observers_) { | 410 for (const auto& observer : observers_) { |
408 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing, | 411 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing, |
409 info); | 412 info); |
410 } | 413 } |
411 return true; | 414 return true; |
412 } | 415 } |
413 return false; | 416 return false; |
414 } | 417 } |
415 | 418 |
416 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { | 419 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { |
417 renderer_tracked_ = renderer_tracked; | 420 renderer_tracked_ = renderer_tracked; |
418 } | 421 } |
419 | 422 |
420 void PageLoadTracker::AddObserver( | 423 void PageLoadTracker::AddObserver( |
421 std::unique_ptr<PageLoadMetricsObserver> observer) { | 424 std::unique_ptr<PageLoadMetricsObserver> observer) { |
422 observers_.push_back(std::move(observer)); | 425 observers_.push_back(std::move(observer)); |
423 } | 426 } |
424 | 427 |
425 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { | 428 void PageLoadTracker::ClampBrowserTimestampIfInterProcessTimeTickSkew( |
426 base::TimeDelta first_background_time; | 429 base::TimeTicks* event_time) { |
427 base::TimeDelta first_foreground_time; | 430 DCHECK(event_time != nullptr); |
428 base::TimeDelta time_to_abort; | 431 // Windows 10 GCE bot non-deterministically failed because TimeTicks::Now() |
429 base::TimeDelta time_to_commit; | 432 // called in the browser process e.g. commit_time was less than |
430 if (!background_time_.is_null()) | 433 // navigation_start_ that was populated in the renderer process because the |
434 // clock was not system-wide monotonic. | |
435 // Note that navigation_start_ can also be set in the browser process in | |
436 // some cases and in those cases event_time should never be < | |
437 // navigation_start_. If it is due to a code error and it gets clamped in this | |
438 // function, on high resolution systems it should lead to a dcheck failure. | |
439 | |
440 // TODO (shivanisha) Currently IsHighResolution is the best way to check | |
441 // if the clock is system-wide monotonic. However IsHighResolution | |
442 // does a broader check to see if the clock in use is high resolution | |
443 // which also implies it is system-wide monotonic (on Windows). | |
444 if (base::TimeTicks::IsHighResolution()) { | |
445 return; | |
Bryan McQuade
2016/06/21 00:59:46
could we also add:
DCHECK(event_time->is_null() ||
shivanisha
2016/06/21 17:08:51
Good point. done.
| |
446 } | |
447 | |
448 if (!event_time->is_null() && *event_time < navigation_start_) { | |
449 RecordInternalError(ERR_INTER_PROCESS_TIME_TICK_SKEW); | |
450 *event_time = navigation_start_; | |
451 } | |
452 } | |
453 | |
454 PageLoadExtraInfo PageLoadTracker::ComputePageLoadExtraInfo() { | |
455 base::Optional<base::TimeDelta> first_background_time; | |
456 base::Optional<base::TimeDelta> first_foreground_time; | |
457 base::Optional<base::TimeDelta> time_to_abort; | |
458 base::Optional<base::TimeDelta> time_to_commit; | |
459 | |
460 if (!background_time_.is_null()) { | |
461 DCHECK_GE(background_time_, navigation_start_); | |
431 first_background_time = background_time_ - navigation_start_; | 462 first_background_time = background_time_ - navigation_start_; |
432 if (!foreground_time_.is_null()) | 463 } |
464 | |
465 if (!foreground_time_.is_null()) { | |
466 DCHECK_GE(foreground_time_, navigation_start_); | |
433 first_foreground_time = foreground_time_ - navigation_start_; | 467 first_foreground_time = foreground_time_ - navigation_start_; |
468 } | |
469 | |
434 if (abort_type_ != ABORT_NONE) { | 470 if (abort_type_ != ABORT_NONE) { |
435 DCHECK_GT(abort_time_, navigation_start_); | 471 DCHECK_GE(abort_time_, navigation_start_); |
436 time_to_abort = abort_time_ - navigation_start_; | 472 time_to_abort = abort_time_ - navigation_start_; |
437 } else { | 473 } else { |
438 DCHECK(abort_time_.is_null()); | 474 DCHECK(abort_time_.is_null()); |
439 } | 475 } |
440 | 476 |
441 if (!commit_time_.is_null()) { | 477 if (!commit_time_.is_null()) { |
442 DCHECK_GT(commit_time_, navigation_start_); | 478 DCHECK_GE(commit_time_, navigation_start_); |
443 time_to_commit = commit_time_ - navigation_start_; | 479 time_to_commit = commit_time_ - navigation_start_; |
444 } else { | |
445 DCHECK(commit_time_.is_null()); | |
446 } | 480 } |
481 | |
447 return PageLoadExtraInfo( | 482 return PageLoadExtraInfo( |
448 first_background_time, first_foreground_time, started_in_foreground_, | 483 first_background_time, first_foreground_time, started_in_foreground_, |
449 commit_time_.is_null() ? GURL() : url_, time_to_commit, abort_type_, | 484 commit_time_.is_null() ? GURL() : url_, time_to_commit, abort_type_, |
450 time_to_abort, metadata_); | 485 time_to_abort, metadata_); |
451 } | 486 } |
452 | 487 |
453 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 488 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, |
454 base::TimeTicks timestamp) { | 489 base::TimeTicks timestamp, |
490 bool is_certainly_browser_timestamp) { | |
455 DCHECK_NE(abort_type, ABORT_NONE); | 491 DCHECK_NE(abort_type, ABORT_NONE); |
456 // Use UpdateAbort to update an already notified PageLoadTracker. | 492 // Use UpdateAbort to update an already notified PageLoadTracker. |
457 if (abort_type_ != ABORT_NONE) | 493 if (abort_type_ != ABORT_NONE) |
458 return; | 494 return; |
459 | 495 |
460 UpdateAbortInternal(abort_type, timestamp); | 496 UpdateAbortInternal(abort_type, timestamp, is_certainly_browser_timestamp); |
461 } | 497 } |
462 | 498 |
463 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, | 499 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, |
464 base::TimeTicks timestamp) { | 500 base::TimeTicks timestamp, |
501 bool is_certainly_browser_timestamp) { | |
465 DCHECK_NE(abort_type, ABORT_NONE); | 502 DCHECK_NE(abort_type, ABORT_NONE); |
466 DCHECK_NE(abort_type, ABORT_OTHER); | 503 DCHECK_NE(abort_type, ABORT_OTHER); |
467 DCHECK_EQ(abort_type_, ABORT_OTHER); | 504 DCHECK_EQ(abort_type_, ABORT_OTHER); |
468 | 505 |
469 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 506 // For some aborts (e.g. navigations), the initiated timestamp can be earlier |
470 // than the timestamp that aborted the load. Taking the minimum gives the | 507 // than the timestamp that aborted the load. Taking the minimum gives the |
471 // closest user initiated time known. | 508 // closest user initiated time known. |
472 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp)); | 509 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp), |
510 is_certainly_browser_timestamp); | |
473 } | 511 } |
474 | 512 |
475 bool PageLoadTracker::IsLikelyProvisionalAbort( | 513 bool PageLoadTracker::IsLikelyProvisionalAbort( |
476 base::TimeTicks abort_cause_time) { | 514 base::TimeTicks abort_cause_time) { |
477 // Note that |abort_cause_time - abort_time| can be negative. | 515 // Note that |abort_cause_time - abort_time| can be negative. |
478 return abort_type_ == ABORT_OTHER && | 516 return abort_type_ == ABORT_OTHER && |
479 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 517 (abort_cause_time - abort_time_).InMilliseconds() < 100; |
480 } | 518 } |
481 | 519 |
482 bool PageLoadTracker::MatchesOriginalNavigation( | 520 bool PageLoadTracker::MatchesOriginalNavigation( |
483 content::NavigationHandle* navigation_handle) { | 521 content::NavigationHandle* navigation_handle) { |
484 // Neither navigation should have committed. | 522 // Neither navigation should have committed. |
485 DCHECK(!navigation_handle->HasCommitted()); | 523 DCHECK(!navigation_handle->HasCommitted()); |
486 DCHECK(commit_time_.is_null()); | 524 DCHECK(commit_time_.is_null()); |
487 return navigation_handle->GetURL() == url_; | 525 return navigation_handle->GetURL() == url_; |
488 } | 526 } |
489 | 527 |
490 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 528 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, |
491 base::TimeTicks timestamp) { | 529 base::TimeTicks timestamp, |
530 bool is_certainly_browser_timestamp) { | |
492 // When a provisional navigation commits, that navigation's start time is | 531 // When a provisional navigation commits, that navigation's start time is |
493 // interpreted as the abort time for other provisional loads in the tab. | 532 // interpreted as the abort time for other provisional loads in the tab. |
494 // However, this only makes sense if the committed load started after the | 533 // However, this only makes sense if the committed load started after the |
495 // aborted provisional loads started. Thus we ignore cases where the committed | 534 // aborted provisional loads started. Thus we ignore cases where the committed |
496 // load started before the aborted provisional load, as this would result in | 535 // load started before the aborted provisional load, as this would result in |
497 // recording a negative time-to-abort. The real issue here is that we have to | 536 // recording a negative time-to-abort. The real issue here is that we have to |
498 // infer the cause of aborts. It would be better if the navigation code could | 537 // infer the cause of aborts. It would be better if the navigation code could |
499 // instead report the actual cause of an aborted navigation. See crbug/571647 | 538 // instead report the actual cause of an aborted navigation. See crbug/571647 |
500 // for details. | 539 // for details. |
501 if (timestamp <= navigation_start_) { | 540 if (timestamp < navigation_start_) { |
502 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 541 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); |
503 abort_type_ = ABORT_NONE; | 542 abort_type_ = ABORT_NONE; |
504 abort_time_ = base::TimeTicks(); | 543 abort_time_ = base::TimeTicks(); |
505 return; | 544 return; |
506 } | 545 } |
507 abort_type_ = abort_type; | 546 abort_type_ = abort_type; |
508 abort_time_ = timestamp; | 547 abort_time_ = timestamp; |
548 | |
549 if (is_certainly_browser_timestamp) { | |
550 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | |
551 } | |
509 } | 552 } |
510 | 553 |
511 // static | 554 // static |
512 MetricsWebContentsObserver::MetricsWebContentsObserver( | 555 MetricsWebContentsObserver::MetricsWebContentsObserver( |
513 content::WebContents* web_contents, | 556 content::WebContents* web_contents, |
514 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) | 557 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) |
515 : content::WebContentsObserver(web_contents), | 558 : content::WebContentsObserver(web_contents), |
516 in_foreground_(false), | 559 in_foreground_(false), |
517 embedder_interface_(std::move(embedder_interface)), | 560 embedder_interface_(std::move(embedder_interface)), |
518 has_navigated_(false) { | 561 has_navigated_(false) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
615 // the MetricsWebContentsObserver owns them both list and they are torn down | 658 // the MetricsWebContentsObserver owns them both list and they are torn down |
616 // after the PageLoadTracker. The PageLoadTracker does not hold on to | 659 // after the PageLoadTracker. The PageLoadTracker does not hold on to |
617 // committed_load_ or navigation_handle beyond the scope of the constructor. | 660 // committed_load_ or navigation_handle beyond the scope of the constructor. |
618 provisional_loads_.insert(std::make_pair( | 661 provisional_loads_.insert(std::make_pair( |
619 navigation_handle, | 662 navigation_handle, |
620 base::WrapUnique(new PageLoadTracker( | 663 base::WrapUnique(new PageLoadTracker( |
621 in_foreground_, embedder_interface_.get(), currently_committed_url, | 664 in_foreground_, embedder_interface_.get(), currently_committed_url, |
622 navigation_handle, chain_size, chain_size_same_url)))); | 665 navigation_handle, chain_size, chain_size_same_url)))); |
623 } | 666 } |
624 | 667 |
668 const PageLoadExtraInfo | |
669 MetricsWebContentsObserver::GetPageLoadExtraInfoForCommittedLoad() { | |
670 DCHECK(committed_load_); | |
671 return committed_load_->ComputePageLoadExtraInfo(); | |
672 } | |
673 | |
625 void MetricsWebContentsObserver::DidFinishNavigation( | 674 void MetricsWebContentsObserver::DidFinishNavigation( |
626 content::NavigationHandle* navigation_handle) { | 675 content::NavigationHandle* navigation_handle) { |
627 if (!navigation_handle->IsInMainFrame()) | 676 if (!navigation_handle->IsInMainFrame()) |
628 return; | 677 return; |
629 | 678 |
630 std::unique_ptr<PageLoadTracker> finished_nav( | 679 std::unique_ptr<PageLoadTracker> finished_nav( |
631 std::move(provisional_loads_[navigation_handle])); | 680 std::move(provisional_loads_[navigation_handle])); |
632 provisional_loads_.erase(navigation_handle); | 681 provisional_loads_.erase(navigation_handle); |
633 | 682 |
634 // There's a chance a navigation could have started before we were added to a | 683 // There's a chance a navigation could have started before we were added to a |
(...skipping 12 matching lines...) Expand all Loading... | |
647 net::Error error = navigation_handle->GetNetErrorCode(); | 696 net::Error error = navigation_handle->GetNetErrorCode(); |
648 | 697 |
649 // net::OK: This case occurs when the NavigationHandle finishes and reports | 698 // net::OK: This case occurs when the NavigationHandle finishes and reports |
650 // !HasCommitted(), but reports no net::Error. This should not occur | 699 // !HasCommitted(), but reports no net::Error. This should not occur |
651 // pre-PlzNavigate, but afterwards it should represent the navigation | 700 // pre-PlzNavigate, but afterwards it should represent the navigation |
652 // stopped by the user before it was ready to commit. | 701 // stopped by the user before it was ready to commit. |
653 // net::ERR_ABORTED: An aborted provisional load has error net::ERR_ABORTED. | 702 // net::ERR_ABORTED: An aborted provisional load has error net::ERR_ABORTED. |
654 // Note that this can come from some non user-initiated errors, such as | 703 // Note that this can come from some non user-initiated errors, such as |
655 // downloads, or 204 responses. See crbug.com/542369. | 704 // downloads, or 204 responses. See crbug.com/542369. |
656 if ((error == net::OK) || (error == net::ERR_ABORTED)) { | 705 if ((error == net::OK) || (error == net::ERR_ABORTED)) { |
657 finished_nav->NotifyAbort(ABORT_OTHER, base::TimeTicks::Now()); | 706 finished_nav->NotifyAbort(ABORT_OTHER, base::TimeTicks::Now(), true); |
658 aborted_provisional_loads_.push_back(std::move(finished_nav)); | 707 aborted_provisional_loads_.push_back(std::move(finished_nav)); |
659 } | 708 } |
660 | 709 |
661 return; | 710 return; |
662 } | 711 } |
663 | 712 |
664 // Don't treat a same-page nav as a new page load. | 713 // Don't treat a same-page nav as a new page load. |
665 if (navigation_handle->IsSamePage()) | 714 if (navigation_handle->IsSamePage()) |
666 return; | 715 return; |
667 | 716 |
668 // Notify other loads that they may have been aborted by this committed load. | 717 // Notify other loads that they may have been aborted by this committed load. |
669 // Note that by using the committed navigation start as the abort cause, we | 718 // Note that by using the committed navigation start as the abort cause, we |
670 // lose data on provisional loads that were aborted by other provisional | 719 // lose data on provisional loads that were aborted by other provisional |
671 // loads. Those will either be listed as ABORT_OTHER or as being aborted by | 720 // loads. Those will either be listed as ABORT_OTHER or as being aborted by |
672 // this load. | 721 // this load. |
722 // is_certainly_browser_timestamp is set to false because NavigationStart() | |
723 // could be set in either the renderer or browser process. | |
673 NotifyAbortAllLoadsWithTimestamp( | 724 NotifyAbortAllLoadsWithTimestamp( |
674 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), | 725 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), |
675 navigation_handle->NavigationStart()); | 726 navigation_handle->NavigationStart(), false); |
676 | 727 |
677 committed_load_ = std::move(finished_nav); | 728 committed_load_ = std::move(finished_nav); |
678 aborted_provisional_loads_.clear(); | 729 aborted_provisional_loads_.clear(); |
679 | 730 |
680 const GURL& browser_url = web_contents()->GetLastCommittedURL(); | 731 const GURL& browser_url = web_contents()->GetLastCommittedURL(); |
681 const std::string& mime_type = web_contents()->GetContentsMimeType(); | 732 const std::string& mime_type = web_contents()->GetContentsMimeType(); |
682 DCHECK(!browser_url.is_empty()); | 733 DCHECK(!browser_url.is_empty()); |
683 DCHECK(!mime_type.empty()); | 734 DCHECK(!mime_type.empty()); |
684 committed_load_->set_renderer_tracked( | 735 committed_load_->set_renderer_tracked( |
685 IsRelevantNavigation(navigation_handle, browser_url, mime_type)); | 736 IsRelevantNavigation(navigation_handle, browser_url, mime_type)); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
752 } | 803 } |
753 | 804 |
754 // If this is a crash, eagerly log the aborted provisional loads and the | 805 // If this is a crash, eagerly log the aborted provisional loads and the |
755 // committed load. |provisional_loads_| don't need to be destroyed here | 806 // committed load. |provisional_loads_| don't need to be destroyed here |
756 // because their lifetime is tied to the NavigationHandle. | 807 // because their lifetime is tied to the NavigationHandle. |
757 committed_load_.reset(); | 808 committed_load_.reset(); |
758 aborted_provisional_loads_.clear(); | 809 aborted_provisional_loads_.clear(); |
759 } | 810 } |
760 | 811 |
761 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { | 812 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { |
762 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now()); | 813 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now(), true); |
763 } | 814 } |
764 | 815 |
765 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( | 816 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( |
766 UserAbortType abort_type, | 817 UserAbortType abort_type, |
767 base::TimeTicks timestamp) { | 818 base::TimeTicks timestamp, |
819 bool is_certainly_browser_timestamp) { | |
768 if (committed_load_) | 820 if (committed_load_) |
769 committed_load_->NotifyAbort(abort_type, timestamp); | 821 committed_load_->NotifyAbort(abort_type, timestamp, |
822 is_certainly_browser_timestamp); | |
770 for (const auto& kv : provisional_loads_) { | 823 for (const auto& kv : provisional_loads_) { |
771 kv.second->NotifyAbort(abort_type, timestamp); | 824 kv.second->NotifyAbort(abort_type, timestamp, |
825 is_certainly_browser_timestamp); | |
772 } | 826 } |
773 for (const auto& tracker : aborted_provisional_loads_) { | 827 for (const auto& tracker : aborted_provisional_loads_) { |
774 if (tracker->IsLikelyProvisionalAbort(timestamp)) | 828 if (tracker->IsLikelyProvisionalAbort(timestamp)) |
775 tracker->UpdateAbort(abort_type, timestamp); | 829 tracker->UpdateAbort(abort_type, timestamp, |
830 is_certainly_browser_timestamp); | |
776 } | 831 } |
777 aborted_provisional_loads_.clear(); | 832 aborted_provisional_loads_.clear(); |
778 } | 833 } |
779 | 834 |
780 std::unique_ptr<PageLoadTracker> | 835 std::unique_ptr<PageLoadTracker> |
781 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( | 836 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( |
782 content::NavigationHandle* new_navigation) { | 837 content::NavigationHandle* new_navigation) { |
783 // If there are multiple aborted loads that can be attributed to this one, | 838 // If there are multiple aborted loads that can be attributed to this one, |
784 // just count the latest one for simplicity. Other loads will fall into the | 839 // just count the latest one for simplicity. Other loads will fall into the |
785 // OTHER bucket, though there shouldn't be very many. | 840 // OTHER bucket, though there shouldn't be very many. |
786 if (aborted_provisional_loads_.size() == 0) | 841 if (aborted_provisional_loads_.size() == 0) |
787 return nullptr; | 842 return nullptr; |
788 if (aborted_provisional_loads_.size() > 1) | 843 if (aborted_provisional_loads_.size() > 1) |
789 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); | 844 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); |
790 | 845 |
791 std::unique_ptr<PageLoadTracker> last_aborted_load = | 846 std::unique_ptr<PageLoadTracker> last_aborted_load = |
792 std::move(aborted_provisional_loads_.back()); | 847 std::move(aborted_provisional_loads_.back()); |
793 aborted_provisional_loads_.pop_back(); | 848 aborted_provisional_loads_.pop_back(); |
794 | 849 |
795 base::TimeTicks timestamp = new_navigation->NavigationStart(); | 850 base::TimeTicks timestamp = new_navigation->NavigationStart(); |
796 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) | 851 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) |
797 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp); | 852 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp, false); |
798 | 853 |
799 aborted_provisional_loads_.clear(); | 854 aborted_provisional_loads_.clear(); |
800 return last_aborted_load; | 855 return last_aborted_load; |
801 } | 856 } |
802 | 857 |
803 void MetricsWebContentsObserver::OnTimingUpdated( | 858 void MetricsWebContentsObserver::OnTimingUpdated( |
804 content::RenderFrameHost* render_frame_host, | 859 content::RenderFrameHost* render_frame_host, |
805 const PageLoadTiming& timing, | 860 const PageLoadTiming& timing, |
806 const PageLoadMetadata& metadata) { | 861 const PageLoadMetadata& metadata) { |
807 bool error = false; | 862 bool error = false; |
(...skipping 22 matching lines...) Expand all Loading... | |
830 | 885 |
831 if (!committed_load_->UpdateTiming(timing, metadata)) { | 886 if (!committed_load_->UpdateTiming(timing, metadata)) { |
832 // If the page load tracker cannot update its timing, something is wrong | 887 // If the page load tracker cannot update its timing, something is wrong |
833 // with the IPC (it's from another load, or it's invalid in some other way). | 888 // with the IPC (it's from another load, or it's invalid in some other way). |
834 // We expect this to be a rare occurrence. | 889 // We expect this to be a rare occurrence. |
835 RecordInternalError(ERR_BAD_TIMING_IPC); | 890 RecordInternalError(ERR_BAD_TIMING_IPC); |
836 } | 891 } |
837 } | 892 } |
838 | 893 |
839 } // namespace page_load_metrics | 894 } // namespace page_load_metrics |
OLD | NEW |