OLD | NEW |
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; |
(...skipping 11 matching lines...) Expand all Loading... |
36 | 37 |
37 namespace internal { | 38 namespace internal { |
38 | 39 |
39 extern const char kErrorEvents[]; | 40 extern const char kErrorEvents[]; |
40 extern const char kAbortChainSizeReload[]; | 41 extern const char kAbortChainSizeReload[]; |
41 extern const char kAbortChainSizeForwardBack[]; | 42 extern const char kAbortChainSizeForwardBack[]; |
42 extern const char kAbortChainSizeNewNavigation[]; | 43 extern const char kAbortChainSizeNewNavigation[]; |
43 extern const char kAbortChainSizeNoCommit[]; | 44 extern const char kAbortChainSizeNoCommit[]; |
44 extern const char kAbortChainSizeSameURL[]; | 45 extern const char kAbortChainSizeSameURL[]; |
45 extern const char kPageLoadCompletedAfterAppBackground[]; | 46 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 | 47 |
90 } // namespace internal | 48 } // namespace internal |
91 | 49 |
92 // These errors are internal to the page_load_metrics subsystem and do not | 50 // These errors are internal to the page_load_metrics subsystem and do not |
93 // reflect actual errors that occur during a page load. | 51 // reflect actual errors that occur during a page load. |
94 // | 52 // |
95 // If you add elements to this enum, make sure you update the enum | 53 // 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 | 54 // value in histograms.xml. Only add elements to the end to prevent |
97 // inconsistencies between versions. | 55 // inconsistencies between versions. |
98 enum InternalErrorLoadEvent { | 56 enum InternalErrorLoadEvent { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 // to access them. | 140 // to access them. |
183 void RecordInternalError(InternalErrorLoadEvent event); | 141 void RecordInternalError(InternalErrorLoadEvent event); |
184 PageEndReason EndReasonForPageTransition(ui::PageTransition transition); | 142 PageEndReason EndReasonForPageTransition(ui::PageTransition transition); |
185 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url); | 143 void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url); |
186 bool IsNavigationUserInitiated(content::NavigationHandle* handle); | 144 bool IsNavigationUserInitiated(content::NavigationHandle* handle); |
187 | 145 |
188 // This class tracks a given page load, starting from navigation start / | 146 // This class tracks a given page load, starting from navigation start / |
189 // provisional load, until a new navigation commits or the navigation fails. | 147 // provisional load, until a new navigation commits or the navigation fails. |
190 // MetricsWebContentsObserver manages a set of provisional PageLoadTrackers, as | 148 // MetricsWebContentsObserver manages a set of provisional PageLoadTrackers, as |
191 // well as a committed PageLoadTracker. | 149 // well as a committed PageLoadTracker. |
192 class PageLoadTracker { | 150 class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client { |
193 public: | 151 public: |
194 // Caller must guarantee that the embedder_interface pointer outlives this | 152 // Caller must guarantee that the embedder_interface pointer outlives this |
195 // class. The PageLoadTracker must not hold on to | 153 // class. The PageLoadTracker must not hold on to |
196 // currently_committed_load_or_null or navigation_handle beyond the scope of | 154 // currently_committed_load_or_null or navigation_handle beyond the scope of |
197 // the constructor. | 155 // the constructor. |
198 PageLoadTracker(bool in_foreground, | 156 PageLoadTracker(bool in_foreground, |
199 PageLoadMetricsEmbedderInterface* embedder_interface, | 157 PageLoadMetricsEmbedderInterface* embedder_interface, |
200 const GURL& currently_committed_url, | 158 const GURL& currently_committed_url, |
201 content::NavigationHandle* navigation_handle, | 159 content::NavigationHandle* navigation_handle, |
202 UserInitiatedInfo user_initiated_info, | 160 UserInitiatedInfo user_initiated_info, |
203 int aborted_chain_size, | 161 int aborted_chain_size, |
204 int aborted_chain_size_same_url); | 162 int aborted_chain_size_same_url); |
205 ~PageLoadTracker(); | 163 ~PageLoadTracker() override; |
| 164 |
| 165 // PageLoadMetricsUpdateDispatcher::Client implementation: |
| 166 void OnTimingChanged() override; |
| 167 void OnMainFrameMetadataChanged() override; |
| 168 void OnSubframeMetadataChanged() override; |
| 169 |
206 void Redirect(content::NavigationHandle* navigation_handle); | 170 void Redirect(content::NavigationHandle* navigation_handle); |
207 void WillProcessNavigationResponse( | 171 void WillProcessNavigationResponse( |
208 content::NavigationHandle* navigation_handle); | 172 content::NavigationHandle* navigation_handle); |
209 void Commit(content::NavigationHandle* navigation_handle); | 173 void Commit(content::NavigationHandle* navigation_handle); |
210 void DidCommitSameDocumentNavigation( | 174 void DidCommitSameDocumentNavigation( |
211 content::NavigationHandle* navigation_handle); | 175 content::NavigationHandle* navigation_handle); |
212 void DidFinishSubFrameNavigation( | 176 void DidFinishSubFrameNavigation( |
213 content::NavigationHandle* navigation_handle); | 177 content::NavigationHandle* navigation_handle); |
214 void FailedProvisionalLoad(content::NavigationHandle* navigation_handle, | 178 void FailedProvisionalLoad(content::NavigationHandle* navigation_handle, |
215 base::TimeTicks failed_load_time); | 179 base::TimeTicks failed_load_time); |
216 void WebContentsHidden(); | 180 void WebContentsHidden(); |
217 void WebContentsShown(); | 181 void WebContentsShown(); |
218 | 182 |
219 void OnInputEvent(const blink::WebInputEvent& event); | 183 void OnInputEvent(const blink::WebInputEvent& event); |
220 | 184 |
221 // Flush any buffered metrics, as part of the metrics subsystem persisting | 185 // Flush any buffered metrics, as part of the metrics subsystem persisting |
222 // metrics as the application goes into the background. The application may be | 186 // metrics as the application goes into the background. The application may be |
223 // killed at any time after this method is invoked without further | 187 // killed at any time after this method is invoked without further |
224 // notification. | 188 // notification. |
225 void FlushMetricsOnAppEnterBackground(); | 189 void FlushMetricsOnAppEnterBackground(); |
226 | 190 |
227 void NotifyClientRedirectTo(const PageLoadTracker& destination); | 191 void NotifyClientRedirectTo(const PageLoadTracker& destination); |
228 | 192 |
229 void UpdateTiming(const mojom::PageLoadTiming& timing, | 193 void UpdateTiming(content::RenderFrameHost* render_frame_host, |
| 194 const mojom::PageLoadTiming& timing, |
230 const mojom::PageLoadMetadata& metadata); | 195 const mojom::PageLoadMetadata& metadata); |
231 | 196 |
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( | 197 void OnStartedResource( |
242 const ExtraRequestStartInfo& extra_request_started_info); | 198 const ExtraRequestStartInfo& extra_request_started_info); |
243 | 199 |
244 void OnLoadedResource( | 200 void OnLoadedResource( |
245 const ExtraRequestCompleteInfo& extra_request_complete_info); | 201 const ExtraRequestCompleteInfo& extra_request_complete_info); |
246 | 202 |
247 // Signals that we should stop tracking metrics for the associated page load. | 203 // 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 | 204 // We may stop tracking a page load if it doesn't meet the criteria for |
249 // tracking metrics in DidFinishNavigation. | 205 // tracking metrics in DidFinishNavigation. |
250 void StopTracking(); | 206 void StopTracking(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 // and is simpler than other feasible methods. See https://goo.gl/WKRG98. | 238 // and is simpler than other feasible methods. See https://goo.gl/WKRG98. |
283 bool IsLikelyProvisionalAbort(base::TimeTicks abort_cause_time) const; | 239 bool IsLikelyProvisionalAbort(base::TimeTicks abort_cause_time) const; |
284 | 240 |
285 bool MatchesOriginalNavigation(content::NavigationHandle* navigation_handle); | 241 bool MatchesOriginalNavigation(content::NavigationHandle* navigation_handle); |
286 | 242 |
287 bool did_commit() const { return did_commit_; } | 243 bool did_commit() const { return did_commit_; } |
288 const GURL& url() const { return url_; } | 244 const GURL& url() const { return url_; } |
289 | 245 |
290 base::TimeTicks navigation_start() const { return navigation_start_; } | 246 base::TimeTicks navigation_start() const { return navigation_start_; } |
291 | 247 |
292 PageLoadExtraInfo ComputePageLoadExtraInfo(); | 248 PageLoadExtraInfo ComputePageLoadExtraInfo() const; |
293 | 249 |
294 ui::PageTransition page_transition() const { return page_transition_; } | 250 ui::PageTransition page_transition() const { return page_transition_; } |
295 | 251 |
296 UserInitiatedInfo user_initiated_info() const { return user_initiated_info_; } | 252 UserInitiatedInfo user_initiated_info() const { return user_initiated_info_; } |
297 | 253 |
298 UserInputTracker* input_tracker() { return &input_tracker_; } | 254 UserInputTracker* input_tracker() { return &input_tracker_; } |
299 | 255 |
300 // Whether this PageLoadTracker has a navigation GlobalRequestID that matches | 256 // Whether this PageLoadTracker has a navigation GlobalRequestID that matches |
301 // the given request_id. This method will return false before | 257 // the given request_id. This method will return false before |
302 // WillProcessNavigationResponse has been invoked, as PageLoadTracker doesn't | 258 // WillProcessNavigationResponse has been invoked, as PageLoadTracker doesn't |
303 // know its GlobalRequestID until WillProcessNavigationResponse has been | 259 // know its GlobalRequestID until WillProcessNavigationResponse has been |
304 // invoked. | 260 // invoked. |
305 bool HasMatchingNavigationRequestID( | 261 bool HasMatchingNavigationRequestID( |
306 const content::GlobalRequestID& request_id) const; | 262 const content::GlobalRequestID& request_id) const; |
307 | 263 |
308 // Invoked when a media element starts playing. | 264 // Invoked when a media element starts playing. |
309 void MediaStartedPlaying( | 265 void MediaStartedPlaying( |
310 const content::WebContentsObserver::MediaPlayerInfo& video_type, | 266 const content::WebContentsObserver::MediaPlayerInfo& video_type, |
311 bool is_in_main_frame); | 267 bool is_in_main_frame); |
312 | 268 |
313 // Invoked on navigations where a navigation delay was added by the | 269 // Invoked on navigations where a navigation delay was added by the |
314 // DelayNavigationThrottle. This is a temporary method that will be removed | 270 // DelayNavigationThrottle. This is a temporary method that will be removed |
315 // once the experiment is complete. | 271 // once the experiment is complete. |
316 void OnNavigationDelayComplete(base::TimeDelta scheduled_delay, | 272 void OnNavigationDelayComplete(base::TimeDelta scheduled_delay, |
317 base::TimeDelta actual_delay); | 273 base::TimeDelta actual_delay); |
318 | 274 |
319 private: | 275 private: |
320 using FrameTreeNodeId = int; | |
321 | |
322 // This function converts a TimeTicks value taken in the browser process | 276 // This function converts a TimeTicks value taken in the browser process |
323 // to navigation_start_ if: | 277 // to navigation_start_ if: |
324 // - base::TimeTicks is not comparable across processes because the clock | 278 // - base::TimeTicks is not comparable across processes because the clock |
325 // is not system wide monotonic. | 279 // is not system wide monotonic. |
326 // - *event_time < navigation_start_ | 280 // - *event_time < navigation_start_ |
327 void ClampBrowserTimestampIfInterProcessTimeTickSkew( | 281 void ClampBrowserTimestampIfInterProcessTimeTickSkew( |
328 base::TimeTicks* event_time); | 282 base::TimeTicks* event_time); |
329 | 283 |
330 void UpdatePageEndInternal(PageEndReason page_end_reason, | 284 void UpdatePageEndInternal(PageEndReason page_end_reason, |
331 UserInitiatedInfo user_initiated_info, | 285 UserInitiatedInfo user_initiated_info, |
332 base::TimeTicks timestamp, | 286 base::TimeTicks timestamp, |
333 bool is_certainly_browser_timestamp); | 287 bool is_certainly_browser_timestamp); |
334 | 288 |
335 // If |final_navigation| is null, then this is an "unparented" abort chain, | 289 // 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 | 290 // and represents a sequence of provisional aborts that never ends with a |
337 // committed load. | 291 // committed load. |
338 void LogAbortChainHistograms(content::NavigationHandle* final_navigation); | 292 void LogAbortChainHistograms(content::NavigationHandle* final_navigation); |
339 | 293 |
340 void MaybeUpdateURL(content::NavigationHandle* navigation_handle); | 294 void MaybeUpdateURL(content::NavigationHandle* navigation_handle); |
341 | 295 |
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_; | 296 UserInputTracker input_tracker_; |
351 | 297 |
352 // Whether we stopped tracking this navigation after it was initiated. We may | 298 // 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 | 299 // stop tracking a navigation if it doesn't meet the criteria for tracking |
354 // metrics in DidFinishNavigation. | 300 // metrics in DidFinishNavigation. |
355 bool did_stop_tracking_; | 301 bool did_stop_tracking_; |
356 | 302 |
357 // Whether the application went into the background when this PageLoadTracker | 303 // Whether the application went into the background when this PageLoadTracker |
358 // was active. This is a temporary boolean for UMA tracking. | 304 // was active. This is a temporary boolean for UMA tracking. |
359 bool app_entered_background_; | 305 bool app_entered_background_; |
(...skipping 29 matching lines...) Expand all Loading... |
389 | 335 |
390 base::TimeTicks page_end_time_; | 336 base::TimeTicks page_end_time_; |
391 | 337 |
392 // We record separate metrics for events that occur after a background, | 338 // We record separate metrics for events that occur after a background, |
393 // because metrics like layout/paint are delayed artificially | 339 // because metrics like layout/paint are delayed artificially |
394 // when they occur in the background. | 340 // when they occur in the background. |
395 base::TimeTicks background_time_; | 341 base::TimeTicks background_time_; |
396 base::TimeTicks foreground_time_; | 342 base::TimeTicks foreground_time_; |
397 bool started_in_foreground_; | 343 bool started_in_foreground_; |
398 | 344 |
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_; | 345 mojom::PageLoadTimingPtr last_dispatched_merged_page_timing_; |
404 | 346 |
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_; | 347 ui::PageTransition page_transition_; |
411 | 348 |
412 base::Optional<content::GlobalRequestID> navigation_request_id_; | 349 base::Optional<content::GlobalRequestID> navigation_request_id_; |
413 | 350 |
414 // Whether this page load was user initiated. | 351 // Whether this page load was user initiated. |
415 UserInitiatedInfo user_initiated_info_; | 352 UserInitiatedInfo user_initiated_info_; |
416 | 353 |
417 // This is a subtle member. If a provisional load A gets aborted by | 354 // 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 | 355 // 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. | 356 // 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 | 357 // 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 | 358 // 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. | 359 // reload will produce a long chain with the RELOAD transition. |
423 const int aborted_chain_size_; | 360 const int aborted_chain_size_; |
424 | 361 |
425 // This member counts consecutive provisional aborts that share a url. It will | 362 // This member counts consecutive provisional aborts that share a url. It will |
426 // always be less than or equal to |aborted_chain_size_|. | 363 // always be less than or equal to |aborted_chain_size_|. |
427 const int aborted_chain_size_same_url_; | 364 const int aborted_chain_size_same_url_; |
428 | 365 |
429 // Interface to chrome features. Must outlive the class. | 366 // Interface to chrome features. Must outlive the class. |
430 PageLoadMetricsEmbedderInterface* const embedder_interface_; | 367 PageLoadMetricsEmbedderInterface* const embedder_interface_; |
431 | 368 |
432 std::vector<std::unique_ptr<PageLoadMetricsObserver>> observers_; | 369 std::vector<std::unique_ptr<PageLoadMetricsObserver>> observers_; |
433 | 370 |
434 // Navigation start offsets for the most recently committed document in each | 371 PageLoadMetricsUpdateDispatcher metrics_update_dispatcher_; |
435 // frame. | |
436 std::map<FrameTreeNodeId, base::TimeDelta> subframe_navigation_start_offset_; | |
437 | 372 |
438 DISALLOW_COPY_AND_ASSIGN(PageLoadTracker); | 373 DISALLOW_COPY_AND_ASSIGN(PageLoadTracker); |
439 }; | 374 }; |
440 | 375 |
441 } // namespace page_load_metrics | 376 } // namespace page_load_metrics |
442 | 377 |
443 #endif // CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_ | 378 #endif // CHROME_BROWSER_PAGE_LOAD_METRICS_PAGE_LOAD_TRACKER_H_ |
OLD | NEW |