| 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 |