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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 251 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
252 embedder_interface_(embedder_interface) { | 252 embedder_interface_(embedder_interface) { |
253 DCHECK(!navigation_handle->HasCommitted()); | 253 DCHECK(!navigation_handle->HasCommitted()); |
254 embedder_interface_->RegisterObservers(this); | 254 embedder_interface_->RegisterObservers(this); |
255 for (const auto& observer : observers_) { | 255 for (const auto& observer : observers_) { |
256 observer->OnStart(navigation_handle, currently_committed_url); | 256 observer->OnStart(navigation_handle, currently_committed_url); |
257 } | 257 } |
258 } | 258 } |
259 | 259 |
260 PageLoadTracker::~PageLoadTracker() { | 260 PageLoadTracker::~PageLoadTracker() { |
261 const PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | 261 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
262 if (!info.time_to_commit.is_zero() && renderer_tracked() && | 262 |
263 timing_.IsEmpty()) { | 263 if (info.time_to_commit && renderer_tracked() && timing_.IsEmpty()) { |
264 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 264 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
265 } | 265 } |
266 // Recall that trackers that are given ABORT_UNKNOWN_NAVIGATION have their | 266 // Recall that trackers that are given ABORT_UNKNOWN_NAVIGATION have their |
267 // chain length added to the next navigation. Take care not to double count | 267 // chain length added to the next navigation. Take care not to double count |
268 // them. Also do not double count committed loads, which call this already. | 268 // them. Also do not double count committed loads, which call this already. |
269 if (commit_time_.is_null() && abort_type_ != ABORT_UNKNOWN_NAVIGATION) | 269 if (commit_time_.is_null() && abort_type_ != ABORT_UNKNOWN_NAVIGATION) |
270 LogAbortChainHistograms(nullptr); | 270 LogAbortChainHistograms(nullptr); |
271 | 271 |
272 for (const auto& observer : observers_) { | 272 for (const auto& observer : observers_) { |
273 observer->OnComplete(timing_, info); | 273 observer->OnComplete(timing_, info); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 default: | 314 default: |
315 NOTREACHED() | 315 NOTREACHED() |
316 << "LogAbortChainHistograms received unexpected ui::PageTransition: " | 316 << "LogAbortChainHistograms received unexpected ui::PageTransition: " |
317 << committed_transition; | 317 << committed_transition; |
318 return; | 318 return; |
319 } | 319 } |
320 } | 320 } |
321 | 321 |
322 void PageLoadTracker::WebContentsHidden() { | 322 void PageLoadTracker::WebContentsHidden() { |
323 // Only log the first time we background in a given page load. | 323 // Only log the first time we background in a given page load. |
324 if (background_time_.is_null()) { | 324 if (!background_time_.is_null()) { |
Charlie Harrison
2016/05/19 18:20:49
Why not convert fg and bg time to optionals too? U
shivanisha
2016/05/23 15:06:43
Either way is fine,
Since TimeTicks has the semant
| |
325 // Make sure we either started in the foreground and haven't been | 325 return; |
326 // foregrounded yet, or started in the background and have already been | |
327 // foregrounded. | |
328 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | |
329 background_time_ = base::TimeTicks::Now(); | |
330 } | 326 } |
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 | |
329 // foregrounded. | |
330 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | |
331 background_time_ = base::TimeTicks::Now(); | |
332 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | |
331 } | 333 } |
332 | 334 |
333 void PageLoadTracker::WebContentsShown() { | 335 void PageLoadTracker::WebContentsShown() { |
334 // Only log the first time we foreground in a given page load. | 336 // Only log the first time we foreground in a given page load. |
335 if (foreground_time_.is_null()) { | 337 if (!foreground_time_.is_null()) { |
336 // Make sure we either started in the background and haven't been | 338 return; |
337 // backgrounded yet, or started in the foreground and have already been | |
338 // backgrounded. | |
339 DCHECK_NE(started_in_foreground_, background_time_.is_null()); | |
340 foreground_time_ = base::TimeTicks::Now(); | |
341 } | 339 } |
340 // Make sure we either started in the background and haven't been | |
341 // backgrounded yet, or started in the foreground and have already been | |
342 // backgrounded. | |
343 DCHECK_NE(started_in_foreground_, background_time_.is_null()); | |
344 foreground_time_ = base::TimeTicks::Now(); | |
345 ClampBrowserTimestampIfInterProcessTimeTickSkew(&foreground_time_); | |
342 } | 346 } |
343 | 347 |
344 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { | 348 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { |
345 // TODO(bmcquade): To improve accuracy, consider adding commit time to | 349 // TODO(bmcquade): To improve accuracy, consider adding commit time to |
346 // NavigationHandle. Taking a timestamp here should be close enough for now. | 350 // NavigationHandle. Taking a timestamp here should be close enough for now. |
347 commit_time_ = base::TimeTicks::Now(); | 351 commit_time_ = base::TimeTicks::Now(); |
352 ClampBrowserTimestampIfInterProcessTimeTickSkew(&commit_time_); | |
348 url_ = navigation_handle->GetURL(); | 353 url_ = navigation_handle->GetURL(); |
349 for (const auto& observer : observers_) { | 354 for (const auto& observer : observers_) { |
350 observer->OnCommit(navigation_handle); | 355 observer->OnCommit(navigation_handle); |
351 } | 356 } |
352 LogAbortChainHistograms(navigation_handle); | 357 LogAbortChainHistograms(navigation_handle); |
353 } | 358 } |
354 | 359 |
355 void PageLoadTracker::FailedProvisionalLoad( | 360 void PageLoadTracker::FailedProvisionalLoad( |
356 content::NavigationHandle* navigation_handle) { | 361 content::NavigationHandle* navigation_handle) { |
357 for (const auto& observer : observers_) { | 362 for (const auto& observer : observers_) { |
(...skipping 24 matching lines...) Expand all Loading... | |
382 valid_behavior_descendent) { | 387 valid_behavior_descendent) { |
383 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() | 388 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() |
384 // must be called before DispatchObserverTimingCallbacks, but its | 389 // must be called before DispatchObserverTimingCallbacks, but its |
385 // implementation depends on the state of metadata_, so we need to update | 390 // implementation depends on the state of metadata_, so we need to update |
386 // metadata_ before calling GetPageLoadMetricsInfo. Thus, we make a copy of | 391 // metadata_ before calling GetPageLoadMetricsInfo. Thus, we make a copy of |
387 // timing here, update timing_ and metadata_, and then proceed to dispatch | 392 // timing here, update timing_ and metadata_, and then proceed to dispatch |
388 // the observer timing callbacks. | 393 // the observer timing callbacks. |
389 const PageLoadTiming last_timing = timing_; | 394 const PageLoadTiming last_timing = timing_; |
390 timing_ = new_timing; | 395 timing_ = new_timing; |
391 metadata_ = new_metadata; | 396 metadata_ = new_metadata; |
392 const PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | 397 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
393 for (const auto& observer : observers_) { | 398 for (const auto& observer : observers_) { |
394 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing, | 399 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing, |
395 info); | 400 info); |
396 } | 401 } |
397 return true; | 402 return true; |
398 } | 403 } |
399 return false; | 404 return false; |
400 } | 405 } |
401 | 406 |
402 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { | 407 void PageLoadTracker::set_renderer_tracked(bool renderer_tracked) { |
403 renderer_tracked_ = renderer_tracked; | 408 renderer_tracked_ = renderer_tracked; |
404 } | 409 } |
405 | 410 |
406 void PageLoadTracker::AddObserver( | 411 void PageLoadTracker::AddObserver( |
407 std::unique_ptr<PageLoadMetricsObserver> observer) { | 412 std::unique_ptr<PageLoadMetricsObserver> observer) { |
408 observers_.push_back(std::move(observer)); | 413 observers_.push_back(std::move(observer)); |
409 } | 414 } |
410 | 415 |
411 PageLoadExtraInfo PageLoadTracker::GetPageLoadMetricsInfo() { | 416 void PageLoadTracker::ClampBrowserTimestampIfInterProcessTimeTickSkew( |
412 base::TimeDelta first_background_time; | 417 base::TimeTicks* event_time) { |
413 base::TimeDelta first_foreground_time; | 418 // Windows 10 GCE bot non-deterministically failed because |
Charlie Harrison
2016/05/19 18:20:49
Looks like you can fit more words on this line.
shivanisha
2016/05/23 15:06:43
done
| |
414 base::TimeDelta time_to_abort; | 419 // TimeTicks::Now() called in the browser process e.g. for commit_time |
415 base::TimeDelta time_to_commit; | 420 // was lesser than navigation_start_ that was populated in the renderer |
Charlie Harrison
2016/05/19 18:20:49
s/lesser/less
shivanisha
2016/05/23 15:06:43
done
| |
416 if (!background_time_.is_null()) | 421 // process because the clock was not system-wide monotonic. |
422 | |
423 // TODO (shivanisha) Currently IsHighResolution is the best way to check | |
424 // if the clock is system-wide monotonic. However IsHighResolution | |
425 // does a broader check to see if the clock in use is high resolution | |
426 // which also implies it is system-wide monotonic (on Windows). | |
Charlie Harrison
2016/05/19 18:20:48
Are you sure this check is always correct in findi
shivanisha
2016/05/23 15:06:43
That's how it is currently implemented on Windows.
| |
427 if (base::TimeTicks::IsHighResolution()) { | |
428 return; | |
429 } | |
430 | |
431 if (!event_time->is_null() && *event_time < navigation_start_) { | |
432 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, | |
433 ERR_INTER_PROCESS_TIME_TICK_SKEW, ERR_LAST_ENTRY); | |
434 *event_time = navigation_start_; | |
435 } | |
436 } | |
437 | |
438 PageLoadExtraInfo PageLoadTracker::ComputePageLoadExtraInfo() { | |
439 base::Optional<base::TimeDelta> first_background_time; | |
440 base::Optional<base::TimeDelta> first_foreground_time; | |
441 base::Optional<base::TimeDelta> time_to_abort; | |
442 base::Optional<base::TimeDelta> time_to_commit; | |
443 | |
444 if (!background_time_.is_null()) { | |
445 DCHECK_GE(background_time_, navigation_start_); | |
417 first_background_time = background_time_ - navigation_start_; | 446 first_background_time = background_time_ - navigation_start_; |
418 if (!foreground_time_.is_null()) | 447 } |
448 | |
449 if (!foreground_time_.is_null()) { | |
450 DCHECK_GE(foreground_time_, navigation_start_); | |
419 first_foreground_time = foreground_time_ - navigation_start_; | 451 first_foreground_time = foreground_time_ - navigation_start_; |
452 } | |
453 | |
420 if (abort_type_ != ABORT_NONE) { | 454 if (abort_type_ != ABORT_NONE) { |
421 DCHECK_GT(abort_time_, navigation_start_); | 455 DCHECK_GE(abort_time_, navigation_start_); |
422 time_to_abort = abort_time_ - navigation_start_; | 456 time_to_abort = abort_time_ - navigation_start_; |
423 } else { | 457 } else { |
424 DCHECK(abort_time_.is_null()); | 458 DCHECK(abort_time_.is_null()); |
425 } | 459 } |
426 | 460 |
427 if (!commit_time_.is_null()) { | 461 if (!commit_time_.is_null()) { |
428 DCHECK_GT(commit_time_, navigation_start_); | 462 DCHECK_GE(commit_time_, navigation_start_); |
429 time_to_commit = commit_time_ - navigation_start_; | 463 time_to_commit = commit_time_ - navigation_start_; |
430 } else { | |
431 DCHECK(commit_time_.is_null()); | |
432 } | 464 } |
465 | |
433 return PageLoadExtraInfo( | 466 return PageLoadExtraInfo( |
434 first_background_time, first_foreground_time, started_in_foreground_, | 467 first_background_time, first_foreground_time, started_in_foreground_, |
435 commit_time_.is_null() ? GURL() : url_, time_to_commit, abort_type_, | 468 commit_time_.is_null() ? GURL() : url_, time_to_commit, abort_type_, |
436 time_to_abort, metadata_); | 469 time_to_abort, metadata_); |
437 } | 470 } |
438 | 471 |
439 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, | 472 void PageLoadTracker::NotifyAbort(UserAbortType abort_type, |
440 base::TimeTicks timestamp) { | 473 base::TimeTicks timestamp, |
474 bool is_browser_timetick) { | |
441 DCHECK_NE(abort_type, ABORT_NONE); | 475 DCHECK_NE(abort_type, ABORT_NONE); |
442 // Use UpdateAbort to update an already notified PageLoadTracker. | 476 // Use UpdateAbort to update an already notified PageLoadTracker. |
443 if (abort_type_ != ABORT_NONE) | 477 if (abort_type_ != ABORT_NONE) |
444 return; | 478 return; |
445 | 479 |
446 UpdateAbortInternal(abort_type, timestamp); | 480 UpdateAbortInternal(abort_type, timestamp, is_browser_timetick); |
447 } | 481 } |
448 | 482 |
449 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, | 483 void PageLoadTracker::UpdateAbort(UserAbortType abort_type, |
450 base::TimeTicks timestamp) { | 484 base::TimeTicks timestamp, |
485 bool is_browser_timetick) { | |
451 DCHECK_NE(abort_type, ABORT_NONE); | 486 DCHECK_NE(abort_type, ABORT_NONE); |
452 DCHECK_NE(abort_type, ABORT_OTHER); | 487 DCHECK_NE(abort_type, ABORT_OTHER); |
453 DCHECK_EQ(abort_type_, ABORT_OTHER); | 488 DCHECK_EQ(abort_type_, ABORT_OTHER); |
454 | 489 |
455 // For some aborts (e.g. navigations), the initiated timestamp can be earlier | 490 // For some aborts (e.g. navigations), the initiated timestamp can be earlier |
456 // than the timestamp that aborted the load. Taking the minimum gives the | 491 // than the timestamp that aborted the load. Taking the minimum gives the |
457 // closest user initiated time known. | 492 // closest user initiated time known. |
458 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp)); | 493 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp), |
494 is_browser_timetick); | |
459 } | 495 } |
460 | 496 |
461 bool PageLoadTracker::IsLikelyProvisionalAbort( | 497 bool PageLoadTracker::IsLikelyProvisionalAbort( |
462 base::TimeTicks abort_cause_time) { | 498 base::TimeTicks abort_cause_time) { |
463 // Note that |abort_cause_time - abort_time| can be negative. | 499 // Note that |abort_cause_time - abort_time| can be negative. |
464 return abort_type_ == ABORT_OTHER && | 500 return abort_type_ == ABORT_OTHER && |
465 (abort_cause_time - abort_time_).InMilliseconds() < 100; | 501 (abort_cause_time - abort_time_).InMilliseconds() < 100; |
466 } | 502 } |
467 | 503 |
468 bool PageLoadTracker::MatchesOriginalNavigation( | 504 bool PageLoadTracker::MatchesOriginalNavigation( |
469 content::NavigationHandle* navigation_handle) { | 505 content::NavigationHandle* navigation_handle) { |
470 // Neither navigation should have committed. | 506 // Neither navigation should have committed. |
471 DCHECK(!navigation_handle->HasCommitted()); | 507 DCHECK(!navigation_handle->HasCommitted()); |
472 DCHECK(commit_time_.is_null()); | 508 DCHECK(commit_time_.is_null()); |
473 return navigation_handle->GetURL() == url_; | 509 return navigation_handle->GetURL() == url_; |
474 } | 510 } |
475 | 511 |
476 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, | 512 void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type, |
477 base::TimeTicks timestamp) { | 513 base::TimeTicks timestamp, |
514 bool is_browser_timetick) { | |
478 // When a provisional navigation commits, that navigation's start time is | 515 // When a provisional navigation commits, that navigation's start time is |
479 // interpreted as the abort time for other provisional loads in the tab. | 516 // interpreted as the abort time for other provisional loads in the tab. |
480 // However, this only makes sense if the committed load started after the | 517 // However, this only makes sense if the committed load started after the |
481 // aborted provisional loads started. Thus we ignore cases where the committed | 518 // aborted provisional loads started. Thus we ignore cases where the committed |
482 // load started before the aborted provisional load, as this would result in | 519 // load started before the aborted provisional load, as this would result in |
483 // recording a negative time-to-abort. The real issue here is that we have to | 520 // recording a negative time-to-abort. The real issue here is that we have to |
484 // infer the cause of aborts. It would be better if the navigation code could | 521 // infer the cause of aborts. It would be better if the navigation code could |
485 // instead report the actual cause of an aborted navigation. See crbug/571647 | 522 // instead report the actual cause of an aborted navigation. See crbug/571647 |
486 // for details. | 523 // for details. |
487 if (timestamp <= navigation_start_) { | 524 if (timestamp < navigation_start_) { |
488 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); | 525 RecordInternalError(ERR_ABORT_BEFORE_NAVIGATION_START); |
489 abort_type_ = ABORT_NONE; | 526 abort_type_ = ABORT_NONE; |
490 abort_time_ = base::TimeTicks(); | 527 abort_time_ = base::TimeTicks(); |
491 return; | 528 return; |
492 } | 529 } |
493 abort_type_ = abort_type; | 530 abort_type_ = abort_type; |
494 abort_time_ = timestamp; | 531 abort_time_ = timestamp; |
532 | |
533 if (is_browser_timetick) { | |
534 ClampBrowserTimestampIfInterProcessTimeTickSkew(&abort_time_); | |
535 } | |
495 } | 536 } |
496 | 537 |
497 // static | 538 // static |
498 MetricsWebContentsObserver::MetricsWebContentsObserver( | 539 MetricsWebContentsObserver::MetricsWebContentsObserver( |
499 content::WebContents* web_contents, | 540 content::WebContents* web_contents, |
500 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) | 541 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) |
501 : content::WebContentsObserver(web_contents), | 542 : content::WebContentsObserver(web_contents), |
502 in_foreground_(false), | 543 in_foreground_(false), |
503 embedder_interface_(std::move(embedder_interface)), | 544 embedder_interface_(std::move(embedder_interface)), |
504 has_navigated_(false) {} | 545 has_navigated_(false) {} |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
580 // the MetricsWebContentsObserver owns them both list and they are torn down | 621 // the MetricsWebContentsObserver owns them both list and they are torn down |
581 // after the PageLoadTracker. The PageLoadTracker does not hold on to | 622 // after the PageLoadTracker. The PageLoadTracker does not hold on to |
582 // committed_load_ or navigation_handle beyond the scope of the constructor. | 623 // committed_load_ or navigation_handle beyond the scope of the constructor. |
583 provisional_loads_.insert(std::make_pair( | 624 provisional_loads_.insert(std::make_pair( |
584 navigation_handle, | 625 navigation_handle, |
585 base::WrapUnique(new PageLoadTracker( | 626 base::WrapUnique(new PageLoadTracker( |
586 in_foreground_, embedder_interface_.get(), currently_committed_url, | 627 in_foreground_, embedder_interface_.get(), currently_committed_url, |
587 navigation_handle, chain_size, chain_size_same_url)))); | 628 navigation_handle, chain_size, chain_size_same_url)))); |
588 } | 629 } |
589 | 630 |
631 const PageLoadExtraInfo | |
632 MetricsWebContentsObserver::GetPageLoadExtraInfoCommittedLoad() { | |
633 DCHECK(committed_load_); | |
634 return committed_load_->ComputePageLoadExtraInfo(); | |
635 } | |
636 | |
590 void MetricsWebContentsObserver::DidFinishNavigation( | 637 void MetricsWebContentsObserver::DidFinishNavigation( |
591 content::NavigationHandle* navigation_handle) { | 638 content::NavigationHandle* navigation_handle) { |
592 if (!navigation_handle->IsInMainFrame()) | 639 if (!navigation_handle->IsInMainFrame()) |
593 return; | 640 return; |
594 | 641 |
595 std::unique_ptr<PageLoadTracker> finished_nav( | 642 std::unique_ptr<PageLoadTracker> finished_nav( |
596 std::move(provisional_loads_[navigation_handle])); | 643 std::move(provisional_loads_[navigation_handle])); |
597 provisional_loads_.erase(navigation_handle); | 644 provisional_loads_.erase(navigation_handle); |
598 | 645 |
599 // There's a chance a navigation could have started before we were added to a | 646 // There's a chance a navigation could have started before we were added to a |
(...skipping 12 matching lines...) Expand all Loading... | |
612 net::Error error = navigation_handle->GetNetErrorCode(); | 659 net::Error error = navigation_handle->GetNetErrorCode(); |
613 | 660 |
614 // net::OK: This case occurs when the NavigationHandle finishes and reports | 661 // net::OK: This case occurs when the NavigationHandle finishes and reports |
615 // !HasCommitted(), but reports no net::Error. This should not occur | 662 // !HasCommitted(), but reports no net::Error. This should not occur |
616 // pre-PlzNavigate, but afterwards it should represent the navigation | 663 // pre-PlzNavigate, but afterwards it should represent the navigation |
617 // stopped by the user before it was ready to commit. | 664 // stopped by the user before it was ready to commit. |
618 // net::ERR_ABORTED: An aborted provisional load has error net::ERR_ABORTED. | 665 // net::ERR_ABORTED: An aborted provisional load has error net::ERR_ABORTED. |
619 // Note that this can come from some non user-initiated errors, such as | 666 // Note that this can come from some non user-initiated errors, such as |
620 // downloads, or 204 responses. See crbug.com/542369. | 667 // downloads, or 204 responses. See crbug.com/542369. |
621 if ((error == net::OK) || (error == net::ERR_ABORTED)) { | 668 if ((error == net::OK) || (error == net::ERR_ABORTED)) { |
622 finished_nav->NotifyAbort(ABORT_OTHER, base::TimeTicks::Now()); | 669 finished_nav->NotifyAbort(ABORT_OTHER, base::TimeTicks::Now(), true); |
623 aborted_provisional_loads_.push_back(std::move(finished_nav)); | 670 aborted_provisional_loads_.push_back(std::move(finished_nav)); |
624 } | 671 } |
625 | 672 |
626 return; | 673 return; |
627 } | 674 } |
628 | 675 |
629 // Don't treat a same-page nav as a new page load. | 676 // Don't treat a same-page nav as a new page load. |
630 if (navigation_handle->IsSamePage()) | 677 if (navigation_handle->IsSamePage()) |
631 return; | 678 return; |
632 | 679 |
633 // Notify other loads that they may have been aborted by this committed load. | 680 // Notify other loads that they may have been aborted by this committed load. |
634 // Note that by using the committed navigation start as the abort cause, we | 681 // Note that by using the committed navigation start as the abort cause, we |
635 // lose data on provisional loads that were aborted by other provisional | 682 // lose data on provisional loads that were aborted by other provisional |
636 // loads. Those will either be listed as ABORT_OTHER or as being aborted by | 683 // loads. Those will either be listed as ABORT_OTHER or as being aborted by |
637 // this load. | 684 // this load. |
638 NotifyAbortAllLoadsWithTimestamp( | 685 NotifyAbortAllLoadsWithTimestamp( |
639 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), | 686 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), |
640 navigation_handle->NavigationStart()); | 687 navigation_handle->NavigationStart(), false); |
641 | 688 |
642 committed_load_ = std::move(finished_nav); | 689 committed_load_ = std::move(finished_nav); |
643 aborted_provisional_loads_.clear(); | 690 aborted_provisional_loads_.clear(); |
644 | 691 |
645 const GURL& browser_url = web_contents()->GetLastCommittedURL(); | 692 const GURL& browser_url = web_contents()->GetLastCommittedURL(); |
646 const std::string& mime_type = web_contents()->GetContentsMimeType(); | 693 const std::string& mime_type = web_contents()->GetContentsMimeType(); |
647 DCHECK(!browser_url.is_empty()); | 694 DCHECK(!browser_url.is_empty()); |
648 DCHECK(!mime_type.empty()); | 695 DCHECK(!mime_type.empty()); |
649 committed_load_->set_renderer_tracked( | 696 committed_load_->set_renderer_tracked( |
650 IsRelevantNavigation(navigation_handle, browser_url, mime_type)); | 697 IsRelevantNavigation(navigation_handle, browser_url, mime_type)); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
703 } | 750 } |
704 | 751 |
705 // If this is a crash, eagerly log the aborted provisional loads and the | 752 // If this is a crash, eagerly log the aborted provisional loads and the |
706 // committed load. |provisional_loads_| don't need to be destroyed here | 753 // committed load. |provisional_loads_| don't need to be destroyed here |
707 // because their lifetime is tied to the NavigationHandle. | 754 // because their lifetime is tied to the NavigationHandle. |
708 committed_load_.reset(); | 755 committed_load_.reset(); |
709 aborted_provisional_loads_.clear(); | 756 aborted_provisional_loads_.clear(); |
710 } | 757 } |
711 | 758 |
712 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { | 759 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { |
713 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now()); | 760 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now(), true); |
714 } | 761 } |
715 | 762 |
716 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( | 763 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( |
717 UserAbortType abort_type, | 764 UserAbortType abort_type, |
718 base::TimeTicks timestamp) { | 765 base::TimeTicks timestamp, |
766 bool is_browser_timetick) { | |
719 if (committed_load_) | 767 if (committed_load_) |
720 committed_load_->NotifyAbort(abort_type, timestamp); | 768 committed_load_->NotifyAbort(abort_type, timestamp, is_browser_timetick); |
721 for (const auto& kv : provisional_loads_) { | 769 for (const auto& kv : provisional_loads_) { |
722 kv.second->NotifyAbort(abort_type, timestamp); | 770 kv.second->NotifyAbort(abort_type, timestamp, is_browser_timetick); |
723 } | 771 } |
724 for (const auto& tracker : aborted_provisional_loads_) { | 772 for (const auto& tracker : aborted_provisional_loads_) { |
725 if (tracker->IsLikelyProvisionalAbort(timestamp)) | 773 if (tracker->IsLikelyProvisionalAbort(timestamp)) |
726 tracker->UpdateAbort(abort_type, timestamp); | 774 tracker->UpdateAbort(abort_type, timestamp, is_browser_timetick); |
727 } | 775 } |
728 aborted_provisional_loads_.clear(); | 776 aborted_provisional_loads_.clear(); |
729 } | 777 } |
730 | 778 |
731 std::unique_ptr<PageLoadTracker> | 779 std::unique_ptr<PageLoadTracker> |
732 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( | 780 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( |
733 content::NavigationHandle* new_navigation) { | 781 content::NavigationHandle* new_navigation) { |
734 // If there are multiple aborted loads that can be attributed to this one, | 782 // If there are multiple aborted loads that can be attributed to this one, |
735 // just count the latest one for simplicity. Other loads will fall into the | 783 // just count the latest one for simplicity. Other loads will fall into the |
736 // OTHER bucket, though there shouldn't be very many. | 784 // OTHER bucket, though there shouldn't be very many. |
737 if (aborted_provisional_loads_.size() == 0) | 785 if (aborted_provisional_loads_.size() == 0) |
738 return nullptr; | 786 return nullptr; |
739 if (aborted_provisional_loads_.size() > 1) | 787 if (aborted_provisional_loads_.size() > 1) |
740 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); | 788 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); |
741 | 789 |
742 std::unique_ptr<PageLoadTracker> last_aborted_load = | 790 std::unique_ptr<PageLoadTracker> last_aborted_load = |
743 std::move(aborted_provisional_loads_.back()); | 791 std::move(aborted_provisional_loads_.back()); |
744 aborted_provisional_loads_.pop_back(); | 792 aborted_provisional_loads_.pop_back(); |
745 | 793 |
746 base::TimeTicks timestamp = new_navigation->NavigationStart(); | 794 base::TimeTicks timestamp = new_navigation->NavigationStart(); |
747 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) | 795 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) |
748 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp); | 796 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp, false); |
749 | 797 |
750 aborted_provisional_loads_.clear(); | 798 aborted_provisional_loads_.clear(); |
751 return last_aborted_load; | 799 return last_aborted_load; |
752 } | 800 } |
753 | 801 |
754 void MetricsWebContentsObserver::OnTimingUpdated( | 802 void MetricsWebContentsObserver::OnTimingUpdated( |
755 content::RenderFrameHost* render_frame_host, | 803 content::RenderFrameHost* render_frame_host, |
756 const PageLoadTiming& timing, | 804 const PageLoadTiming& timing, |
757 const PageLoadMetadata& metadata) { | 805 const PageLoadMetadata& metadata) { |
758 bool error = false; | 806 bool error = false; |
(...skipping 22 matching lines...) Expand all Loading... | |
781 | 829 |
782 if (!committed_load_->UpdateTiming(timing, metadata)) { | 830 if (!committed_load_->UpdateTiming(timing, metadata)) { |
783 // If the page load tracker cannot update its timing, something is wrong | 831 // If the page load tracker cannot update its timing, something is wrong |
784 // with the IPC (it's from another load, or it's invalid in some other way). | 832 // with the IPC (it's from another load, or it's invalid in some other way). |
785 // We expect this to be a rare occurrence. | 833 // We expect this to be a rare occurrence. |
786 RecordInternalError(ERR_BAD_TIMING_IPC); | 834 RecordInternalError(ERR_BAD_TIMING_IPC); |
787 } | 835 } |
788 } | 836 } |
789 | 837 |
790 } // namespace page_load_metrics | 838 } // namespace page_load_metrics |
OLD | NEW |