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

Side by Side Diff: components/page_load_metrics/browser/metrics_web_contents_observer.h

Issue 2177743002: Migrate page_load_metrics out of components. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: migrate page_load_metrics_messages to common message generator Created 4 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 #ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_METRICS_WEB_CONTENTS_OBSERVER_H_
6 #define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_METRICS_WEB_CONTENTS_OBSERVER_H_
7
8 #include <map>
9 #include <memory>
10 #include <vector>
11
12 #include "base/macros.h"
13 #include "base/time/time.h"
14 #include "components/page_load_metrics/browser/page_load_metrics_observer.h"
15 #include "components/page_load_metrics/common/page_load_timing.h"
16 #include "content/public/browser/render_widget_host.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_observer.h"
19 #include "content/public/browser/web_contents_user_data.h"
20 #include "net/base/net_errors.h"
21 #include "third_party/WebKit/public/web/WebInputEvent.h"
22
23 namespace content {
24 class NavigationHandle;
25 class RenderFrameHost;
26 } // namespace content
27
28 namespace IPC {
29 class Message;
30 } // namespace IPC
31
32 namespace page_load_metrics {
33
34 class PageLoadTracker;
35
36 namespace internal {
37
38 extern const char kErrorEvents[];
39 extern const char kAbortChainSizeReload[];
40 extern const char kAbortChainSizeForwardBack[];
41 extern const char kAbortChainSizeNewNavigation[];
42 extern const char kAbortChainSizeNoCommit[];
43 extern const char kAbortChainSizeSameURL[];
44
45 } // namespace internal
46
47 // These errors are internal to the page_load_metrics subsystem and do not
48 // reflect actual errors that occur during a page load.
49 //
50 // If you add elements to this enum, make sure you update the enum
51 // value in histograms.xml. Only add elements to the end to prevent
52 // inconsistencies between versions.
53 enum InternalErrorLoadEvent {
54 // A timing IPC was sent from the renderer that did not line up with previous
55 // data we've received (i.e. navigation start is different or the timing
56 // struct is somehow invalid). This error can only occur once the IPC is
57 // vetted in other ways (see other errors).
58 ERR_BAD_TIMING_IPC,
59
60 // The following IPCs are not mutually exclusive.
61 //
62 // We received an IPC when we weren't tracking a committed load. This will
63 // often happen if we get an IPC from a bad URL scheme (that is, the renderer
64 // sent us an IPC from a navigation we don't care about).
65 ERR_IPC_WITH_NO_RELEVANT_LOAD,
66
67 // Received a notification from a frame that has been navigated away from.
68 ERR_IPC_FROM_WRONG_FRAME,
69
70 // We received an IPC even through the last committed url from the browser
71 // was not http/s. This can happen with the renderer sending IPCs for the
72 // new tab page. This will often come paired with
73 // ERR_IPC_WITH_NO_RELEVANT_LOAD.
74 ERR_IPC_FROM_BAD_URL_SCHEME,
75
76 // If we track a navigation, but the renderer sends us no IPCs. This could
77 // occur if the browser filters loads less aggressively than the renderer.
78 ERR_NO_IPCS_RECEIVED,
79
80 // Tracks frequency with which we record an abort time that occurred before
81 // navigation start. This is expected to happen in some cases (see comments in
82 // cc file for details). We use this error counter to understand how often it
83 // happens.
84 ERR_ABORT_BEFORE_NAVIGATION_START,
85
86 // A new navigation triggers abort updates in multiple trackers in
87 // |aborted_provisional_loads_|, when usually there should only be one (the
88 // navigation that just aborted because of this one). If this happens, the
89 // latest aborted load is used to track the chain size.
90 ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS,
91
92 // Received user input without a relevant load. This error type is deprecated,
93 // as it is valid to receive user input without a relevant load. We leave the
94 // enum value here since it's also used in histogram recording, so it's
95 // important that we not re-use this enum entry for a different value.
96 DEPRECATED_ERR_USER_INPUT_WITH_NO_RELEVANT_LOAD,
97
98 // A TimeTicks value in the browser process has value less than
99 // navigation_start_. This could happen if navigation_start_ was computed in
100 // renderer process and the system clock has inter process time tick skew.
101 ERR_INTER_PROCESS_TIME_TICK_SKEW,
102
103 // Add values before this final count.
104 ERR_LAST_ENTRY,
105 };
106
107 // This class serves as a functional interface to various chrome// features.
108 // Impl version is defined in chrome/browser/page_load_metrics.
109 class PageLoadMetricsEmbedderInterface {
110 public:
111 virtual ~PageLoadMetricsEmbedderInterface() {}
112 virtual bool IsPrerendering(content::WebContents* web_contents) = 0;
113 virtual bool IsNewTabPageUrl(const GURL& url) = 0;
114 virtual void RegisterObservers(PageLoadTracker* metrics) = 0;
115 };
116
117 // This class tracks a given page load, starting from navigation start /
118 // provisional load, until a new navigation commits or the navigation fails.
119 // MetricsWebContentsObserver manages a set of provisional PageLoadTrackers, as
120 // well as a committed PageLoadTracker.
121 class PageLoadTracker {
122 public:
123 // Caller must guarantee that the embedder_interface pointer outlives this
124 // class. The PageLoadTracker must not hold on to
125 // currently_committed_load_or_null or navigation_handle beyond the scope of
126 // the constructor.
127 PageLoadTracker(bool in_foreground,
128 PageLoadMetricsEmbedderInterface* embedder_interface,
129 const GURL& currently_committed_url,
130 content::NavigationHandle* navigation_handle,
131 int aborted_chain_size,
132 int aborted_chain_size_same_url);
133 ~PageLoadTracker();
134 void Redirect(content::NavigationHandle* navigation_handle);
135 void Commit(content::NavigationHandle* navigation_handle);
136 void FailedProvisionalLoad(content::NavigationHandle* navigation_handle);
137 void WebContentsHidden();
138 void WebContentsShown();
139
140 void OnInputEvent(const blink::WebInputEvent& event);
141
142 void NotifyClientRedirectTo(const PageLoadTracker& destination);
143
144 // Returns true if the timing was successfully updated.
145 bool UpdateTiming(const PageLoadTiming& timing,
146 const PageLoadMetadata& metadata);
147
148 // Signals that we should stop tracking metrics for the associated page load.
149 // We may stop tracking a page load if it doesn't meet the criteria for
150 // tracking metrics in DidFinishNavigation.
151 void StopTracking();
152
153 int aborted_chain_size() const { return aborted_chain_size_; }
154 int aborted_chain_size_same_url() const {
155 return aborted_chain_size_same_url_;
156 }
157
158 UserAbortType abort_type() const { return abort_type_; }
159 base::TimeTicks abort_time() const { return abort_time_; }
160
161 void AddObserver(std::unique_ptr<PageLoadMetricsObserver> observer);
162
163 // If the user performs some abort-like action while we are tracking this page
164 // load, notify the tracker. Note that we may not classify this as an abort if
165 // we've already performed a first paint.
166 // is_certainly_browser_timestamp signifies if the timestamp passed is taken
167 // in the
168 // browser process or not. We need this to possibly clamp browser timestamp on
169 // a machine with inter process time tick skew.
170 void NotifyAbort(UserAbortType abort_type,
171 base::TimeTicks timestamp,
172 bool is_certainly_browser_timestamp);
173 void UpdateAbort(UserAbortType abort_type,
174 base::TimeTicks timestamp,
175 bool is_certainly_browser_timestamp);
176
177 // This method returns true if this page load has been aborted with type of
178 // ABORT_OTHER, and the |abort_cause_time| is within a sufficiently close
179 // delta to when it was aborted. Note that only provisional loads can be
180 // aborted with ABORT_OTHER. While this heuristic is coarse, it works better
181 // and is simpler than other feasible methods. See https://goo.gl/WKRG98.
182 bool IsLikelyProvisionalAbort(base::TimeTicks abort_cause_time);
183
184 bool MatchesOriginalNavigation(content::NavigationHandle* navigation_handle);
185
186 // Only valid to call post-commit.
187 const GURL& committed_url() const {
188 DCHECK(!commit_time_.is_null());
189 return url_;
190 }
191
192 base::TimeTicks navigation_start() const { return navigation_start_; }
193
194 PageLoadExtraInfo ComputePageLoadExtraInfo();
195
196 private:
197 // This function converts a TimeTicks value taken in the browser process
198 // to navigation_start_ if:
199 // - base::TimeTicks is not comparable across processes because the clock
200 // is not system wide monotonic.
201 // - *event_time < navigation_start_
202 void ClampBrowserTimestampIfInterProcessTimeTickSkew(
203 base::TimeTicks* event_time);
204
205 void UpdateAbortInternal(UserAbortType abort_type,
206 base::TimeTicks timestamp,
207 bool is_certainly_browser_timestamp);
208
209 // If |final_navigation| is null, then this is an "unparented" abort chain,
210 // and represents a sequence of provisional aborts that never ends with a
211 // committed load.
212 void LogAbortChainHistograms(content::NavigationHandle* final_navigation);
213
214 // Whether we stopped tracking this navigation after it was initiated. We may
215 // stop tracking a navigation if it doesn't meet the criteria for tracking
216 // metrics in DidFinishNavigation.
217 bool did_stop_tracking_;
218
219 // The navigation start in TimeTicks, not the wall time reported by Blink.
220 const base::TimeTicks navigation_start_;
221
222 // Time this page load was committed. If this page load hasn't committed,
223 // |commit_time_| will be zero.
224 base::TimeTicks commit_time_;
225
226 // The URL of this page load. This is the provisional url before commit
227 // (before redirects), and the committed url after commit.
228 GURL url_;
229
230 std::unique_ptr<FailedProvisionalLoadInfo> failed_provisional_load_info_;
231
232 // Will be ABORT_NONE if we have not aborted this load yet. Otherwise will
233 // be the first abort action the user performed.
234 UserAbortType abort_type_;
235 base::TimeTicks abort_time_;
236
237 // We record separate metrics for events that occur after a background,
238 // because metrics like layout/paint are delayed artificially
239 // when they occur in the background.
240 base::TimeTicks background_time_;
241 base::TimeTicks foreground_time_;
242 bool started_in_foreground_;
243
244 PageLoadTiming timing_;
245 PageLoadMetadata metadata_;
246
247 // This is a subtle member. If a provisional load A gets aborted by
248 // provisional load B, which gets aborted by C that eventually commits, then
249 // there exists an abort chain of length 2, starting at A's navigation_start.
250 // This is useful because it allows histograming abort chain lengths based on
251 // what the last load's transition type is. i.e. holding down F-5 to spam
252 // reload will produce a long chain with the RELOAD transition.
253 const int aborted_chain_size_;
254
255 // This member counts consecutive provisional aborts that share a url. It will
256 // always be less than or equal to |aborted_chain_size_|.
257 const int aborted_chain_size_same_url_;
258
259 // Interface to chrome features. Must outlive the class.
260 PageLoadMetricsEmbedderInterface* const embedder_interface_;
261
262 std::vector<std::unique_ptr<PageLoadMetricsObserver>> observers_;
263
264 DISALLOW_COPY_AND_ASSIGN(PageLoadTracker);
265 };
266
267 // MetricsWebContentsObserver tracks page loads and loading metrics
268 // related data based on IPC messages received from a
269 // MetricsRenderFrameObserver.
270 class MetricsWebContentsObserver
271 : public content::WebContentsObserver,
272 public content::WebContentsUserData<MetricsWebContentsObserver>,
273 public content::RenderWidgetHost::InputEventObserver {
274 public:
275 // Note that the returned metrics is owned by the web contents.
276 static MetricsWebContentsObserver* CreateForWebContents(
277 content::WebContents* web_contents,
278 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface);
279 MetricsWebContentsObserver(
280 content::WebContents* web_contents,
281 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface);
282 ~MetricsWebContentsObserver() override;
283
284 // content::WebContentsObserver implementation:
285 bool OnMessageReceived(const IPC::Message& message,
286 content::RenderFrameHost* render_frame_host) override;
287 void DidStartNavigation(
288 content::NavigationHandle* navigation_handle) override;
289 void DidFinishNavigation(
290 content::NavigationHandle* navigation_handle) override;
291 void DidRedirectNavigation(
292 content::NavigationHandle* navigation_handle) override;
293 void NavigationStopped() override;
294 void OnInputEvent(const blink::WebInputEvent& event) override;
295 void WasShown() override;
296 void WasHidden() override;
297 void RenderProcessGone(base::TerminationStatus status) override;
298 void RenderViewHostChanged(content::RenderViewHost* old_host,
299 content::RenderViewHost* new_host) override;
300
301 // This getter function is required for testing.
302 const PageLoadExtraInfo GetPageLoadExtraInfoForCommittedLoad();
303
304 private:
305 friend class content::WebContentsUserData<MetricsWebContentsObserver>;
306
307 void HandleFailedNavigationForTrackedLoad(
308 content::NavigationHandle* navigation_handle,
309 std::unique_ptr<PageLoadTracker> tracker);
310
311 void HandleCommittedNavigationForTrackedLoad(
312 content::NavigationHandle* navigation_handle,
313 std::unique_ptr<PageLoadTracker> tracker);
314
315 // Notify all loads, provisional and committed, that we performed an action
316 // that might abort them.
317 void NotifyAbortAllLoads(UserAbortType abort_type);
318 void NotifyAbortAllLoadsWithTimestamp(UserAbortType abort_type,
319 base::TimeTicks timestamp,
320 bool is_certainly_browser_timestamp);
321
322 // Register / Unregister input event callback to given RenderViewHost
323 void RegisterInputEventObserver(content::RenderViewHost* host);
324 void UnregisterInputEventObserver(content::RenderViewHost* host);
325
326 // Notify aborted provisional loads that a new navigation occurred. This is
327 // used for more consistent attribution tracking for aborted provisional
328 // loads. This method returns the provisional load that was likely aborted
329 // by this navigation, to help instantiate the new PageLoadTracker.
330 std::unique_ptr<PageLoadTracker> NotifyAbortedProvisionalLoadsNewNavigation(
331 content::NavigationHandle* new_navigation);
332
333 void OnTimingUpdated(content::RenderFrameHost*,
334 const PageLoadTiming& timing,
335 const PageLoadMetadata& metadata);
336
337 bool ShouldTrackNavigation(
338 content::NavigationHandle* navigation_handle) const;
339
340 // True if the web contents is currently in the foreground.
341 bool in_foreground_;
342
343 // The PageLoadTrackers must be deleted before the |embedder_interface_|,
344 // because they hold a pointer to the |embedder_interface_|.
345 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface_;
346
347 // This map tracks all of the navigations ongoing that are not committed
348 // yet. Once a navigation is committed, it moves from the map to
349 // committed_load_. Note that a PageLoadTrackers NavigationHandle is only
350 // valid until commit time, when we remove it from the map.
351 std::map<content::NavigationHandle*, std::unique_ptr<PageLoadTracker>>
352 provisional_loads_;
353
354 // Tracks aborted provisional loads for a little bit longer than usual (one
355 // more navigation commit at the max), in order to better understand how the
356 // navigation failed. This is because most provisional loads are destroyed
357 // and vanish before we get signal about what caused the abort (new
358 // navigation, stop button, etc.).
359 std::vector<std::unique_ptr<PageLoadTracker>> aborted_provisional_loads_;
360
361 std::unique_ptr<PageLoadTracker> committed_load_;
362
363 // Has the MWCO observed at least one navigation?
364 bool has_navigated_;
365
366 DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserver);
367 };
368
369 } // namespace page_load_metrics
370
371 #endif // COMPONENTS_PAGE_LOAD_METRICS_BROWSER_METRICS_WEB_CONTENTS_OBSERVER_H_
OLDNEW
« no previous file with comments | « components/page_load_metrics/browser/DEPS ('k') | components/page_load_metrics/browser/metrics_web_contents_observer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698