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

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

Issue 2435233002: Factor PageLoadTracker into its own header and impl files. (Closed)
Patch Set: share IsNavigationUserInitiated impl Created 4 years, 1 month 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_METRICS_WEB_CONTENTS_OBSERVER_H_ 5 #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_METRICS_WEB_CONTENTS_OBSERVER_H_
6 #define CHROME_BROWSER_PAGE_LOAD_METRICS_METRICS_WEB_CONTENTS_OBSERVER_H_ 6 #define CHROME_BROWSER_PAGE_LOAD_METRICS_METRICS_WEB_CONTENTS_OBSERVER_H_
7 7
8 #include <map> 8 #include <map>
9 #include <memory> 9 #include <memory>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/time/time.h" 13 #include "base/time/time.h"
14 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" 14 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
15 #include "chrome/common/page_load_metrics/page_load_timing.h" 15 #include "chrome/common/page_load_metrics/page_load_timing.h"
16 #include "content/public/browser/render_widget_host.h" 16 #include "content/public/browser/render_widget_host.h"
17 #include "content/public/browser/web_contents.h" 17 #include "content/public/browser/web_contents.h"
18 #include "content/public/browser/web_contents_observer.h" 18 #include "content/public/browser/web_contents_observer.h"
19 #include "content/public/browser/web_contents_user_data.h" 19 #include "content/public/browser/web_contents_user_data.h"
20 #include "content/public/common/resource_type.h" 20 #include "content/public/common/resource_type.h"
21 #include "net/base/net_errors.h"
22 #include "third_party/WebKit/public/web/WebInputEvent.h" 21 #include "third_party/WebKit/public/web/WebInputEvent.h"
23 22
24 namespace content { 23 namespace content {
25 class NavigationHandle; 24 class NavigationHandle;
26 class RenderFrameHost; 25 class RenderFrameHost;
27 } // namespace content 26 } // namespace content
28 27
29 namespace IPC { 28 namespace IPC {
30 class Message; 29 class Message;
31 } // namespace IPC 30 } // namespace IPC
32 31
33 namespace page_load_metrics { 32 namespace page_load_metrics {
34 33
34 class PageLoadMetricsEmbedderInterface;
35 class PageLoadTracker; 35 class PageLoadTracker;
36 36
37 namespace internal {
38
39 extern const char kErrorEvents[];
40 extern const char kAbortChainSizeReload[];
41 extern const char kAbortChainSizeForwardBack[];
42 extern const char kAbortChainSizeNewNavigation[];
43 extern const char kAbortChainSizeNoCommit[];
44 extern const char kAbortChainSizeSameURL[];
45 extern const char kPageLoadCompletedAfterAppBackground[];
46
47 } // namespace internal
48
49 // These errors are internal to the page_load_metrics subsystem and do not
50 // reflect actual errors that occur during a page load.
51 //
52 // If you add elements to this enum, make sure you update the enum
53 // value in histograms.xml. Only add elements to the end to prevent
54 // inconsistencies between versions.
55 enum InternalErrorLoadEvent {
56 // A timing IPC was sent from the renderer that did not line up with previous
57 // data we've received (i.e. navigation start is different or the timing
58 // struct is somehow invalid). This error can only occur once the IPC is
59 // vetted in other ways (see other errors).
60 ERR_BAD_TIMING_IPC,
61
62 // The following IPCs are not mutually exclusive.
63 //
64 // We received an IPC when we weren't tracking a committed load. This will
65 // often happen if we get an IPC from a bad URL scheme (that is, the renderer
66 // sent us an IPC from a navigation we don't care about).
67 ERR_IPC_WITH_NO_RELEVANT_LOAD,
68
69 // Received a notification from a frame that has been navigated away from.
70 ERR_IPC_FROM_WRONG_FRAME,
71
72 // We received an IPC even through the last committed url from the browser
73 // was not http/s. This can happen with the renderer sending IPCs for the
74 // new tab page. This will often come paired with
75 // ERR_IPC_WITH_NO_RELEVANT_LOAD.
76 ERR_IPC_FROM_BAD_URL_SCHEME,
77
78 // If we track a navigation, but the renderer sends us no IPCs. This could
79 // occur if the browser filters loads less aggressively than the renderer.
80 ERR_NO_IPCS_RECEIVED,
81
82 // Tracks frequency with which we record an abort time that occurred before
83 // navigation start. This is expected to happen in some cases (see comments in
84 // cc file for details). We use this error counter to understand how often it
85 // happens.
86 ERR_ABORT_BEFORE_NAVIGATION_START,
87
88 // A new navigation triggers abort updates in multiple trackers in
89 // |aborted_provisional_loads_|, when usually there should only be one (the
90 // navigation that just aborted because of this one). If this happens, the
91 // latest aborted load is used to track the chain size.
92 ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS,
93
94 // Received user input without a relevant load. This error type is deprecated,
95 // as it is valid to receive user input without a relevant load. We leave the
96 // enum value here since it's also used in histogram recording, so it's
97 // important that we not re-use this enum entry for a different value.
98 DEPRECATED_ERR_USER_INPUT_WITH_NO_RELEVANT_LOAD,
99
100 // A TimeTicks value in the browser process has value less than
101 // navigation_start_. This could happen if navigation_start_ was computed in
102 // renderer process and the system clock has inter process time tick skew.
103 ERR_INTER_PROCESS_TIME_TICK_SKEW,
104
105 // At the time a PageLoadTracker was destroyed, we had received neither a
106 // commit nor a failed provisional load.
107 ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD,
108
109 // Add values before this final count.
110 ERR_LAST_ENTRY,
111 };
112
113 // This class serves as a functional interface to various chrome// features.
114 // Impl version is defined in chrome/browser/page_load_metrics.
115 class PageLoadMetricsEmbedderInterface {
116 public:
117 virtual ~PageLoadMetricsEmbedderInterface() {}
118 virtual bool IsPrerendering(content::WebContents* web_contents) = 0;
119 virtual bool IsNewTabPageUrl(const GURL& url) = 0;
120 virtual void RegisterObservers(PageLoadTracker* metrics) = 0;
121 };
122
123 // This class tracks a given page load, starting from navigation start /
124 // provisional load, until a new navigation commits or the navigation fails.
125 // MetricsWebContentsObserver manages a set of provisional PageLoadTrackers, as
126 // well as a committed PageLoadTracker.
127 class PageLoadTracker {
128 public:
129 // Caller must guarantee that the embedder_interface pointer outlives this
130 // class. The PageLoadTracker must not hold on to
131 // currently_committed_load_or_null or navigation_handle beyond the scope of
132 // the constructor.
133 PageLoadTracker(bool in_foreground,
134 PageLoadMetricsEmbedderInterface* embedder_interface,
135 const GURL& currently_committed_url,
136 content::NavigationHandle* navigation_handle,
137 int aborted_chain_size,
138 int aborted_chain_size_same_url);
139 ~PageLoadTracker();
140 void Redirect(content::NavigationHandle* navigation_handle);
141 void Commit(content::NavigationHandle* navigation_handle);
142 void FailedProvisionalLoad(content::NavigationHandle* navigation_handle);
143 void WebContentsHidden();
144 void WebContentsShown();
145
146 void OnInputEvent(const blink::WebInputEvent& event);
147
148 // Flush any buffered metrics, as part of the metrics subsystem persisting
149 // metrics as the application goes into the background. The application may be
150 // killed at any time after this method is invoked without further
151 // notification.
152 void FlushMetricsOnAppEnterBackground();
153
154 void NotifyClientRedirectTo(const PageLoadTracker& destination);
155
156 // Returns true if the timing was successfully updated.
157 bool UpdateTiming(const PageLoadTiming& timing,
158 const PageLoadMetadata& metadata);
159
160 void OnLoadedSubresource(bool was_cached);
161
162 // Signals that we should stop tracking metrics for the associated page load.
163 // We may stop tracking a page load if it doesn't meet the criteria for
164 // tracking metrics in DidFinishNavigation.
165 void StopTracking();
166
167 int aborted_chain_size() const { return aborted_chain_size_; }
168 int aborted_chain_size_same_url() const {
169 return aborted_chain_size_same_url_;
170 }
171
172 UserAbortType abort_type() const { return abort_type_; }
173 base::TimeTicks abort_time() const { return abort_time_; }
174
175 void AddObserver(std::unique_ptr<PageLoadMetricsObserver> observer);
176
177 // If the user performs some abort-like action while we are tracking this page
178 // load, notify the tracker. Note that we may not classify this as an abort if
179 // we've already performed a first paint.
180 // is_certainly_browser_timestamp signifies if the timestamp passed is taken
181 // in the
182 // browser process or not. We need this to possibly clamp browser timestamp on
183 // a machine with inter process time tick skew.
184 void NotifyAbort(UserAbortType abort_type,
185 bool user_initiated,
186 base::TimeTicks timestamp,
187 bool is_certainly_browser_timestamp);
188 void UpdateAbort(UserAbortType abort_type,
189 bool user_initiated,
190 base::TimeTicks timestamp,
191 bool is_certainly_browser_timestamp);
192
193 // This method returns true if this page load has been aborted with type of
194 // ABORT_OTHER, and the |abort_cause_time| is within a sufficiently close
195 // delta to when it was aborted. Note that only provisional loads can be
196 // aborted with ABORT_OTHER. While this heuristic is coarse, it works better
197 // and is simpler than other feasible methods. See https://goo.gl/WKRG98.
198 bool IsLikelyProvisionalAbort(base::TimeTicks abort_cause_time) const;
199
200 bool MatchesOriginalNavigation(content::NavigationHandle* navigation_handle);
201
202 // Only valid to call post-commit.
203 const GURL& committed_url() const {
204 DCHECK(!committed_url_.is_empty());
205 return committed_url_;
206 }
207
208 base::TimeTicks navigation_start() const { return navigation_start_; }
209
210 PageLoadExtraInfo ComputePageLoadExtraInfo();
211
212 ui::PageTransition page_transition() const { return page_transition_; }
213
214 private:
215 // This function converts a TimeTicks value taken in the browser process
216 // to navigation_start_ if:
217 // - base::TimeTicks is not comparable across processes because the clock
218 // is not system wide monotonic.
219 // - *event_time < navigation_start_
220 void ClampBrowserTimestampIfInterProcessTimeTickSkew(
221 base::TimeTicks* event_time);
222
223 void UpdateAbortInternal(UserAbortType abort_type,
224 bool user_initiated,
225 base::TimeTicks timestamp,
226 bool is_certainly_browser_timestamp);
227
228 // If |final_navigation| is null, then this is an "unparented" abort chain,
229 // and represents a sequence of provisional aborts that never ends with a
230 // committed load.
231 void LogAbortChainHistograms(content::NavigationHandle* final_navigation);
232
233 // Whether we stopped tracking this navigation after it was initiated. We may
234 // stop tracking a navigation if it doesn't meet the criteria for tracking
235 // metrics in DidFinishNavigation.
236 bool did_stop_tracking_;
237
238 // Whether the application went into the background when this PageLoadTracker
239 // was active. This is a temporary boolean for UMA tracking.
240 bool app_entered_background_;
241
242 // The navigation start in TimeTicks, not the wall time reported by Blink.
243 const base::TimeTicks navigation_start_;
244
245 // The committed URL of this page load.
246 GURL committed_url_;
247
248 // The start URL for this page load (before redirects).
249 GURL start_url_;
250
251 std::unique_ptr<FailedProvisionalLoadInfo> failed_provisional_load_info_;
252
253 // Will be ABORT_NONE if we have not aborted this load yet. Otherwise will
254 // be the first abort action the user performed.
255 UserAbortType abort_type_;
256
257 // This boolean is only an approximation. As the aborts pipeline is updated,
258 // more abort types will have this set to true. Currently, this is only set
259 // for navigations aborting navigations.
260 bool abort_user_initiated_;
261
262 base::TimeTicks abort_time_;
263
264 // We record separate metrics for events that occur after a background,
265 // because metrics like layout/paint are delayed artificially
266 // when they occur in the background.
267 base::TimeTicks background_time_;
268 base::TimeTicks foreground_time_;
269 bool started_in_foreground_;
270
271 PageLoadTiming timing_;
272 PageLoadMetadata metadata_;
273
274 ui::PageTransition page_transition_;
275
276 // Note: these are only approximations, based on WebContents attribution from
277 // ResourceRequestInfo objects while this is the currently committed load in
278 // the WebContents.
279 int num_cache_requests_;
280 int num_network_requests_;
281
282 // This is derived from the user gesture bit in the renderer. For browser
283 // initiated navigations this will always be true.
284 bool user_gesture_;
285
286 // This is a subtle member. If a provisional load A gets aborted by
287 // provisional load B, which gets aborted by C that eventually commits, then
288 // there exists an abort chain of length 2, starting at A's navigation_start.
289 // This is useful because it allows histograming abort chain lengths based on
290 // what the last load's transition type is. i.e. holding down F-5 to spam
291 // reload will produce a long chain with the RELOAD transition.
292 const int aborted_chain_size_;
293
294 // This member counts consecutive provisional aborts that share a url. It will
295 // always be less than or equal to |aborted_chain_size_|.
296 const int aborted_chain_size_same_url_;
297
298 // Interface to chrome features. Must outlive the class.
299 PageLoadMetricsEmbedderInterface* const embedder_interface_;
300
301 std::vector<std::unique_ptr<PageLoadMetricsObserver>> observers_;
302
303 DISALLOW_COPY_AND_ASSIGN(PageLoadTracker);
304 };
305
306 // MetricsWebContentsObserver tracks page loads and loading metrics 37 // MetricsWebContentsObserver tracks page loads and loading metrics
307 // related data based on IPC messages received from a 38 // related data based on IPC messages received from a
308 // MetricsRenderFrameObserver. 39 // MetricsRenderFrameObserver.
309 class MetricsWebContentsObserver 40 class MetricsWebContentsObserver
310 : public content::WebContentsObserver, 41 : public content::WebContentsObserver,
311 public content::WebContentsUserData<MetricsWebContentsObserver>, 42 public content::WebContentsUserData<MetricsWebContentsObserver>,
312 public content::RenderWidgetHost::InputEventObserver { 43 public content::RenderWidgetHost::InputEventObserver {
313 public: 44 public:
314 // Note that the returned metrics is owned by the web contents. 45 // Note that the returned metrics is owned by the web contents.
315 static MetricsWebContentsObserver* CreateForWebContents( 46 static MetricsWebContentsObserver* CreateForWebContents(
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 145
415 // Has the MWCO observed at least one navigation? 146 // Has the MWCO observed at least one navigation?
416 bool has_navigated_; 147 bool has_navigated_;
417 148
418 DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserver); 149 DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserver);
419 }; 150 };
420 151
421 } // namespace page_load_metrics 152 } // namespace page_load_metrics
422 153
423 #endif // CHROME_BROWSER_PAGE_LOAD_METRICS_METRICS_WEB_CONTENTS_OBSERVER_H_ 154 #endif // CHROME_BROWSER_PAGE_LOAD_METRICS_METRICS_WEB_CONTENTS_OBSERVER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698