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

Side by Side Diff: components/page_load_metrics/renderer/page_load_metrics_render_frame_observer.cc

Issue 1282303002: PageLoadMetrics renderer and browser implementation (deprecated) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 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 "base/time/time.h"
6 #include "components/page_load_metrics/common/page_load_metrics_messages.h"
7 #include "components/page_load_metrics/renderer/page_load_metrics_render_frame_o bserver.h"
8 #include "content/public/renderer/render_frame.h"
9 #include "third_party/WebKit/public/platform/WebURLResponse.h"
10 #include "third_party/WebKit/public/web/WebDataSource.h"
11 #include "third_party/WebKit/public/web/WebDocument.h"
12 #include "third_party/WebKit/public/web/WebLocalFrame.h"
13 #include "third_party/WebKit/public/web/WebPerformance.h"
14 #include "url/gurl.h"
15
16 using base::Time;
17
18 namespace page_load_metrics {
19
20 namespace {
21
22 // PerformanceTiming is the concrete implementation of the Timing interface
23 // that gets its timing data from a blink::WebPerformance instance.
24 class PerformanceTiming : public PageLoadMetricsRenderFrameObserver::Timing {
25 public:
26 explicit PerformanceTiming(const blink::WebPerformance& performance)
27 : performance_(performance) {}
28
29 Time GetNavigationStart() const override {
30 return Time::FromDoubleT(performance_.navigationStart());
31 }
32
33 Time GetDOMContentLoadedEvent() const override {
34 return Time::FromDoubleT(performance_.domContentLoadedEventStart());
35 }
36
37 Time GetLoadEvent() const override {
38 return Time::FromDoubleT(performance_.loadEventStart());
39 }
40
41 Time GetFirstLayout() const override {
42 return Time::FromDoubleT(performance_.firstLayout());
43 }
44
45 private:
46 blink::WebPerformance performance_;
47
48 DISALLOW_COPY_AND_ASSIGN(PerformanceTiming);
49 };
50
51 } // namespace
52
53 // PageMetricsSender is a helper class responsible for sending page load
54 // metrics over the lifetime of a webpage. A PageMetricsSender instance is
55 // active from the time a provisional load is committed, until the time the
56 // provisional load for the next page is started.
57 class PageLoadMetricsRenderFrameObserver::PageMetricsSender {
58 public:
59 explicit PageMetricsSender(PageLoadMetricsRenderFrameObserver* parent);
60 void MaybeSendMetrics(const Timing& timing);
61
62 private:
63 void Send(IPC::Message* message) { parent_->Send(message); }
64 int routing_id() const { return parent_->routing_id(); }
65
66 void MaybeSendFirstLayout(const Timing& timing);
67 void MaybeSendDOMContentLoadedEvent(const Timing& timing);
68 void MaybeSendLoadEvent(const Timing& timing);
69
70 PageLoadMetricsRenderFrameObserver* const parent_;
71 bool did_send_first_layout_;
72 bool did_send_dom_content_loaded_event_;
73 bool did_send_load_event_;
kinuko 2015/08/18 10:37:39 So this object's created for each page/document ma
Bryan McQuade 2015/08/19 11:45:14 The Blink WebPerformance object that exposes the t
74 };
75
76 PageLoadMetricsRenderFrameObserver::PageLoadMetricsRenderFrameObserver(
77 content::RenderFrame* render_frame)
78 : content::RenderFrameObserver(render_frame) {}
79
80 PageLoadMetricsRenderFrameObserver::~PageLoadMetricsRenderFrameObserver() {}
81
82 // TODO(bmcquade): use DidChangePerformanceTiming instead, once available.
83 void PageLoadMetricsRenderFrameObserver::DidFinishDocumentLoad() {
84 MaybeSendMetrics();
85 }
86
87 // TODO(bmcquade): use DidChangePerformanceTiming instead, once available.
Randy Smith (Not in Mondays) 2015/08/17 19:31:07 Is there a pointer to issue # or CL to include her
Bryan McQuade 2015/08/19 11:45:14 Sure - this should actually be addressed before I
88 void PageLoadMetricsRenderFrameObserver::DidFinishLoad() {
89 MaybeSendMetrics();
90 }
91
92 void PageLoadMetricsRenderFrameObserver::DidStartProvisionalLoad() {
93 // A provisional page load has started. Shut down metrics reporting until the
94 // next page load is committed. Note that a provisoinal load may fail. We
95 // simply stop reporting metrics in that case, until the next successful page
96 // load is committed.
97 page_metrics_sender_.reset();
98 }
99
100 void PageLoadMetricsRenderFrameObserver::DidCommitProvisionalLoad(
101 bool is_new_navigation, bool is_same_page_navigation) {
102 // Same-page navigations (e.g. an in-document navigation from a fragment
103 // link) aren't full page loads, since they don't go to network to load the
104 // main HTML resource.
105 if (is_same_page_navigation)
106 return;
Randy Smith (Not in Mondays) 2015/08/17 19:31:07 Does this mean that a same page navigation will nu
Bryan McQuade 2015/08/19 11:45:14 DidStartProvisionalLoad doesn't get invoked for sa
107
108 if (ShouldSendMetrics())
109 page_metrics_sender_.reset(new PageMetricsSender(this));
Randy Smith (Not in Mondays) 2015/08/17 19:31:07 I'd like a comment somewhere (not sure where, but
Bryan McQuade 2015/08/25 13:53:35 Done.
110 else
111 page_metrics_sender_.reset();
Randy Smith (Not in Mondays) 2015/08/17 19:31:07 Under what circumstances will this have an effect?
Bryan McQuade 2015/08/19 11:45:14 Good point. A DCHECK seems much better here. Will
112 }
113
114 void PageLoadMetricsRenderFrameObserver::MaybeSendMetrics() {
115 if (!page_metrics_sender_)
116 return;
117
118 scoped_ptr<Timing> timing(CreateTiming());
119 page_metrics_sender_->MaybeSendMetrics(*timing);
120 }
121
122 bool PageLoadMetricsRenderFrameObserver::ShouldSendMetrics() {
123 const blink::WebLocalFrame& frame = *render_frame()->GetWebFrame();
124 // We only generate historgrams for main frames.
125 if (frame.parent())
126 return false;
127
128 const blink::WebDocument& document = frame.document();
129 // Ignore non-HTTP schemes (e.g. chrome://).
130 const GURL& url = document.url();
131 if (!url.SchemeIs("http") && !url.SchemeIs("https"))
kinuko 2015/08/18 10:37:39 nit: !url.SchemeIsHTTPOrHTTPS()
Bryan McQuade 2015/08/25 13:53:35 Thanks, did not know about that. Fixed.
132 return false;
133
134 const blink::WebURLResponse& url_response = frame.dataSource()->response();
135 // Ignore multipart responses (e.g. MHTML).
136 if (url_response.isMultipartPayload())
137 return false;
138
139 // Ignore non-HTML documents (e.g. SVG). Note that images are treated by
140 // Blink as HTML documents, so to exclude images, we must perform
141 // additional mime type checking below.
142 if (!document.isHTMLDocument() && !document.isXHTMLDocument())
143 return false;
144
145 // Ignore non-HTML mime types (e.g. images).
146 std::string mime_type = url_response.mimeType().utf8();
147 if (mime_type != "text/html" && mime_type != "application/xhtml+xml")
148 return false;
149
150 return true;
151 }
152
153 scoped_ptr<PageLoadMetricsRenderFrameObserver::Timing>
154 PageLoadMetricsRenderFrameObserver::CreateTiming() {
155 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
156 scoped_ptr<Timing> timing(new PerformanceTiming(
157 frame ? frame->performance() : blink::WebPerformance()));
158 return timing.Pass();
159 }
160
161 PageLoadMetricsRenderFrameObserver::PageMetricsSender::PageMetricsSender(
162 PageLoadMetricsRenderFrameObserver* parent)
163 : parent_(parent),
164 did_send_first_layout_(false),
165 did_send_dom_content_loaded_event_(false),
166 did_send_load_event_(false) {}
167
168 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::MaybeSendMetrics(
169 const Timing& timing) {
170 MaybeSendFirstLayout(timing);
171 MaybeSendDOMContentLoadedEvent(timing);
172 MaybeSendLoadEvent(timing);
Randy Smith (Not in Mondays) 2015/08/17 19:31:08 I'll happily accept this architecture if you tell
Bryan McQuade 2015/08/19 11:45:14 It's generally hard to predict when in the page lo
173 }
174
175 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::
176 MaybeSendFirstLayout(const Timing& timing) {
177 if (did_send_first_layout_)
178 return;
179
180 if (timing.GetNavigationStart().is_null() ||
181 timing.GetFirstLayout().is_null())
182 return;
183
184 Send(new PageLoadMetricsMsg_FirstLayout(
185 routing_id(),
186 timing.GetFirstLayout() - timing.GetNavigationStart()));
187 did_send_first_layout_ = true;
188 }
189
190 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::
191 MaybeSendDOMContentLoadedEvent(const Timing& timing) {
192 if (did_send_dom_content_loaded_event_)
193 return;
194
195 if (timing.GetNavigationStart().is_null() ||
196 timing.GetDOMContentLoadedEvent().is_null())
197 return;
198
199 Send(new PageLoadMetricsMsg_DOMContentLoadedEvent(
200 routing_id(),
201 timing.GetDOMContentLoadedEvent() - timing.GetNavigationStart()));
202 did_send_dom_content_loaded_event_ = true;
203 }
204
205 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::MaybeSendLoadEvent(
206 const Timing& timing) {
207 if (did_send_load_event_)
208 return;
209
210 if (timing.GetNavigationStart().is_null() || timing.GetLoadEvent().is_null())
211 return;
212
213 Send(new PageLoadMetricsMsg_LoadEvent(
214 routing_id(),
215 timing.GetLoadEvent() - timing.GetNavigationStart()));
216 did_send_load_event_ = true;
217 }
218
219 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698