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

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: Add DidFinishNavigation handler and remove unneeded DCHECK 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/navigation_details.h"
12 #include "content/public/browser/navigation_handle.h"
13 #include "content/public/browser/render_frame_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_observer.h"
16 #include "content/public/browser/web_contents_user_data.h"
17 #include "ipc/ipc_message.h"
18 #include "ipc/ipc_message_macros.h"
19
20 DEFINE_WEB_CONTENTS_USER_DATA_KEY(page_load_metrics::WebContentsObserver);
21
22 namespace page_load_metrics {
23
24 namespace {
25
26 // True if the timing structs have the same navigation start.
27 bool PageLoadTimingIsChild(const PageLoadTiming& timing,
28 const PageLoadTiming& parent) {
29 return (parent.navigation_start.is_null() ||
30 timing.navigation_start == parent.navigation_start);
31 }
32
33 bool PageLoadTimingIsComplete(const PageLoadTiming& timing) {
34 return !timing.navigation_start.is_null() &&
35 !timing.response_start.is_zero() &&
36 !timing.dom_content_loaded_event_start.is_zero() &&
37 !timing.load_event_start.is_zero() &&
38 !timing.first_layout.is_zero();
39 }
40
41 bool PageLoadTimingIsEmpty(const PageLoadTiming& timing) {
Bryan McQuade 2015/09/04 12:29:26 this one method actually seems reasonable to keep
Charlie Harrison 2015/09/04 15:19:40 Done.
42 return timing.navigation_start.is_null() &&
43 timing.response_start.is_zero() &&
44 timing.dom_content_loaded_event_start.is_zero() &&
45 timing.load_event_start.is_zero() &&
46 timing.first_layout.is_zero();
47 }
48
49 // Checks guaranteed ordering for performance events.
50 // Assumes IsComplete().
51 // Order: navigation_start => response_start =>
52 // dom_content_loaded_event_start => load_event_start
53 bool PageLoadTimingIsOrdered(const PageLoadTiming& timing) {
54 return !timing.response_start.is_zero() &&
55 timing.response_start < timing.dom_content_loaded_event_start &&
56 timing.dom_content_loaded_event_start < timing.load_event_start;
57 }
58
59 } // namespace
60 WebContentsObserver::WebContentsObserver(content::WebContents* web_contents)
61 : content::WebContentsObserver(web_contents) {}
62
63 WebContentsObserver::~WebContentsObserver() {
64 RecordTimingHistograms();
65 }
66
67 bool WebContentsObserver::OnMessageReceived(
68 const IPC::Message& message,
69 content::RenderFrameHost* render_frame_host) {
70 bool handled = true;
71 IPC_BEGIN_MESSAGE_MAP(WebContentsObserver, message)
72 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated)
73 IPC_MESSAGE_UNHANDLED(handled = false)
74 IPC_END_MESSAGE_MAP()
75 return handled;
76 }
77
78 void WebContentsObserver::DidCommitNavigation(
79 content::NavigationHandle* navigation_handle) {
80 if (IsRelevantNavigation(navigation_handle)) {
81 RecordTimingHistograms();
Bryan McQuade 2015/09/04 12:29:26 I think we probably want to commit the histograms
Charlie Harrison 2015/09/04 15:19:40 yes! This is a mistake.
82 current_timing_ = PageLoadTiming();
83 current_navigation_ = navigation_handle;
84 }
85 }
86
87 void WebContentsObserver::DidFinishNavigation(
88 content::NavigationHandle* navigation_handle) {
89 if (IsRelevantNavigation(navigation_handle)) {
90 // TODO(csharrison) track aborts and log those histograms here
91 DCHECK(navigation_handle == current_navigation_);
92 current_navigation_ = nullptr;
93 }
94 }
95
96 void WebContentsObserver::RenderProcessGone(base::TerminationStatus status) {
97 RecordTimingHistograms();
Bryan McQuade 2015/09/04 12:29:26 you may also want to do current_timing_ = PageLoad
Charlie Harrison 2015/09/04 15:19:40 Done.
98 }
99
100 #define PAGE_LOAD_HISTOGRAM(name, sample) \
101 UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, \
102 base::TimeDelta::FromMilliseconds(10), \
103 base::TimeDelta::FromMinutes(10), 100);
104
105 void WebContentsObserver::OnTimingUpdated(const PageLoadTiming& timing) {
106 // See above comment about browser/renderer url disagreement (newtab).
107 if (!GetLastCommittedURL().SchemeIsHTTPOrHTTPS())
108 return;
109
110 if (PageLoadTimingIsChild(timing, current_timing_))
111 current_timing_ = timing;
112 }
113
114 void WebContentsObserver::RecordTimingHistograms() {
115 if (PageLoadTimingIsEmpty(current_timing_))
116 return;
117 else if (PageLoadTimingIsComplete(current_timing_))
118 DCHECK(PageLoadTimingIsOrdered(current_timing_));
119
120 if (!current_timing_.dom_content_loaded_event_start.is_zero()) {
121 PAGE_LOAD_HISTOGRAM("PageLoad.Timing.DOMContentLoadedEventFired",
122 current_timing_.dom_content_loaded_event_start);
123 }
124
125 if (!current_timing_.load_event_start.is_zero()) {
126 PAGE_LOAD_HISTOGRAM("PageLoad.Timing.LoadEventFired",
127 current_timing_.load_event_start);
128 }
129
130 if (!current_timing_.first_layout.is_zero()) {
131 PAGE_LOAD_HISTOGRAM("PageLoad.Timing.FirstLayout",
132 current_timing_.first_layout);
133 }
134 }
135
136 bool WebContentsObserver::IsRelevantNavigation(
137 content::NavigationHandle* navigation_handle) {
138 // The url we see from the renderer side is not always the same as what
139 // we see from the browser side (e.g. chrome://newtab). We wan't to be
140 // sure here that we aren't logging UMA for internal pages
141 const GURL& browser_url = GetLastCommittedURL();
142 return navigation_handle->IsInMainFrame() &&
143 navigation_handle->HasCommittedDocument() &&
144 navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() &&
145 browser_url.SchemeIsHTTPOrHTTPS();
146 }
147
148 const GURL& WebContentsObserver::GetLastCommittedURL() {
149 return web_contents()->GetLastCommittedURL();
150 }
151
152 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698