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