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

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

Issue 2904533002: Factor management of metrics updates into its own class. (Closed)
Patch Set: address comments Created 3 years, 7 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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_PAGE_LOAD_TRACKER_H_ 5 #ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_
6 #define CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_ 6 #define CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_
7 7
8 #include <memory> 8 #include <memory>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/optional.h" 12 #include "base/optional.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/browser/page_load_metrics/page_load_metrics_update_dispatcher.h "
15 #include "chrome/browser/page_load_metrics/user_input_tracker.h" 16 #include "chrome/browser/page_load_metrics/user_input_tracker.h"
16 #include "chrome/common/page_load_metrics/page_load_timing.h" 17 #include "chrome/common/page_load_metrics/page_load_timing.h"
17 #include "content/public/browser/global_request_id.h" 18 #include "content/public/browser/global_request_id.h"
18 #include "content/public/browser/web_contents_observer.h" 19 #include "content/public/browser/web_contents_observer.h"
19 #include "ui/base/page_transition_types.h" 20 #include "ui/base/page_transition_types.h"
20 21
21 class GURL; 22 class GURL;
22 23
23 namespace blink { 24 namespace blink {
24 class WebInputEvent; 25 class WebInputEvent;
25 } // namespace blink 26 } // namespace blink
26 27
27 namespace content { 28 namespace content {
28 class NavigationHandle; 29 class NavigationHandle;
29 class RenderFrameHost;
30 } // namespace content 30 } // namespace content
31 31
32 namespace page_load_metrics { 32 namespace page_load_metrics {
33 33
34 class PageLoadMetricsEmbedderInterface; 34 class PageLoadMetricsEmbedderInterface;
35 class PageLoadMetricsObserver; 35 class PageLoadMetricsObserver;
36 36
37 namespace internal { 37 namespace internal {
38 38
39 extern const char kErrorEvents[]; 39 extern const char kErrorEvents[];
40 extern const char kAbortChainSizeReload[]; 40 extern const char kAbortChainSizeReload[];
41 extern const char kAbortChainSizeForwardBack[]; 41 extern const char kAbortChainSizeForwardBack[];
42 extern const char kAbortChainSizeNewNavigation[]; 42 extern const char kAbortChainSizeNewNavigation[];
43 extern const char kAbortChainSizeNoCommit[]; 43 extern const char kAbortChainSizeNoCommit[];
44 extern const char kAbortChainSizeSameURL[]; 44 extern const char kAbortChainSizeSameURL[];
45 extern const char kPageLoadCompletedAfterAppBackground[]; 45 extern const char kPageLoadCompletedAfterAppBackground[];
46 extern const char kPageLoadTimingStatus[];
47
48 // Used to track the status of PageLoadTimings received from the render process.
49 //
50 // If you add elements to this enum, make sure you update the enum value in
51 // histograms.xml. Only add elements to the end to prevent inconsistencies
52 // between versions.
53 enum PageLoadTimingStatus {
54 // The PageLoadTiming is valid (all data within the PageLoadTiming is
55 // consistent with expectations).
56 VALID,
57
58 // All remaining status codes are for invalid PageLoadTimings.
59
60 // The PageLoadTiming was empty.
61 INVALID_EMPTY_TIMING,
62
63 // The PageLoadTiming had a null navigation_start.
64 INVALID_NULL_NAVIGATION_START,
65
66 // Script load or execution durations in the PageLoadTiming were too long.
67 INVALID_SCRIPT_LOAD_LONGER_THAN_PARSE,
68 INVALID_SCRIPT_EXEC_LONGER_THAN_PARSE,
69 INVALID_SCRIPT_LOAD_DOC_WRITE_LONGER_THAN_SCRIPT_LOAD,
70 INVALID_SCRIPT_EXEC_DOC_WRITE_LONGER_THAN_SCRIPT_EXEC,
71
72 // The order of two events in the PageLoadTiming was invalid. Either the first
73 // wasn't present when the second was present, or the second was reported as
74 // happening before the first.
75 INVALID_ORDER_RESPONSE_START_PARSE_START,
76 INVALID_ORDER_PARSE_START_PARSE_STOP,
77 INVALID_ORDER_PARSE_STOP_DOM_CONTENT_LOADED,
78 INVALID_ORDER_DOM_CONTENT_LOADED_LOAD,
79 INVALID_ORDER_PARSE_START_FIRST_LAYOUT,
80 INVALID_ORDER_FIRST_LAYOUT_FIRST_PAINT,
81 INVALID_ORDER_FIRST_PAINT_FIRST_TEXT_PAINT,
82 INVALID_ORDER_FIRST_PAINT_FIRST_IMAGE_PAINT,
83 INVALID_ORDER_FIRST_PAINT_FIRST_CONTENTFUL_PAINT,
84 INVALID_ORDER_FIRST_PAINT_FIRST_MEANINGFUL_PAINT,
85
86 // New values should be added before this final entry.
87 LAST_PAGE_LOAD_TIMING_STATUS
88 };
89 46
90 } // namespace internal 47 } // namespace internal
91 48
92 // These errors are internal to the page_load_metrics subsystem and do not 49 // These errors are internal to the page_load_metrics subsystem and do not
93 // reflect actual errors that occur during a page load. 50 // reflect actual errors that occur during a page load.
94 // 51 //
95 // If you add elements to this enum, make sure you update the enum 52 // If you add elements to this enum, make sure you update the enum
96 // value in histograms.xml. Only add elements to the end to prevent 53 // value in histograms.xml. Only add elements to the end to prevent
97 // inconsistencies between versions. 54 // inconsistencies between versions.
98 enum InternalErrorLoadEvent { 55 enum InternalErrorLoadEvent {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 // to access them. 139 // to access them.
183 void RecordInternalError(InternalErrorLoadEvent event); 140 void RecordInternalError(InternalErrorLoadEvent event);
184 PageEndReason EndReasonForPageTransition(ui::PageTransition transition); 141 PageEndReason EndReasonForPageTransition(ui::PageTransition transition);
185 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url); 142 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url);
186 bool IsNavigationUserInitiated(content::NavigationHandle* handle); 143 bool IsNavigationUserInitiated(content::NavigationHandle* handle);
187 144
188 // This class tracks a given page load, starting from navigation start / 145 // This class tracks a given page load, starting from navigation start /
189 // provisional load, until a new navigation commits or the navigation fails. 146 // provisional load, until a new navigation commits or the navigation fails.
190 // MetricsWebContentsObserver manages a set of provisional PageLoadTrackers, as 147 // MetricsWebContentsObserver manages a set of provisional PageLoadTrackers, as
191 // well as a committed PageLoadTracker. 148 // well as a committed PageLoadTracker.
192 class PageLoadTracker { 149 class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client {
193 public: 150 public:
194 // Caller must guarantee that the embedder_interface pointer outlives this 151 // Caller must guarantee that the embedder_interface pointer outlives this
195 // class. The PageLoadTracker must not hold on to 152 // class. The PageLoadTracker must not hold on to
196 // currently_committed_load_or_null or navigation_handle beyond the scope of 153 // currently_committed_load_or_null or navigation_handle beyond the scope of
197 // the constructor. 154 // the constructor.
198 PageLoadTracker(bool in_foreground, 155 PageLoadTracker(bool in_foreground,
199 PageLoadMetricsEmbedderInterface* embedder_interface, 156 PageLoadMetricsEmbedderInterface* embedder_interface,
200 const GURL& currently_committed_url, 157 const GURL& currently_committed_url,
201 content::NavigationHandle* navigation_handle, 158 content::NavigationHandle* navigation_handle,
202 UserInitiatedInfo user_initiated_info, 159 UserInitiatedInfo user_initiated_info,
203 int aborted_chain_size, 160 int aborted_chain_size,
204 int aborted_chain_size_same_url); 161 int aborted_chain_size_same_url);
205 ~PageLoadTracker(); 162 ~PageLoadTracker() override;
163
164 // PageLoadMetricsUpdateDispatcher::Client implementation:
165 void OnTimingChanged() override;
166 void OnMainFrameMetadataChanged() override;
167 void OnSubframeMetadataChanged() override;
168
206 void Redirect(content::NavigationHandle* navigation_handle); 169 void Redirect(content::NavigationHandle* navigation_handle);
207 void WillProcessNavigationResponse( 170 void WillProcessNavigationResponse(
208 content::NavigationHandle* navigation_handle); 171 content::NavigationHandle* navigation_handle);
209 void Commit(content::NavigationHandle* navigation_handle); 172 void Commit(content::NavigationHandle* navigation_handle);
210 void DidCommitSameDocumentNavigation( 173 void DidCommitSameDocumentNavigation(
211 content::NavigationHandle* navigation_handle); 174 content::NavigationHandle* navigation_handle);
212 void DidFinishSubFrameNavigation( 175 void DidFinishSubFrameNavigation(
213 content::NavigationHandle* navigation_handle); 176 content::NavigationHandle* navigation_handle);
214 void FailedProvisionalLoad(content::NavigationHandle* navigation_handle, 177 void FailedProvisionalLoad(content::NavigationHandle* navigation_handle,
215 base::TimeTicks failed_load_time); 178 base::TimeTicks failed_load_time);
216 void WebContentsHidden(); 179 void WebContentsHidden();
217 void WebContentsShown(); 180 void WebContentsShown();
218 181
219 void OnInputEvent(const blink::WebInputEvent& event); 182 void OnInputEvent(const blink::WebInputEvent& event);
220 183
221 // Flush any buffered metrics, as part of the metrics subsystem persisting 184 // Flush any buffered metrics, as part of the metrics subsystem persisting
222 // metrics as the application goes into the background. The application may be 185 // metrics as the application goes into the background. The application may be
223 // killed at any time after this method is invoked without further 186 // killed at any time after this method is invoked without further
224 // notification. 187 // notification.
225 void FlushMetricsOnAppEnterBackground(); 188 void FlushMetricsOnAppEnterBackground();
226 189
227 void NotifyClientRedirectTo(const PageLoadTracker& destination); 190 void NotifyClientRedirectTo(const PageLoadTracker& destination);
228 191
229 void UpdateTiming(const mojom::PageLoadTiming& timing,
230 const mojom::PageLoadMetadata& metadata);
231
232 void UpdateSubFrameTiming(content::RenderFrameHost* render_frame_host,
233 const mojom::PageLoadTiming& new_timing,
234 const mojom::PageLoadMetadata& new_metadata);
235
236 // Update metadata for child frames. Updates for child frames arrive
237 // separately from updates for the main frame, so aren't included in
238 // UpdateTiming.
239 void UpdateSubFrameMetadata(const mojom::PageLoadMetadata& subframe_metadata);
240
241 void OnStartedResource( 192 void OnStartedResource(
242 const ExtraRequestStartInfo& extra_request_started_info); 193 const ExtraRequestStartInfo& extra_request_started_info);
243 194
244 void OnLoadedResource( 195 void OnLoadedResource(
245 const ExtraRequestCompleteInfo& extra_request_complete_info); 196 const ExtraRequestCompleteInfo& extra_request_complete_info);
246 197
247 // Signals that we should stop tracking metrics for the associated page load. 198 // Signals that we should stop tracking metrics for the associated page load.
248 // We may stop tracking a page load if it doesn't meet the criteria for 199 // We may stop tracking a page load if it doesn't meet the criteria for
249 // tracking metrics in DidFinishNavigation. 200 // tracking metrics in DidFinishNavigation.
250 void StopTracking(); 201 void StopTracking();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 // and is simpler than other feasible methods. See https://goo.gl/WKRG98. 233 // and is simpler than other feasible methods. See https://goo.gl/WKRG98.
283 bool IsLikelyProvisionalAbort(base::TimeTicks abort_cause_time) const; 234 bool IsLikelyProvisionalAbort(base::TimeTicks abort_cause_time) const;
284 235
285 bool MatchesOriginalNavigation(content::NavigationHandle* navigation_handle); 236 bool MatchesOriginalNavigation(content::NavigationHandle* navigation_handle);
286 237
287 bool did_commit() const { return did_commit_; } 238 bool did_commit() const { return did_commit_; }
288 const GURL& url() const { return url_; } 239 const GURL& url() const { return url_; }
289 240
290 base::TimeTicks navigation_start() const { return navigation_start_; } 241 base::TimeTicks navigation_start() const { return navigation_start_; }
291 242
292 PageLoadExtraInfo ComputePageLoadExtraInfo(); 243 PageLoadExtraInfo ComputePageLoadExtraInfo() const;
293 244
294 ui::PageTransition page_transition() const { return page_transition_; } 245 ui::PageTransition page_transition() const { return page_transition_; }
295 246
296 UserInitiatedInfo user_initiated_info() const { return user_initiated_info_; } 247 UserInitiatedInfo user_initiated_info() const { return user_initiated_info_; }
297 248
298 UserInputTracker* input_tracker() { return &input_tracker_; } 249 UserInputTracker* input_tracker() { return &input_tracker_; }
299 250
251 PageLoadMetricsUpdateDispatcher* metrics_update_dispatcher() {
252 return &metrics_update_dispatcher_;
253 }
254
300 // Whether this PageLoadTracker has a navigation GlobalRequestID that matches 255 // Whether this PageLoadTracker has a navigation GlobalRequestID that matches
301 // the given request_id. This method will return false before 256 // the given request_id. This method will return false before
302 // WillProcessNavigationResponse has been invoked, as PageLoadTracker doesn't 257 // WillProcessNavigationResponse has been invoked, as PageLoadTracker doesn't
303 // know its GlobalRequestID until WillProcessNavigationResponse has been 258 // know its GlobalRequestID until WillProcessNavigationResponse has been
304 // invoked. 259 // invoked.
305 bool HasMatchingNavigationRequestID( 260 bool HasMatchingNavigationRequestID(
306 const content::GlobalRequestID& request_id) const; 261 const content::GlobalRequestID& request_id) const;
307 262
308 // Invoked when a media element starts playing. 263 // Invoked when a media element starts playing.
309 void MediaStartedPlaying( 264 void MediaStartedPlaying(
310 const content::WebContentsObserver::MediaPlayerInfo& video_type, 265 const content::WebContentsObserver::MediaPlayerInfo& video_type,
311 bool is_in_main_frame); 266 bool is_in_main_frame);
312 267
313 // Invoked on navigations where a navigation delay was added by the 268 // Invoked on navigations where a navigation delay was added by the
314 // DelayNavigationThrottle. This is a temporary method that will be removed 269 // DelayNavigationThrottle. This is a temporary method that will be removed
315 // once the experiment is complete. 270 // once the experiment is complete.
316 void OnNavigationDelayComplete(base::TimeDelta scheduled_delay, 271 void OnNavigationDelayComplete(base::TimeDelta scheduled_delay,
317 base::TimeDelta actual_delay); 272 base::TimeDelta actual_delay);
318 273
319 private: 274 private:
320 using FrameTreeNodeId = int;
321
322 // This function converts a TimeTicks value taken in the browser process 275 // This function converts a TimeTicks value taken in the browser process
323 // to navigation_start_ if: 276 // to navigation_start_ if:
324 // - base::TimeTicks is not comparable across processes because the clock 277 // - base::TimeTicks is not comparable across processes because the clock
325 // is not system wide monotonic. 278 // is not system wide monotonic.
326 // - *event_time < navigation_start_ 279 // - *event_time < navigation_start_
327 void ClampBrowserTimestampIfInterProcessTimeTickSkew( 280 void ClampBrowserTimestampIfInterProcessTimeTickSkew(
328 base::TimeTicks* event_time); 281 base::TimeTicks* event_time);
329 282
330 void UpdatePageEndInternal(PageEndReason page_end_reason, 283 void UpdatePageEndInternal(PageEndReason page_end_reason,
331 UserInitiatedInfo user_initiated_info, 284 UserInitiatedInfo user_initiated_info,
332 base::TimeTicks timestamp, 285 base::TimeTicks timestamp,
333 bool is_certainly_browser_timestamp); 286 bool is_certainly_browser_timestamp);
334 287
335 // If |final_navigation| is null, then this is an "unparented" abort chain, 288 // If |final_navigation| is null, then this is an "unparented" abort chain,
336 // and represents a sequence of provisional aborts that never ends with a 289 // and represents a sequence of provisional aborts that never ends with a
337 // committed load. 290 // committed load.
338 void LogAbortChainHistograms(content::NavigationHandle* final_navigation); 291 void LogAbortChainHistograms(content::NavigationHandle* final_navigation);
339 292
340 void MaybeUpdateURL(content::NavigationHandle* navigation_handle); 293 void MaybeUpdateURL(content::NavigationHandle* navigation_handle);
341 294
342 // Merge values from |new_paint_timing| into |merged_page_timing_|, offsetting
343 // any new timings by the |navigation_start_offset|.
344 void MergePaintTiming(base::TimeDelta navigation_start_offset,
345 const mojom::PaintTiming& new_paint_timing,
346 bool is_main_frame);
347
348 void DispatchTimingUpdates();
349
350 UserInputTracker input_tracker_; 295 UserInputTracker input_tracker_;
351 296
352 // Whether we stopped tracking this navigation after it was initiated. We may 297 // Whether we stopped tracking this navigation after it was initiated. We may
353 // stop tracking a navigation if it doesn't meet the criteria for tracking 298 // stop tracking a navigation if it doesn't meet the criteria for tracking
354 // metrics in DidFinishNavigation. 299 // metrics in DidFinishNavigation.
355 bool did_stop_tracking_; 300 bool did_stop_tracking_;
356 301
357 // Whether the application went into the background when this PageLoadTracker 302 // Whether the application went into the background when this PageLoadTracker
358 // was active. This is a temporary boolean for UMA tracking. 303 // was active. This is a temporary boolean for UMA tracking.
359 bool app_entered_background_; 304 bool app_entered_background_;
(...skipping 29 matching lines...) Expand all
389 334
390 base::TimeTicks page_end_time_; 335 base::TimeTicks page_end_time_;
391 336
392 // We record separate metrics for events that occur after a background, 337 // We record separate metrics for events that occur after a background,
393 // because metrics like layout/paint are delayed artificially 338 // because metrics like layout/paint are delayed artificially
394 // when they occur in the background. 339 // when they occur in the background.
395 base::TimeTicks background_time_; 340 base::TimeTicks background_time_;
396 base::TimeTicks foreground_time_; 341 base::TimeTicks foreground_time_;
397 bool started_in_foreground_; 342 bool started_in_foreground_;
398 343
399 // PageLoadTiming for the currently tracked page. The fields in |paint_timing|
400 // are merged across all frames in the document. All other fields are for the
401 // main frame document.
402 mojom::PageLoadTimingPtr merged_page_timing_;
403 mojom::PageLoadTimingPtr last_dispatched_merged_page_timing_; 344 mojom::PageLoadTimingPtr last_dispatched_merged_page_timing_;
404 345
405 mojom::PageLoadMetadata main_frame_metadata_;
406 mojom::PageLoadMetadataPtr last_dispatched_main_frame_metadata_;
407
408 mojom::PageLoadMetadata subframe_metadata_;
409
410 ui::PageTransition page_transition_; 346 ui::PageTransition page_transition_;
411 347
412 base::Optional<content::GlobalRequestID> navigation_request_id_; 348 base::Optional<content::GlobalRequestID> navigation_request_id_;
413 349
414 // Whether this page load was user initiated. 350 // Whether this page load was user initiated.
415 UserInitiatedInfo user_initiated_info_; 351 UserInitiatedInfo user_initiated_info_;
416 352
417 // This is a subtle member. If a provisional load A gets aborted by 353 // This is a subtle member. If a provisional load A gets aborted by
418 // provisional load B, which gets aborted by C that eventually commits, then 354 // provisional load B, which gets aborted by C that eventually commits, then
419 // there exists an abort chain of length 2, starting at A's navigation_start. 355 // there exists an abort chain of length 2, starting at A's navigation_start.
420 // This is useful because it allows histograming abort chain lengths based on 356 // This is useful because it allows histograming abort chain lengths based on
421 // what the last load's transition type is. i.e. holding down F-5 to spam 357 // what the last load's transition type is. i.e. holding down F-5 to spam
422 // reload will produce a long chain with the RELOAD transition. 358 // reload will produce a long chain with the RELOAD transition.
423 const int aborted_chain_size_; 359 const int aborted_chain_size_;
424 360
425 // This member counts consecutive provisional aborts that share a url. It will 361 // This member counts consecutive provisional aborts that share a url. It will
426 // always be less than or equal to |aborted_chain_size_|. 362 // always be less than or equal to |aborted_chain_size_|.
427 const int aborted_chain_size_same_url_; 363 const int aborted_chain_size_same_url_;
428 364
429 // Interface to chrome features. Must outlive the class. 365 // Interface to chrome features. Must outlive the class.
430 PageLoadMetricsEmbedderInterface* const embedder_interface_; 366 PageLoadMetricsEmbedderInterface* const embedder_interface_;
431 367
432 std::vector<std::unique_ptr<PageLoadMetricsObserver>> observers_; 368 std::vector<std::unique_ptr<PageLoadMetricsObserver>> observers_;
433 369
434 // Navigation start offsets for the most recently committed document in each 370 PageLoadMetricsUpdateDispatcher metrics_update_dispatcher_;
435 // frame.
436 std::map<FrameTreeNodeId, base::TimeDelta> subframe_navigation_start_offset_;
437 371
438 DISALLOW_COPY_AND_ASSIGN(PageLoadTracker); 372 DISALLOW_COPY_AND_ASSIGN(PageLoadTracker);
439 }; 373 };
440 374
441 } // namespace page_load_metrics 375 } // namespace page_load_metrics
442 376
443 #endif // CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_ 377 #endif // CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698