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

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_;
nasko 2015/08/20 00:22:18 Parent has a very well defined meaning with frames
Bryan McQuade 2015/08/25 13:53:36 This got refactored so we no longer have a parent_
71 bool did_send_first_layout_;
72 bool did_send_dom_content_loaded_event_;
73 bool did_send_load_event_;
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.
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. DidStartProvisionalLoad doesn't get invoked for same
nasko 2015/08/20 00:22:18 Do we only care about network loads? If so, we nee
Bryan McQuade 2015/08/25 13:53:36 Ah, interesting. Are you saying that DidStartProvi
105 // page navigations, so we may still have an active page_metrics_sender_ at
106 // this point.
107 if (is_same_page_navigation)
108 return;
109
110 DCHECK(!page_metrics_sender_);
111
112 // We only create a PageMetricsSender if the page meets the criteria for
113 // sending and recording metrics. Once page_metrics_sender_ is non-null,
114 // we will send metrics for the current page at some later time, as those
115 // metrics become available.
116 if (ShouldSendMetrics())
117 page_metrics_sender_.reset(new PageMetricsSender(this));
118 }
119
120 void PageLoadMetricsRenderFrameObserver::MaybeSendMetrics() {
121 if (!page_metrics_sender_)
122 return;
123
124 scoped_ptr<Timing> timing(CreateTiming());
125 page_metrics_sender_->MaybeSendMetrics(*timing);
126 }
127
128 bool PageLoadMetricsRenderFrameObserver::ShouldSendMetrics() const {
129 const blink::WebLocalFrame& frame = *render_frame()->GetWebFrame();
130 // We only generate historgrams for main frames.
131 if (frame.parent())
132 return false;
133
134 const blink::WebDocument& document = frame.document();
135 // Ignore non-HTTP schemes (e.g. chrome://).
136 const GURL& url = document.url();
137 if (!url.SchemeIsHTTPOrHTTPS())
138 return false;
139
140 const blink::WebURLResponse& url_response = frame.dataSource()->response();
141 // Ignore multipart responses (e.g. MHTML).
142 if (url_response.isMultipartPayload())
143 return false;
144
145 // Ignore non-HTML documents (e.g. SVG). Note that images are treated by
146 // Blink as HTML documents, so to exclude images, we must perform
147 // additional mime type checking below.
148 if (!document.isHTMLDocument() && !document.isXHTMLDocument())
149 return false;
150
151 // Ignore non-HTML mime types (e.g. images).
152 std::string mime_type = url_response.mimeType().utf8();
153 if (mime_type != "text/html" && mime_type != "application/xhtml+xml")
154 return false;
155
156 return true;
157 }
158
159 scoped_ptr<PageLoadMetricsRenderFrameObserver::Timing>
160 PageLoadMetricsRenderFrameObserver::CreateTiming() {
161 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
162 scoped_ptr<Timing> timing(new PerformanceTiming(
163 frame ? frame->performance() : blink::WebPerformance()));
164 return timing.Pass();
165 }
166
167 PageLoadMetricsRenderFrameObserver::PageMetricsSender::PageMetricsSender(
168 PageLoadMetricsRenderFrameObserver* parent)
169 : parent_(parent),
170 did_send_first_layout_(false),
171 did_send_dom_content_loaded_event_(false),
172 did_send_load_event_(false) {}
173
174 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::MaybeSendMetrics(
175 const Timing& timing) {
176 MaybeSendFirstLayout(timing);
177 MaybeSendDOMContentLoadedEvent(timing);
178 MaybeSendLoadEvent(timing);
179 }
180
181 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::
182 MaybeSendFirstLayout(const Timing& timing) {
183 if (did_send_first_layout_)
184 return;
185
186 if (timing.GetNavigationStart().is_null() ||
187 timing.GetFirstLayout().is_null())
188 return;
189
190 Send(new PageLoadMetricsMsg_FirstLayout(
191 routing_id(),
192 timing.GetFirstLayout() - timing.GetNavigationStart()));
193 did_send_first_layout_ = true;
194 }
195
196 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::
197 MaybeSendDOMContentLoadedEvent(const Timing& timing) {
198 if (did_send_dom_content_loaded_event_)
199 return;
200
201 if (timing.GetNavigationStart().is_null() ||
202 timing.GetDOMContentLoadedEvent().is_null())
203 return;
204
205 Send(new PageLoadMetricsMsg_DOMContentLoadedEvent(
206 routing_id(),
207 timing.GetDOMContentLoadedEvent() - timing.GetNavigationStart()));
208 did_send_dom_content_loaded_event_ = true;
209 }
210
211 void PageLoadMetricsRenderFrameObserver::PageMetricsSender::MaybeSendLoadEvent(
212 const Timing& timing) {
213 if (did_send_load_event_)
214 return;
215
216 if (timing.GetNavigationStart().is_null() || timing.GetLoadEvent().is_null())
217 return;
218
219 Send(new PageLoadMetricsMsg_LoadEvent(
220 routing_id(),
221 timing.GetLoadEvent() - timing.GetNavigationStart()));
222 did_send_load_event_ = true;
223 }
224
225 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698