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

Side by Side Diff: components/page_load_metrics/browser/page_load_metrics_web_contents_observer.cc

Issue 1312213010: PageLoadMetrics renderer and browser implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Instrumented NavigationHandle for IsSamePage, fixed broken logic and tests Created 5 years, 3 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/page_load_metrics/browser/page_load_metrics_web_contents_ob server.h"
6
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "components/page_load_metrics/common/page_load_metrics_messages.h"
10 #include "components/page_load_metrics/common/page_load_timing.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/navigation_details.h"
13 #include "content/public/browser/navigation_handle.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_contents_observer.h"
17 #include "content/public/browser/web_contents_user_data.h"
18 #include "ipc/ipc_message.h"
19 #include "ipc/ipc_message_macros.h"
20
21 DEFINE_WEB_CONTENTS_USER_DATA_KEY(page_load_metrics::WebContentsObserver);
22
23 namespace page_load_metrics {
24
25 namespace {
26
27 // True if the timing structs have the same navigation start.
28 bool PageLoadTimingIsChild(const PageLoadTiming& timing,
29 const PageLoadTiming& parent) {
30 return (parent.navigation_start.is_null() ||
31 timing.navigation_start == parent.navigation_start);
32 }
33
34 bool PageLoadTimingIsComplete(const PageLoadTiming& timing) {
35 return !timing.navigation_start.is_null() &&
36 !timing.response_start.is_zero() &&
37 !timing.dom_content_loaded_event_start.is_zero() &&
38 !timing.load_event_start.is_zero() &&
39 !timing.first_layout.is_zero();
40 }
41
42 // Checks guaranteed ordering for performance events.
43 // Assumes IsComplete().
44 // Order: navigation_start => response_start =>
45 // dom_content_loaded_event_start => load_event_start
46 bool PageLoadTimingIsOrdered(const PageLoadTiming& timing) {
47 return !timing.response_start.is_zero() &&
48 timing.response_start < timing.dom_content_loaded_event_start &&
49 timing.dom_content_loaded_event_start < timing.load_event_start;
50 }
51
52 } // namespace
53 WebContentsObserver::WebContentsObserver(content::WebContents* web_contents)
54 : content::WebContentsObserver(web_contents) {}
55
56 WebContentsObserver::~WebContentsObserver() {
57 RecordTimingHistograms();
Bryan McQuade 2015/09/04 20:53:17 let's add a short comment here to note the cases w
Charlie Harrison 2015/09/08 23:05:15 Done.
58 }
59
60 bool WebContentsObserver::OnMessageReceived(
61 const IPC::Message& message,
62 content::RenderFrameHost* render_frame_host) {
63 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
64 return HandleMessageReceived(message, render_frame_host);
65 }
66
67 void WebContentsObserver::DidCommitNavigation(
68 content::NavigationHandle* navigation_handle) {
69 RecordTimingHistograms();
Bryan McQuade 2015/09/04 20:53:17 we only want to RecordTimingHistograms() if this i
Charlie Harrison 2015/09/08 23:05:15 Done.
70 if (IsRelevantNavigation(navigation_handle)) {
71 current_timing_.reset(new PageLoadTiming());
72 current_navigation_ = navigation_handle;
Bryan McQuade 2015/09/04 20:53:17 looks like we're no longer using current_navigatio
Charlie Harrison 2015/09/08 23:05:15 Done.
73 }
74 }
75
76 void WebContentsObserver::RenderProcessGone(base::TerminationStatus status) {
77 RecordTimingHistograms();
Bryan McQuade 2015/09/04 20:53:17 let's add a short comment here to note where this
Charlie Harrison 2015/09/08 23:05:15 Done.
78 }
79
80 bool WebContentsObserver::HandleMessageReceived(
Bryan McQuade 2015/09/04 20:53:17 minor suggestion: even though it makes the method
Charlie Harrison 2015/09/08 23:05:15 Done.
81 const IPC::Message& message,
82 content::RenderFrameHost* render_frame_host) {
83 bool handled = true;
84 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(WebContentsObserver, message,
85 render_frame_host)
86 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated,
87 OnTimingUpdated)
88 IPC_MESSAGE_UNHANDLED(handled = false)
89 IPC_END_MESSAGE_MAP()
90 return handled;
91 }
92
93 #define PAGE_LOAD_HISTOGRAM(name, sample) \
94 UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, \
95 base::TimeDelta::FromMilliseconds(10), \
96 base::TimeDelta::FromMinutes(10), 100);
97
98 void WebContentsObserver::OnTimingUpdated(
99 content::RenderFrameHost* render_frame_host,
100 const PageLoadTiming& timing) {
101 if (!current_timing_)
102 return;
103
104 // See above comment about browser/renderer url disagreement (newtab).
Bryan McQuade 2015/09/04 20:53:17 can we add: // We may receive notifications from f
Bryan McQuade 2015/09/04 20:53:17 maybe change to "See comment in IsRelevantNavigati
105 if (!GetLastCommittedURL().SchemeIsHTTPOrHTTPS())
106 return;
107
108 // Throw away IPCs that are not relevant to the current navigation.
109 if (PageLoadTimingIsChild(timing, *current_timing_)) {
Bryan McQuade 2015/09/04 20:53:17 given that this is the only place we do this 'is c
110 if (current_timing_->IsEmpty())
111 current_host_ = render_frame_host;
Bryan McQuade 2015/09/04 20:53:17 seems like the canonical source for the current re
Charlie Harrison 2015/09/08 23:05:14 Which side of the equality would you propose chang
112 else
113 DCHECK(render_frame_host == current_host_);
Bryan McQuade 2015/09/04 20:53:17 IIRC creis said that this can actually happen some
Charlie Harrison 2015/09/08 23:05:15 Shouldn't that be handled by the !IsCurrentMainFra
114 current_timing_.reset(new PageLoadTiming(timing));
Bryan McQuade 2015/09/04 20:53:17 can you simplify to: *current_timing_ = timing;
Charlie Harrison 2015/09/08 23:05:15 Done.
115 }
116 }
117
118 void WebContentsObserver::RecordTimingHistograms() {
119 if (!current_timing_ || current_timing_->IsEmpty())
120 return;
121 else if (PageLoadTimingIsComplete(*current_timing_))
Bryan McQuade 2015/09/04 20:53:17 testing validiting of the PageLoadHistograms seems
Bryan McQuade 2015/09/08 14:09:46 oh, and I forgot, we should also test ordering bet
Charlie Harrison 2015/09/08 23:05:15 Is a PageLoadTiming with null nav_start really val
122 DCHECK(PageLoadTimingIsOrdered(*current_timing_));
123
124 if (!current_timing_->dom_content_loaded_event_start.is_zero()) {
125 PAGE_LOAD_HISTOGRAM("PageLoad.Timing.DOMContentLoadedEventFired",
126 current_timing_->dom_content_loaded_event_start);
127 }
128
129 if (!current_timing_->load_event_start.is_zero()) {
130 PAGE_LOAD_HISTOGRAM("PageLoad.Timing.LoadEventFired",
131 current_timing_->load_event_start);
132 }
133
134 if (!current_timing_->first_layout.is_zero()) {
135 PAGE_LOAD_HISTOGRAM("PageLoad.Timing.FirstLayout",
136 current_timing_->first_layout);
137 }
138 current_timing_.reset();
139 }
140
141 bool WebContentsObserver::IsRelevantNavigation(
142 content::NavigationHandle* navigation_handle) {
143 // The url we see from the renderer side is not always the same as what
144 // we see from the browser side (e.g. chrome://newtab). We wan't to be
145 // sure here that we aren't logging UMA for internal pages
146 const GURL& browser_url = GetLastCommittedURL();
147 return navigation_handle->IsInMainFrame() &&
148 !navigation_handle->IsSamePage() &&
149 navigation_handle->HasCommittedDocument() &&
150 navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() &&
151 browser_url.SchemeIsHTTPOrHTTPS();
152 }
153
154 const GURL& WebContentsObserver::GetLastCommittedURL() {
155 return web_contents()->GetLastCommittedURL();
156 }
157
158 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698