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 "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_
observer.h" | 5 #include "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_
observer.h" |
6 #include <string> | 6 #include <string> |
7 | 7 |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "components/page_load_metrics/browser/page_load_metrics_util.h" | 10 #include "components/page_load_metrics/browser/page_load_metrics_util.h" |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 385 |
386 void FromGWSPageLoadMetricsLogger::SetPreviouslyCommittedUrl(const GURL& url) { | 386 void FromGWSPageLoadMetricsLogger::SetPreviouslyCommittedUrl(const GURL& url) { |
387 previously_committed_url_is_search_results_ = IsGoogleSearchResultUrl(url); | 387 previously_committed_url_is_search_results_ = IsGoogleSearchResultUrl(url); |
388 previously_committed_url_is_search_redirector_ = | 388 previously_committed_url_is_search_redirector_ = |
389 IsGoogleSearchRedirectorUrl(url); | 389 IsGoogleSearchRedirectorUrl(url); |
390 } | 390 } |
391 | 391 |
392 void FromGWSPageLoadMetricsLogger::SetProvisionalUrl(const GURL& url) { | 392 void FromGWSPageLoadMetricsLogger::SetProvisionalUrl(const GURL& url) { |
393 provisional_url_has_search_hostname_ = | 393 provisional_url_has_search_hostname_ = |
394 IsGoogleSearchHostname(url.host_piece()); | 394 IsGoogleSearchHostname(url.host_piece()); |
395 provisional_url_is_non_http_or_https_ = !url.SchemeIsHTTPOrHTTPS(); | |
396 } | 395 } |
397 | 396 |
398 FromGWSPageLoadMetricsObserver::FromGWSPageLoadMetricsObserver() {} | 397 FromGWSPageLoadMetricsObserver::FromGWSPageLoadMetricsObserver() {} |
399 | 398 |
400 void FromGWSPageLoadMetricsObserver::OnStart( | 399 void FromGWSPageLoadMetricsObserver::OnStart( |
401 content::NavigationHandle* navigation_handle, | 400 content::NavigationHandle* navigation_handle, |
402 const GURL& currently_committed_url, | 401 const GURL& currently_committed_url, |
403 bool started_in_foreground) { | 402 bool started_in_foreground) { |
404 logger_.SetPreviouslyCommittedUrl(currently_committed_url); | 403 logger_.SetPreviouslyCommittedUrl(currently_committed_url); |
405 logger_.SetProvisionalUrl(navigation_handle->GetURL()); | 404 logger_.SetProvisionalUrl(navigation_handle->GetURL()); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 const page_load_metrics::PageLoadExtraInfo& extra_info) { | 468 const page_load_metrics::PageLoadExtraInfo& extra_info) { |
470 logger_.OnParseStop(timing, extra_info); | 469 logger_.OnParseStop(timing, extra_info); |
471 } | 470 } |
472 | 471 |
473 void FromGWSPageLoadMetricsObserver::OnComplete( | 472 void FromGWSPageLoadMetricsObserver::OnComplete( |
474 const page_load_metrics::PageLoadTiming& timing, | 473 const page_load_metrics::PageLoadTiming& timing, |
475 const page_load_metrics::PageLoadExtraInfo& extra_info) { | 474 const page_load_metrics::PageLoadExtraInfo& extra_info) { |
476 logger_.OnComplete(timing, extra_info); | 475 logger_.OnComplete(timing, extra_info); |
477 } | 476 } |
478 | 477 |
| 478 void FromGWSPageLoadMetricsObserver::OnFailedProvisionalLoad( |
| 479 const page_load_metrics::FailedProvisionalLoadInfo& failed_load_info, |
| 480 const page_load_metrics::PageLoadExtraInfo& extra_info) { |
| 481 logger_.OnFailedProvisionalLoad(failed_load_info, extra_info); |
| 482 } |
| 483 |
479 void FromGWSPageLoadMetricsObserver::OnUserInput( | 484 void FromGWSPageLoadMetricsObserver::OnUserInput( |
480 const blink::WebInputEvent& event) { | 485 const blink::WebInputEvent& event) { |
481 logger_.OnUserInput(event); | 486 logger_.OnUserInput(event); |
482 } | 487 } |
483 | 488 |
484 void FromGWSPageLoadMetricsLogger::OnComplete( | 489 void FromGWSPageLoadMetricsLogger::OnComplete( |
485 const page_load_metrics::PageLoadTiming& timing, | 490 const page_load_metrics::PageLoadTiming& timing, |
486 const page_load_metrics::PageLoadExtraInfo& extra_info) { | 491 const page_load_metrics::PageLoadExtraInfo& extra_info) { |
487 if (!ShouldLogMetrics(extra_info.committed_url)) | 492 if (!ShouldLogPostCommitMetrics(extra_info.committed_url)) |
488 return; | 493 return; |
489 | 494 |
490 // If we have a committed load but |timing.IsEmpty()|, then this load was not | |
491 // tracked by the renderer. In this case, it is not possible to know whether | |
492 // the abort signals came before the page painted. Additionally, for | |
493 // consistency with core PageLoad metrics, we ignore non-render-tracked | |
494 // loads when tracking aborts after commit. | |
495 UserAbortType abort_type = extra_info.abort_type; | 495 UserAbortType abort_type = extra_info.abort_type; |
496 if (!WasAbortedInForeground(abort_type, extra_info.time_to_abort, extra_info)) | 496 if (!WasAbortedInForeground(abort_type, extra_info.time_to_abort, extra_info)) |
497 return; | 497 return; |
498 | 498 |
499 base::TimeDelta time_to_abort = extra_info.time_to_abort.value(); | 499 // If we did not receive any timing IPCs from the render process, we can't |
500 if (extra_info.committed_url.is_empty()) { | 500 // know for certain if the page was truly aborted before paint, or if the |
501 LogProvisionalAborts(abort_type, time_to_abort); | 501 // abort happened before we received the IPC from the render process. Thus, we |
502 return; | 502 // do not log aborts for these page loads. Tracked page loads that receive no |
503 } | 503 // timing IPCs are tracked via the ERR_NO_IPCS_RECEIVED error code in the |
504 | 504 // PageLoad.Events.InternalError histogram, so we can keep track of how often |
505 // If we didn't receive any timing data but did commit, this is likely not a | 505 // this happens. |
506 // renderer-tracked navigation, so ignore it. | |
507 if (timing.IsEmpty()) | 506 if (timing.IsEmpty()) |
508 return; | 507 return; |
509 | 508 |
| 509 base::TimeDelta time_to_abort = extra_info.time_to_abort.value(); |
510 if (!timing.first_paint || timing.first_paint >= time_to_abort) { | 510 if (!timing.first_paint || timing.first_paint >= time_to_abort) { |
511 LogCommittedAbortsBeforePaint(abort_type, time_to_abort); | 511 LogCommittedAbortsBeforePaint(abort_type, time_to_abort); |
512 } else if (WasAbortedBeforeInteraction(abort_type, | 512 } else if (WasAbortedBeforeInteraction(abort_type, |
513 first_user_interaction_after_paint_, | 513 first_user_interaction_after_paint_, |
514 extra_info.time_to_abort)) { | 514 extra_info.time_to_abort)) { |
515 LogAbortsAfterPaintBeforeInteraction(abort_type, time_to_abort); | 515 LogAbortsAfterPaintBeforeInteraction(abort_type, time_to_abort); |
516 } | 516 } |
517 } | 517 } |
518 | 518 |
519 bool FromGWSPageLoadMetricsLogger::ShouldLogMetrics(const GURL& committed_url) { | 519 void FromGWSPageLoadMetricsLogger::OnFailedProvisionalLoad( |
| 520 const page_load_metrics::FailedProvisionalLoadInfo& failed_load_info, |
| 521 const page_load_metrics::PageLoadExtraInfo& extra_info) { |
| 522 if (!ShouldLogFailedProvisionalLoadMetrics()) |
| 523 return; |
| 524 |
| 525 UserAbortType abort_type = extra_info.abort_type; |
| 526 if (!WasAbortedInForeground(abort_type, extra_info.time_to_abort, extra_info)) |
| 527 return; |
| 528 |
| 529 LogProvisionalAborts(abort_type, extra_info.time_to_abort.value()); |
| 530 } |
| 531 |
| 532 bool FromGWSPageLoadMetricsLogger::ShouldLogFailedProvisionalLoadMetrics() { |
| 533 // See comment in ShouldLogPostCommitMetrics above the call to |
| 534 // IsGoogleSearchHostname for more info on this if test. |
| 535 if (provisional_url_has_search_hostname_) |
| 536 return false; |
| 537 |
| 538 return previously_committed_url_is_search_results_ || |
| 539 previously_committed_url_is_search_redirector_; |
| 540 } |
| 541 |
| 542 bool FromGWSPageLoadMetricsLogger::ShouldLogPostCommitMetrics( |
| 543 const GURL& committed_url) { |
| 544 DCHECK(!committed_url.is_empty()); |
| 545 |
520 // If this page has a URL on a known google search hostname, then it may be a | 546 // If this page has a URL on a known google search hostname, then it may be a |
521 // page associated with search (either a search results page, or a search | 547 // page associated with search (either a search results page, or a search |
522 // redirector url), so we should not log stats. We could try to detect only | 548 // redirector url), so we should not log stats. We could try to detect only |
523 // the specific known search URLs here, and log navigations to other pages on | 549 // the specific known search URLs here, and log navigations to other pages on |
524 // the google search hostname (for example, a search for 'about google' | 550 // the google search hostname (for example, a search for 'about google' |
525 // includes a result for https://www.google.com/about/), however, we assume | 551 // includes a result for https://www.google.com/about/), however, we assume |
526 // these cases are relatively uncommon, and we run the risk of logging metrics | 552 // these cases are relatively uncommon, and we run the risk of logging metrics |
527 // for some search redirector URLs. Thus we choose the more conservative | 553 // for some search redirector URLs. Thus we choose the more conservative |
528 // approach of ignoring all urls on known search hostnames. We use the | 554 // approach of ignoring all urls on known search hostnames. |
529 // provisional url if the navigation didn't commit. Also ignore navigations to | 555 if (IsGoogleSearchHostname(committed_url.host_piece())) |
530 // other URL schemes, such as app navigations via intent://. | 556 return false; |
531 if (committed_url.is_empty()) { | |
532 if (provisional_url_has_search_hostname_ || | |
533 provisional_url_is_non_http_or_https_) | |
534 return false; | |
535 } else { | |
536 if (IsGoogleSearchHostname(committed_url.host_piece()) || | |
537 !committed_url.SchemeIsHTTPOrHTTPS()) | |
538 return false; | |
539 } | |
540 | 557 |
541 // We're only interested in tracking navigations (e.g. clicks) initiated via | 558 // We're only interested in tracking navigations (e.g. clicks) initiated via |
542 // links. Note that the redirector will mask these, so don't enforce this if | 559 // links. Note that the redirector will mask these, so don't enforce this if |
543 // the navigation came from a redirect url. TODO(csharrison): Use this signal | 560 // the navigation came from a redirect url. TODO(csharrison): Use this signal |
544 // for provisional loads when the content APIs allow for it. | 561 // for provisional loads when the content APIs allow for it. |
545 if (previously_committed_url_is_search_results_ && | 562 if (previously_committed_url_is_search_results_ && |
546 (committed_url.is_empty() || navigation_initiated_via_link_)) { | 563 navigation_initiated_via_link_) { |
547 return true; | 564 return true; |
548 } | 565 } |
549 | 566 |
550 // If the navigation was via the search redirector, then the information about | 567 // If the navigation was via the search redirector, then the information about |
551 // whether the navigation was from a link would have been associated with the | 568 // whether the navigation was from a link would have been associated with the |
552 // navigation to the redirector, and not included in the redirected | 569 // navigation to the redirector, and not included in the redirected |
553 // navigation. Therefore, do not require link navigation this case. | 570 // navigation. Therefore, do not require link navigation this case. |
554 return previously_committed_url_is_search_redirector_; | 571 return previously_committed_url_is_search_redirector_; |
555 } | 572 } |
556 | 573 |
557 bool FromGWSPageLoadMetricsLogger::ShouldLogForegroundEventAfterCommit( | 574 bool FromGWSPageLoadMetricsLogger::ShouldLogForegroundEventAfterCommit( |
558 const base::Optional<base::TimeDelta>& event, | 575 const base::Optional<base::TimeDelta>& event, |
559 const page_load_metrics::PageLoadExtraInfo& info) { | 576 const page_load_metrics::PageLoadExtraInfo& info) { |
560 DCHECK(!info.committed_url.is_empty()) | 577 DCHECK(!info.committed_url.is_empty()) |
561 << "ShouldLogForegroundEventAfterCommit called without committed URL."; | 578 << "ShouldLogForegroundEventAfterCommit called without committed URL."; |
562 return ShouldLogMetrics(info.committed_url) && | 579 return ShouldLogPostCommitMetrics(info.committed_url) && |
563 WasStartedInForegroundOptionalEventInForeground(event, info); | 580 WasStartedInForegroundOptionalEventInForeground(event, info); |
564 } | 581 } |
565 | 582 |
566 void FromGWSPageLoadMetricsLogger::OnDomContentLoadedEventStart( | 583 void FromGWSPageLoadMetricsLogger::OnDomContentLoadedEventStart( |
567 const page_load_metrics::PageLoadTiming& timing, | 584 const page_load_metrics::PageLoadTiming& timing, |
568 const page_load_metrics::PageLoadExtraInfo& extra_info) { | 585 const page_load_metrics::PageLoadExtraInfo& extra_info) { |
569 if (ShouldLogForegroundEventAfterCommit(timing.dom_content_loaded_event_start, | 586 if (ShouldLogForegroundEventAfterCommit(timing.dom_content_loaded_event_start, |
570 extra_info)) { | 587 extra_info)) { |
571 PAGE_LOAD_HISTOGRAM(internal::kHistogramFromGWSDomContentLoaded, | 588 PAGE_LOAD_HISTOGRAM(internal::kHistogramFromGWSDomContentLoaded, |
572 timing.dom_content_loaded_event_start.value()); | 589 timing.dom_content_loaded_event_start.value()); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 } | 667 } |
651 | 668 |
652 void FromGWSPageLoadMetricsLogger::OnUserInput( | 669 void FromGWSPageLoadMetricsLogger::OnUserInput( |
653 const blink::WebInputEvent& event) { | 670 const blink::WebInputEvent& event) { |
654 if (first_paint_triggered_ && !first_user_interaction_after_paint_) { | 671 if (first_paint_triggered_ && !first_user_interaction_after_paint_) { |
655 DCHECK(!navigation_start_.is_null()); | 672 DCHECK(!navigation_start_.is_null()); |
656 first_user_interaction_after_paint_ = | 673 first_user_interaction_after_paint_ = |
657 base::TimeTicks::Now() - navigation_start_; | 674 base::TimeTicks::Now() - navigation_start_; |
658 } | 675 } |
659 } | 676 } |
OLD | NEW |