Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(577)

Side by Side Diff: chrome/browser/page_load_metrics/page_load_tracker.cc

Issue 2804093002: Various page_load_metrics cleanups and improvements (Closed)
Patch Set: fix tests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/page_load_metrics/page_load_tracker.h" 5 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <ostream> 8 #include <ostream>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "chrome/browser/page_load_metrics/page_load_metrics_embedder_interface. h" 15 #include "chrome/browser/page_load_metrics/page_load_metrics_embedder_interface. h"
16 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" 16 #include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
17 #include "chrome/browser/prerender/prerender_contents.h"
17 #include "chrome/common/page_load_metrics/page_load_timing.h" 18 #include "chrome/common/page_load_metrics/page_load_timing.h"
18 #include "content/public/browser/navigation_details.h" 19 #include "content/public/browser/navigation_details.h"
19 #include "content/public/browser/navigation_handle.h" 20 #include "content/public/browser/navigation_handle.h"
20 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
21 #include "content/public/browser/web_contents_observer.h" 22 #include "content/public/browser/web_contents_observer.h"
22 #include "content/public/common/browser_side_navigation_policy.h" 23 #include "content/public/common/browser_side_navigation_policy.h"
23 #include "ui/base/page_transition_types.h" 24 #include "ui/base/page_transition_types.h"
24 25
25 // This macro invokes the specified method on each observer, passing the 26 // This macro invokes the specified method on each observer, passing the
26 // variable length arguments as the method's arguments, and removes the observer 27 // variable length arguments as the method's arguments, and removes the observer
(...skipping 22 matching lines...) Expand all
49 const char kAbortChainSizeSameURL[] = 50 const char kAbortChainSizeSameURL[] =
50 "PageLoad.Internal.ProvisionalAbortChainSize.SameURL"; 51 "PageLoad.Internal.ProvisionalAbortChainSize.SameURL";
51 const char kAbortChainSizeNoCommit[] = 52 const char kAbortChainSizeNoCommit[] =
52 "PageLoad.Internal.ProvisionalAbortChainSize.NoCommit"; 53 "PageLoad.Internal.ProvisionalAbortChainSize.NoCommit";
53 const char kClientRedirectFirstPaintToNavigation[] = 54 const char kClientRedirectFirstPaintToNavigation[] =
54 "PageLoad.Internal.ClientRedirect.FirstPaintToNavigation"; 55 "PageLoad.Internal.ClientRedirect.FirstPaintToNavigation";
55 const char kClientRedirectWithoutPaint[] = 56 const char kClientRedirectWithoutPaint[] =
56 "PageLoad.Internal.ClientRedirect.NavigationWithoutPaint"; 57 "PageLoad.Internal.ClientRedirect.NavigationWithoutPaint";
57 const char kPageLoadCompletedAfterAppBackground[] = 58 const char kPageLoadCompletedAfterAppBackground[] =
58 "PageLoad.Internal.PageLoadCompleted.AfterAppBackground"; 59 "PageLoad.Internal.PageLoadCompleted.AfterAppBackground";
60 const char kPageLoadStartedInForeground[] =
61 "PageLoad.Internal.NavigationStartedInForeground";
62 const char kPageLoadPrerender[] = "PageLoad.Internal.Prerender";
59 63
60 } // namespace internal 64 } // namespace internal
61 65
62 void RecordInternalError(InternalErrorLoadEvent event) { 66 void RecordInternalError(InternalErrorLoadEvent event) {
63 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY); 67 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY);
64 } 68 }
65 69
66 // TODO(csharrison): Add a case for client side redirects, which is what JS 70 // TODO(csharrison): Add a case for client side redirects, which is what JS
67 // initiated window.location / window.history navigations get set to. 71 // initiated window.location / window.history navigations get set to.
68 PageEndReason EndReasonForPageTransition(ui::PageTransition transition) { 72 PageEndReason EndReasonForPageTransition(ui::PageTransition transition) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 132
129 // If we have a non-empty timing, it should always have a navigation start. 133 // If we have a non-empty timing, it should always have a navigation start.
130 if (timing.navigation_start.is_null()) { 134 if (timing.navigation_start.is_null()) {
131 NOTREACHED() << "Received null navigation_start."; 135 NOTREACHED() << "Received null navigation_start.";
132 return false; 136 return false;
133 } 137 }
134 138
135 // Verify proper ordering between the various timings. 139 // Verify proper ordering between the various timings.
136 140
137 if (!EventsInOrder(timing.response_start, timing.parse_start)) { 141 if (!EventsInOrder(timing.response_start, timing.parse_start)) {
138 // We sometimes get a zero response_start with a non-zero parse start. See 142 NOTREACHED() << "Invalid response_start " << timing.response_start
139 // crbug.com/590212. 143 << " for parse_start " << timing.parse_start;
140 DLOG(ERROR) << "Invalid response_start " << timing.response_start
141 << " for parse_start " << timing.parse_start;
142 return false; 144 return false;
143 } 145 }
144 146
145 if (!EventsInOrder(timing.parse_start, timing.parse_stop)) { 147 if (!EventsInOrder(timing.parse_start, timing.parse_stop)) {
146 NOTREACHED() << "Invalid parse_start " << timing.parse_start 148 NOTREACHED() << "Invalid parse_start " << timing.parse_start
147 << " for parse_stop " << timing.parse_stop; 149 << " for parse_stop " << timing.parse_stop;
148 return false; 150 return false;
149 } 151 }
150 152
151 if (timing.parse_stop) { 153 if (timing.parse_stop) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 started_in_foreground_(in_foreground), 306 started_in_foreground_(in_foreground),
305 page_transition_(navigation_handle->GetPageTransition()), 307 page_transition_(navigation_handle->GetPageTransition()),
306 user_initiated_info_(user_initiated_info), 308 user_initiated_info_(user_initiated_info),
307 aborted_chain_size_(aborted_chain_size), 309 aborted_chain_size_(aborted_chain_size),
308 aborted_chain_size_same_url_(aborted_chain_size_same_url), 310 aborted_chain_size_same_url_(aborted_chain_size_same_url),
309 embedder_interface_(embedder_interface) { 311 embedder_interface_(embedder_interface) {
310 DCHECK(!navigation_handle->HasCommitted()); 312 DCHECK(!navigation_handle->HasCommitted());
311 embedder_interface_->RegisterObservers(this); 313 embedder_interface_->RegisterObservers(this);
312 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, 314 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle,
313 currently_committed_url, started_in_foreground_); 315 currently_committed_url, started_in_foreground_);
316
317 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadStartedInForeground,
318 started_in_foreground_);
319 const bool is_prerender = prerender::PrerenderContents::FromWebContents(
320 navigation_handle->GetWebContents()) != nullptr;
321 if (is_prerender) {
322 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadPrerender, true);
323 }
314 } 324 }
315 325
316 PageLoadTracker::~PageLoadTracker() { 326 PageLoadTracker::~PageLoadTracker() {
317 if (app_entered_background_) { 327 if (app_entered_background_) {
318 RecordAppBackgroundPageLoadCompleted(true); 328 RecordAppBackgroundPageLoadCompleted(true);
319 } 329 }
320 330
321 if (did_stop_tracking_) 331 if (did_stop_tracking_)
322 return; 332 return;
323 333
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 child_frame_metadata_.behavior_flags |= child_metadata.behavior_flags; 530 child_frame_metadata_.behavior_flags |= child_metadata.behavior_flags;
521 if (last_child_loading_behavior_flags == child_frame_metadata_.behavior_flags) 531 if (last_child_loading_behavior_flags == child_frame_metadata_.behavior_flags)
522 return; 532 return;
523 533
524 PageLoadExtraInfo extra_info(ComputePageLoadExtraInfo()); 534 PageLoadExtraInfo extra_info(ComputePageLoadExtraInfo());
525 for (const auto& observer : observers_) { 535 for (const auto& observer : observers_) {
526 observer->OnLoadingBehaviorObserved(extra_info); 536 observer->OnLoadingBehaviorObserved(extra_info);
527 } 537 }
528 } 538 }
529 539
530 bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing, 540 void PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing,
531 const PageLoadMetadata& new_metadata) { 541 const PageLoadMetadata& new_metadata) {
532 // Throw away IPCs that are not relevant to the current navigation. 542 // Throw away IPCs that are not relevant to the current navigation.
533 // Two timing structures cannot refer to the same navigation if they indicate 543 // Two timing structures cannot refer to the same navigation if they indicate
534 // that a navigation started at different times, so a new timing struct with a 544 // that a navigation started at different times, so a new timing struct with a
535 // different start time from an earlier struct is considered invalid. 545 // different start time from an earlier struct is considered invalid.
536 bool valid_timing_descendent = 546 const bool valid_timing_descendent =
537 timing_.navigation_start.is_null() || 547 timing_.navigation_start.is_null() ||
538 timing_.navigation_start == new_timing.navigation_start; 548 timing_.navigation_start == new_timing.navigation_start;
549 if (!valid_timing_descendent) {
550 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT);
551 return;
552 }
553
539 // Ensure flags sent previously are still present in the new metadata fields. 554 // Ensure flags sent previously are still present in the new metadata fields.
540 bool valid_behavior_descendent = 555 const bool valid_behavior_descendent =
541 (main_frame_metadata_.behavior_flags & new_metadata.behavior_flags) == 556 (main_frame_metadata_.behavior_flags & new_metadata.behavior_flags) ==
542 main_frame_metadata_.behavior_flags; 557 main_frame_metadata_.behavior_flags;
543 if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent && 558 if (!valid_behavior_descendent) {
544 valid_behavior_descendent) { 559 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_BEHAVIOR_DESCENDENT);
545 DCHECK(did_commit_); // OnCommit() must be called first. 560 return;
546 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() 561 }
547 // must be called before DispatchObserverTimingCallbacks, but its 562 if (!IsValidPageLoadTiming(new_timing)) {
548 // implementation depends on the state of main_frame_metadata_, so we need 563 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING);
549 // to update main_frame_metadata_ before calling GetPageLoadMetricsInfo. 564 return;
550 // Thus, we make a copy of timing here, update timing_ and 565 }
551 // main_frame_metadata_, and then proceed to dispatch the observer timing
552 // callbacks.
553 const PageLoadTiming last_timing = timing_;
554 timing_ = new_timing;
555 566
556 const PageLoadMetadata last_metadata = main_frame_metadata_; 567 DCHECK(did_commit_); // OnCommit() must be called first.
557 main_frame_metadata_ = new_metadata; 568 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo()
558 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); 569 // must be called before DispatchObserverTimingCallbacks, but its
559 for (const auto& observer : observers_) { 570 // implementation depends on the state of main_frame_metadata_, so we need
560 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing, 571 // to update main_frame_metadata_ before calling GetPageLoadMetricsInfo.
561 last_metadata, info); 572 // Thus, we make a copy of timing here, update timing_ and
562 } 573 // main_frame_metadata_, and then proceed to dispatch the observer timing
563 return true; 574 // callbacks.
575 const PageLoadTiming last_timing = timing_;
576 timing_ = new_timing;
577
578 const PageLoadMetadata last_metadata = main_frame_metadata_;
579 main_frame_metadata_ = new_metadata;
580 const PageLoadExtraInfo info = ComputePageLoadExtraInfo();
581 for (const auto& observer : observers_) {
582 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing,
583 last_metadata, info);
564 } 584 }
565 return false;
566 } 585 }
567 586
568 void PageLoadTracker::OnLoadedResource( 587 void PageLoadTracker::OnLoadedResource(
569 const ExtraRequestInfo& extra_request_info) { 588 const ExtraRequestInfo& extra_request_info) {
570 for (const auto& observer : observers_) { 589 for (const auto& observer : observers_) {
571 observer->OnLoadedResource(extra_request_info); 590 observer->OnLoadedResource(extra_request_info);
572 } 591 }
573 } 592 }
574 593
575 void PageLoadTracker::StopTracking() { 594 void PageLoadTracker::StopTracking() {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 } 756 }
738 757
739 void PageLoadTracker::MediaStartedPlaying( 758 void PageLoadTracker::MediaStartedPlaying(
740 const content::WebContentsObserver::MediaPlayerInfo& video_type, 759 const content::WebContentsObserver::MediaPlayerInfo& video_type,
741 bool is_in_main_frame) { 760 bool is_in_main_frame) {
742 for (const auto& observer : observers_) 761 for (const auto& observer : observers_)
743 observer->MediaStartedPlaying(video_type, is_in_main_frame); 762 observer->MediaStartedPlaying(video_type, is_in_main_frame);
744 } 763 }
745 764
746 } // namespace page_load_metrics 765 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698