| 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 #include "chrome/browser/page_load_metrics/page_load_tracker.h" | 5 #include "chrome/browser/page_load_metrics/page_load_tracker.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <ostream> | 8 #include <ostream> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 // second. | 125 // second. |
| 126 bool EventsInOrder(const base::Optional<base::TimeDelta>& first, | 126 bool EventsInOrder(const base::Optional<base::TimeDelta>& first, |
| 127 const base::Optional<base::TimeDelta>& second) { | 127 const base::Optional<base::TimeDelta>& second) { |
| 128 if (!second) { | 128 if (!second) { |
| 129 return true; | 129 return true; |
| 130 } | 130 } |
| 131 return first && first <= second; | 131 return first && first <= second; |
| 132 } | 132 } |
| 133 | 133 |
| 134 internal::PageLoadTimingStatus IsValidPageLoadTiming( | 134 internal::PageLoadTimingStatus IsValidPageLoadTiming( |
| 135 const PageLoadTiming& timing) { | 135 const mojom::PageLoadTiming& timing) { |
| 136 if (timing.IsEmpty()) | 136 if (page_load_metrics::IsEmpty(timing)) |
| 137 return internal::INVALID_EMPTY_TIMING; | 137 return internal::INVALID_EMPTY_TIMING; |
| 138 | 138 |
| 139 // If we have a non-empty timing, it should always have a navigation start. | 139 // If we have a non-empty timing, it should always have a navigation start. |
| 140 if (timing.navigation_start.is_null()) { | 140 if (timing.navigation_start.is_null()) { |
| 141 LOG(ERROR) << "Received null navigation_start."; | 141 LOG(ERROR) << "Received null navigation_start."; |
| 142 return internal::INVALID_NULL_NAVIGATION_START; | 142 return internal::INVALID_NULL_NAVIGATION_START; |
| 143 } | 143 } |
| 144 | 144 |
| 145 // Verify proper ordering between the various timings. | 145 // Verify proper ordering between the various timings. |
| 146 | 146 |
| 147 if (!EventsInOrder(timing.response_start, timing.parse_timing.parse_start)) { | 147 if (!EventsInOrder(timing.response_start, timing.parse_timing->parse_start)) { |
| 148 // We sometimes get a zero response_start with a non-zero parse start. See | 148 // We sometimes get a zero response_start with a non-zero parse start. See |
| 149 // crbug.com/590212. | 149 // crbug.com/590212. |
| 150 LOG(ERROR) << "Invalid response_start " << timing.response_start | 150 LOG(ERROR) << "Invalid response_start " << timing.response_start |
| 151 << " for parse_start " << timing.parse_timing.parse_start; | 151 << " for parse_start " << timing.parse_timing->parse_start; |
| 152 // When browser-side navigation is enabled, we sometimes encounter this | 152 // When browser-side navigation is enabled, we sometimes encounter this |
| 153 // error case. For now, we disable reporting of this error, since most | 153 // error case. For now, we disable reporting of this error, since most |
| 154 // PageLoadMetricsObservers don't care about response_start and we want to | 154 // PageLoadMetricsObservers don't care about response_start and we want to |
| 155 // see how much closer fixing this error will get us to page load metrics | 155 // see how much closer fixing this error will get us to page load metrics |
| 156 // being consistent with and without browser side navigation enabled. See | 156 // being consistent with and without browser side navigation enabled. See |
| 157 // crbug.com/716587 for more details. | 157 // crbug.com/716587 for more details. |
| 158 // | 158 // |
| 159 // return internal::INVALID_ORDER_RESPONSE_START_PARSE_START; | 159 // return internal::INVALID_ORDER_RESPONSE_START_PARSE_START; |
| 160 } | 160 } |
| 161 | 161 |
| 162 if (!EventsInOrder(timing.parse_timing.parse_start, | 162 if (!EventsInOrder(timing.parse_timing->parse_start, |
| 163 timing.parse_timing.parse_stop)) { | 163 timing.parse_timing->parse_stop)) { |
| 164 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing.parse_start | 164 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing->parse_start |
| 165 << " for parse_stop " << timing.parse_timing.parse_stop; | 165 << " for parse_stop " << timing.parse_timing->parse_stop; |
| 166 return internal::INVALID_ORDER_PARSE_START_PARSE_STOP; | 166 return internal::INVALID_ORDER_PARSE_START_PARSE_STOP; |
| 167 } | 167 } |
| 168 | 168 |
| 169 if (timing.parse_timing.parse_stop) { | 169 if (timing.parse_timing->parse_stop) { |
| 170 const base::TimeDelta parse_duration = | 170 const base::TimeDelta parse_duration = |
| 171 timing.parse_timing.parse_stop.value() - | 171 timing.parse_timing->parse_stop.value() - |
| 172 timing.parse_timing.parse_start.value(); | 172 timing.parse_timing->parse_start.value(); |
| 173 if (timing.parse_timing.parse_blocked_on_script_load_duration > | 173 if (timing.parse_timing->parse_blocked_on_script_load_duration > |
| 174 parse_duration) { | 174 parse_duration) { |
| 175 LOG(ERROR) << "Invalid parse_blocked_on_script_load_duration " | 175 LOG(ERROR) << "Invalid parse_blocked_on_script_load_duration " |
| 176 << timing.parse_timing.parse_blocked_on_script_load_duration | 176 << timing.parse_timing->parse_blocked_on_script_load_duration |
| 177 << " for parse duration " << parse_duration; | 177 << " for parse duration " << parse_duration; |
| 178 return internal::INVALID_SCRIPT_LOAD_LONGER_THAN_PARSE; | 178 return internal::INVALID_SCRIPT_LOAD_LONGER_THAN_PARSE; |
| 179 } | 179 } |
| 180 if (timing.parse_timing.parse_blocked_on_script_execution_duration > | 180 if (timing.parse_timing->parse_blocked_on_script_execution_duration > |
| 181 parse_duration) { | 181 parse_duration) { |
| 182 LOG(ERROR) | 182 LOG(ERROR) |
| 183 << "Invalid parse_blocked_on_script_execution_duration " | 183 << "Invalid parse_blocked_on_script_execution_duration " |
| 184 << timing.parse_timing.parse_blocked_on_script_execution_duration | 184 << timing.parse_timing->parse_blocked_on_script_execution_duration |
| 185 << " for parse duration " << parse_duration; | 185 << " for parse duration " << parse_duration; |
| 186 return internal::INVALID_SCRIPT_EXEC_LONGER_THAN_PARSE; | 186 return internal::INVALID_SCRIPT_EXEC_LONGER_THAN_PARSE; |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 | 189 |
| 190 if (timing.parse_timing | 190 if (timing.parse_timing |
| 191 .parse_blocked_on_script_load_from_document_write_duration > | 191 ->parse_blocked_on_script_load_from_document_write_duration > |
| 192 timing.parse_timing.parse_blocked_on_script_load_duration) { | 192 timing.parse_timing->parse_blocked_on_script_load_duration) { |
| 193 LOG(ERROR) | 193 LOG(ERROR) |
| 194 << "Invalid parse_blocked_on_script_load_from_document_write_duration " | 194 << "Invalid parse_blocked_on_script_load_from_document_write_duration " |
| 195 << timing.parse_timing | 195 << timing.parse_timing |
| 196 .parse_blocked_on_script_load_from_document_write_duration | 196 ->parse_blocked_on_script_load_from_document_write_duration |
| 197 << " for parse_blocked_on_script_load_duration " | 197 << " for parse_blocked_on_script_load_duration " |
| 198 << timing.parse_timing.parse_blocked_on_script_load_duration; | 198 << timing.parse_timing->parse_blocked_on_script_load_duration; |
| 199 return internal::INVALID_SCRIPT_LOAD_DOC_WRITE_LONGER_THAN_SCRIPT_LOAD; | 199 return internal::INVALID_SCRIPT_LOAD_DOC_WRITE_LONGER_THAN_SCRIPT_LOAD; |
| 200 } | 200 } |
| 201 | 201 |
| 202 if (timing.parse_timing | 202 if (timing.parse_timing |
| 203 .parse_blocked_on_script_execution_from_document_write_duration > | 203 ->parse_blocked_on_script_execution_from_document_write_duration > |
| 204 timing.parse_timing.parse_blocked_on_script_execution_duration) { | 204 timing.parse_timing->parse_blocked_on_script_execution_duration) { |
| 205 LOG(ERROR) | 205 LOG(ERROR) |
| 206 << "Invalid " | 206 << "Invalid " |
| 207 "parse_blocked_on_script_execution_from_document_write_duration " | 207 "parse_blocked_on_script_execution_from_document_write_duration " |
| 208 << timing.parse_timing | 208 << timing.parse_timing |
| 209 .parse_blocked_on_script_execution_from_document_write_duration | 209 ->parse_blocked_on_script_execution_from_document_write_duration |
| 210 << " for parse_blocked_on_script_execution_duration " | 210 << " for parse_blocked_on_script_execution_duration " |
| 211 << timing.parse_timing.parse_blocked_on_script_execution_duration; | 211 << timing.parse_timing->parse_blocked_on_script_execution_duration; |
| 212 return internal::INVALID_SCRIPT_EXEC_DOC_WRITE_LONGER_THAN_SCRIPT_EXEC; | 212 return internal::INVALID_SCRIPT_EXEC_DOC_WRITE_LONGER_THAN_SCRIPT_EXEC; |
| 213 } | 213 } |
| 214 | 214 |
| 215 if (!EventsInOrder(timing.parse_timing.parse_stop, | 215 if (!EventsInOrder(timing.parse_timing->parse_stop, |
| 216 timing.document_timing.dom_content_loaded_event_start)) { | 216 timing.document_timing->dom_content_loaded_event_start)) { |
| 217 LOG(ERROR) << "Invalid parse_stop " << timing.parse_timing.parse_stop | 217 LOG(ERROR) << "Invalid parse_stop " << timing.parse_timing->parse_stop |
| 218 << " for dom_content_loaded_event_start " | 218 << " for dom_content_loaded_event_start " |
| 219 << timing.document_timing.dom_content_loaded_event_start; | 219 << timing.document_timing->dom_content_loaded_event_start; |
| 220 return internal::INVALID_ORDER_PARSE_STOP_DOM_CONTENT_LOADED; | 220 return internal::INVALID_ORDER_PARSE_STOP_DOM_CONTENT_LOADED; |
| 221 } | 221 } |
| 222 | 222 |
| 223 if (!EventsInOrder(timing.document_timing.dom_content_loaded_event_start, | 223 if (!EventsInOrder(timing.document_timing->dom_content_loaded_event_start, |
| 224 timing.document_timing.load_event_start)) { | 224 timing.document_timing->load_event_start)) { |
| 225 LOG(ERROR) << "Invalid dom_content_loaded_event_start " | 225 LOG(ERROR) << "Invalid dom_content_loaded_event_start " |
| 226 << timing.document_timing.dom_content_loaded_event_start | 226 << timing.document_timing->dom_content_loaded_event_start |
| 227 << " for load_event_start " | 227 << " for load_event_start " |
| 228 << timing.document_timing.load_event_start; | 228 << timing.document_timing->load_event_start; |
| 229 return internal::INVALID_ORDER_DOM_CONTENT_LOADED_LOAD; | 229 return internal::INVALID_ORDER_DOM_CONTENT_LOADED_LOAD; |
| 230 } | 230 } |
| 231 | 231 |
| 232 if (!EventsInOrder(timing.parse_timing.parse_start, | 232 if (!EventsInOrder(timing.parse_timing->parse_start, |
| 233 timing.document_timing.first_layout)) { | 233 timing.document_timing->first_layout)) { |
| 234 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing.parse_start | 234 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing->parse_start |
| 235 << " for first_layout " << timing.document_timing.first_layout; | 235 << " for first_layout " << timing.document_timing->first_layout; |
| 236 return internal::INVALID_ORDER_PARSE_START_FIRST_LAYOUT; | 236 return internal::INVALID_ORDER_PARSE_START_FIRST_LAYOUT; |
| 237 } | 237 } |
| 238 | 238 |
| 239 if (!EventsInOrder(timing.document_timing.first_layout, | 239 if (!EventsInOrder(timing.document_timing->first_layout, |
| 240 timing.paint_timing.first_paint)) { | 240 timing.paint_timing->first_paint)) { |
| 241 // This can happen when we process an XHTML document that doesn't contain | 241 // This can happen when we process an XHTML document that doesn't contain |
| 242 // well formed XML. See crbug.com/627607. | 242 // well formed XML. See crbug.com/627607. |
| 243 DLOG(ERROR) << "Invalid first_layout " | 243 DLOG(ERROR) << "Invalid first_layout " |
| 244 << timing.document_timing.first_layout << " for first_paint " | 244 << timing.document_timing->first_layout << " for first_paint " |
| 245 << timing.paint_timing.first_paint; | 245 << timing.paint_timing->first_paint; |
| 246 return internal::INVALID_ORDER_FIRST_LAYOUT_FIRST_PAINT; | 246 return internal::INVALID_ORDER_FIRST_LAYOUT_FIRST_PAINT; |
| 247 } | 247 } |
| 248 | 248 |
| 249 if (!EventsInOrder(timing.paint_timing.first_paint, | 249 if (!EventsInOrder(timing.paint_timing->first_paint, |
| 250 timing.paint_timing.first_text_paint)) { | 250 timing.paint_timing->first_text_paint)) { |
| 251 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 251 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
| 252 << " for first_text_paint " | 252 << " for first_text_paint " |
| 253 << timing.paint_timing.first_text_paint; | 253 << timing.paint_timing->first_text_paint; |
| 254 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_TEXT_PAINT; | 254 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_TEXT_PAINT; |
| 255 } | 255 } |
| 256 | 256 |
| 257 if (!EventsInOrder(timing.paint_timing.first_paint, | 257 if (!EventsInOrder(timing.paint_timing->first_paint, |
| 258 timing.paint_timing.first_image_paint)) { | 258 timing.paint_timing->first_image_paint)) { |
| 259 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 259 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
| 260 << " for first_image_paint " | 260 << " for first_image_paint " |
| 261 << timing.paint_timing.first_image_paint; | 261 << timing.paint_timing->first_image_paint; |
| 262 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_IMAGE_PAINT; | 262 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_IMAGE_PAINT; |
| 263 } | 263 } |
| 264 | 264 |
| 265 if (!EventsInOrder(timing.paint_timing.first_paint, | 265 if (!EventsInOrder(timing.paint_timing->first_paint, |
| 266 timing.paint_timing.first_contentful_paint)) { | 266 timing.paint_timing->first_contentful_paint)) { |
| 267 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 267 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
| 268 << " for first_contentful_paint " | 268 << " for first_contentful_paint " |
| 269 << timing.paint_timing.first_contentful_paint; | 269 << timing.paint_timing->first_contentful_paint; |
| 270 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_CONTENTFUL_PAINT; | 270 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_CONTENTFUL_PAINT; |
| 271 } | 271 } |
| 272 | 272 |
| 273 if (!EventsInOrder(timing.paint_timing.first_paint, | 273 if (!EventsInOrder(timing.paint_timing->first_paint, |
| 274 timing.paint_timing.first_meaningful_paint)) { | 274 timing.paint_timing->first_meaningful_paint)) { |
| 275 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 275 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
| 276 << " for first_meaningful_paint " | 276 << " for first_meaningful_paint " |
| 277 << timing.paint_timing.first_meaningful_paint; | 277 << timing.paint_timing->first_meaningful_paint; |
| 278 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_MEANINGFUL_PAINT; | 278 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_MEANINGFUL_PAINT; |
| 279 } | 279 } |
| 280 | 280 |
| 281 return internal::VALID; | 281 return internal::VALID; |
| 282 } | 282 } |
| 283 | 283 |
| 284 // Updates *|inout_existing_value| with |optional_candidate_new_value|, if | 284 // Updates *|inout_existing_value| with |optional_candidate_new_value|, if |
| 285 // either *|inout_existing_value| isn't set, or |optional_candidate_new_value| < | 285 // either *|inout_existing_value| isn't set, or |optional_candidate_new_value| < |
| 286 // |inout_existing_value|. | 286 // |inout_existing_value|. |
| 287 void MaybeUpdateTimeDelta( | 287 void MaybeUpdateTimeDelta( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 314 } | 314 } |
| 315 | 315 |
| 316 *inout_existing_value = candidate_new_value; | 316 *inout_existing_value = candidate_new_value; |
| 317 } | 317 } |
| 318 | 318 |
| 319 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { | 319 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { |
| 320 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, | 320 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, |
| 321 completed_after_background); | 321 completed_after_background); |
| 322 } | 322 } |
| 323 | 323 |
| 324 void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer, | 324 void DispatchObserverTimingCallbacks( |
| 325 const PageLoadTiming& last_timing, | 325 PageLoadMetricsObserver* observer, |
| 326 const PageLoadTiming& new_timing, | 326 const mojom::PageLoadTiming& last_timing, |
| 327 const PageLoadMetadata& last_metadata, | 327 const mojom::PageLoadTiming& new_timing, |
| 328 const PageLoadExtraInfo& extra_info) { | 328 const mojom::PageLoadMetadata& last_metadata, |
| 329 const PageLoadExtraInfo& extra_info) { |
| 329 if (extra_info.main_frame_metadata.behavior_flags != | 330 if (extra_info.main_frame_metadata.behavior_flags != |
| 330 last_metadata.behavior_flags) | 331 last_metadata.behavior_flags) |
| 331 observer->OnLoadingBehaviorObserved(extra_info); | 332 observer->OnLoadingBehaviorObserved(extra_info); |
| 332 if (last_timing != new_timing) | 333 if (!last_timing.Equals(new_timing)) |
| 333 observer->OnTimingUpdate(new_timing, extra_info); | 334 observer->OnTimingUpdate(new_timing, extra_info); |
| 334 if (new_timing.document_timing.dom_content_loaded_event_start && | 335 if (new_timing.document_timing->dom_content_loaded_event_start && |
| 335 !last_timing.document_timing.dom_content_loaded_event_start) | 336 !last_timing.document_timing->dom_content_loaded_event_start) |
| 336 observer->OnDomContentLoadedEventStart(new_timing, extra_info); | 337 observer->OnDomContentLoadedEventStart(new_timing, extra_info); |
| 337 if (new_timing.document_timing.load_event_start && | 338 if (new_timing.document_timing->load_event_start && |
| 338 !last_timing.document_timing.load_event_start) | 339 !last_timing.document_timing->load_event_start) |
| 339 observer->OnLoadEventStart(new_timing, extra_info); | 340 observer->OnLoadEventStart(new_timing, extra_info); |
| 340 if (new_timing.document_timing.first_layout && | 341 if (new_timing.document_timing->first_layout && |
| 341 !last_timing.document_timing.first_layout) | 342 !last_timing.document_timing->first_layout) |
| 342 observer->OnFirstLayout(new_timing, extra_info); | 343 observer->OnFirstLayout(new_timing, extra_info); |
| 343 if (new_timing.paint_timing.first_paint && | 344 if (new_timing.paint_timing->first_paint && |
| 344 !last_timing.paint_timing.first_paint) | 345 !last_timing.paint_timing->first_paint) |
| 345 observer->OnFirstPaintInPage(new_timing, extra_info); | 346 observer->OnFirstPaintInPage(new_timing, extra_info); |
| 346 if (new_timing.paint_timing.first_text_paint && | 347 if (new_timing.paint_timing->first_text_paint && |
| 347 !last_timing.paint_timing.first_text_paint) | 348 !last_timing.paint_timing->first_text_paint) |
| 348 observer->OnFirstTextPaintInPage(new_timing, extra_info); | 349 observer->OnFirstTextPaintInPage(new_timing, extra_info); |
| 349 if (new_timing.paint_timing.first_image_paint && | 350 if (new_timing.paint_timing->first_image_paint && |
| 350 !last_timing.paint_timing.first_image_paint) | 351 !last_timing.paint_timing->first_image_paint) |
| 351 observer->OnFirstImagePaintInPage(new_timing, extra_info); | 352 observer->OnFirstImagePaintInPage(new_timing, extra_info); |
| 352 if (new_timing.paint_timing.first_contentful_paint && | 353 if (new_timing.paint_timing->first_contentful_paint && |
| 353 !last_timing.paint_timing.first_contentful_paint) | 354 !last_timing.paint_timing->first_contentful_paint) |
| 354 observer->OnFirstContentfulPaintInPage(new_timing, extra_info); | 355 observer->OnFirstContentfulPaintInPage(new_timing, extra_info); |
| 355 if (new_timing.paint_timing.first_meaningful_paint && | 356 if (new_timing.paint_timing->first_meaningful_paint && |
| 356 !last_timing.paint_timing.first_meaningful_paint) | 357 !last_timing.paint_timing->first_meaningful_paint) |
| 357 observer->OnFirstMeaningfulPaintInMainFrameDocument(new_timing, extra_info); | 358 observer->OnFirstMeaningfulPaintInMainFrameDocument(new_timing, extra_info); |
| 358 if (new_timing.parse_timing.parse_start && | 359 if (new_timing.parse_timing->parse_start && |
| 359 !last_timing.parse_timing.parse_start) | 360 !last_timing.parse_timing->parse_start) |
| 360 observer->OnParseStart(new_timing, extra_info); | 361 observer->OnParseStart(new_timing, extra_info); |
| 361 if (new_timing.parse_timing.parse_stop && | 362 if (new_timing.parse_timing->parse_stop && |
| 362 !last_timing.parse_timing.parse_stop) | 363 !last_timing.parse_timing->parse_stop) |
| 363 observer->OnParseStop(new_timing, extra_info); | 364 observer->OnParseStop(new_timing, extra_info); |
| 364 } | 365 } |
| 365 | 366 |
| 366 } // namespace | 367 } // namespace |
| 367 | 368 |
| 368 PageLoadTracker::PageLoadTracker( | 369 PageLoadTracker::PageLoadTracker( |
| 369 bool in_foreground, | 370 bool in_foreground, |
| 370 PageLoadMetricsEmbedderInterface* embedder_interface, | 371 PageLoadMetricsEmbedderInterface* embedder_interface, |
| 371 const GURL& currently_committed_url, | 372 const GURL& currently_committed_url, |
| 372 content::NavigationHandle* navigation_handle, | 373 content::NavigationHandle* navigation_handle, |
| 373 UserInitiatedInfo user_initiated_info, | 374 UserInitiatedInfo user_initiated_info, |
| 374 int aborted_chain_size, | 375 int aborted_chain_size, |
| 375 int aborted_chain_size_same_url) | 376 int aborted_chain_size_same_url) |
| 376 : did_stop_tracking_(false), | 377 : did_stop_tracking_(false), |
| 377 app_entered_background_(false), | 378 app_entered_background_(false), |
| 378 navigation_start_(navigation_handle->NavigationStart()), | 379 navigation_start_(navigation_handle->NavigationStart()), |
| 379 url_(navigation_handle->GetURL()), | 380 url_(navigation_handle->GetURL()), |
| 380 start_url_(navigation_handle->GetURL()), | 381 start_url_(navigation_handle->GetURL()), |
| 381 did_commit_(false), | 382 did_commit_(false), |
| 382 page_end_reason_(END_NONE), | 383 page_end_reason_(END_NONE), |
| 383 page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), | 384 page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), |
| 384 started_in_foreground_(in_foreground), | 385 started_in_foreground_(in_foreground), |
| 386 merged_page_timing_(CreatePageLoadTiming()), |
| 387 last_dispatched_merged_page_timing_(CreatePageLoadTiming()), |
| 388 last_dispatched_main_frame_metadata_(mojom::PageLoadMetadata::New()), |
| 385 page_transition_(navigation_handle->GetPageTransition()), | 389 page_transition_(navigation_handle->GetPageTransition()), |
| 386 user_initiated_info_(user_initiated_info), | 390 user_initiated_info_(user_initiated_info), |
| 387 aborted_chain_size_(aborted_chain_size), | 391 aborted_chain_size_(aborted_chain_size), |
| 388 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 392 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
| 389 embedder_interface_(embedder_interface) { | 393 embedder_interface_(embedder_interface) { |
| 390 DCHECK(!navigation_handle->HasCommitted()); | 394 DCHECK(!navigation_handle->HasCommitted()); |
| 391 embedder_interface_->RegisterObservers(this); | 395 embedder_interface_->RegisterObservers(this); |
| 392 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, | 396 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, |
| 393 currently_committed_url, started_in_foreground_); | 397 currently_committed_url, started_in_foreground_); |
| 394 | 398 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 422 if (!failed_provisional_load_info_) | 426 if (!failed_provisional_load_info_) |
| 423 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); | 427 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); |
| 424 | 428 |
| 425 // Don't include any aborts that resulted in a new navigation, as the chain | 429 // Don't include any aborts that resulted in a new navigation, as the chain |
| 426 // length will be included in the aborter PageLoadTracker. | 430 // length will be included in the aborter PageLoadTracker. |
| 427 if (page_end_reason_ != END_RELOAD && | 431 if (page_end_reason_ != END_RELOAD && |
| 428 page_end_reason_ != END_FORWARD_BACK && | 432 page_end_reason_ != END_FORWARD_BACK && |
| 429 page_end_reason_ != END_NEW_NAVIGATION) { | 433 page_end_reason_ != END_NEW_NAVIGATION) { |
| 430 LogAbortChainHistograms(nullptr); | 434 LogAbortChainHistograms(nullptr); |
| 431 } | 435 } |
| 432 } else if (merged_page_timing_.IsEmpty()) { | 436 } else if (page_load_metrics::IsEmpty(*merged_page_timing_)) { |
| 433 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 437 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
| 434 } | 438 } |
| 435 | 439 |
| 436 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 440 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 437 for (const auto& observer : observers_) { | 441 for (const auto& observer : observers_) { |
| 438 if (failed_provisional_load_info_) { | 442 if (failed_provisional_load_info_) { |
| 439 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); | 443 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); |
| 440 } else if (did_commit_) { | 444 } else if (did_commit_) { |
| 441 observer->OnComplete(merged_page_timing_, info); | 445 observer->OnComplete(*merged_page_timing_, info); |
| 442 } | 446 } |
| 443 } | 447 } |
| 444 } | 448 } |
| 445 | 449 |
| 446 void PageLoadTracker::LogAbortChainHistograms( | 450 void PageLoadTracker::LogAbortChainHistograms( |
| 447 content::NavigationHandle* final_navigation) { | 451 content::NavigationHandle* final_navigation) { |
| 448 if (aborted_chain_size_ == 0) | 452 if (aborted_chain_size_ == 0) |
| 449 return; | 453 return; |
| 450 // Note that this could be broken out by this navigation's abort type, if more | 454 // Note that this could be broken out by this navigation's abort type, if more |
| 451 // granularity is needed. Add one to the chain size to count the current | 455 // granularity is needed. Add one to the chain size to count the current |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 // Only log the first time we background in a given page load. | 502 // Only log the first time we background in a given page load. |
| 499 if (background_time_.is_null()) { | 503 if (background_time_.is_null()) { |
| 500 // Make sure we either started in the foreground and haven't been | 504 // Make sure we either started in the foreground and haven't been |
| 501 // foregrounded yet, or started in the background and have already been | 505 // foregrounded yet, or started in the background and have already been |
| 502 // foregrounded. | 506 // foregrounded. |
| 503 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | 507 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); |
| 504 background_time_ = base::TimeTicks::Now(); | 508 background_time_ = base::TimeTicks::Now(); |
| 505 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | 509 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); |
| 506 } | 510 } |
| 507 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 511 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 508 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, merged_page_timing_, info); | 512 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, *merged_page_timing_, info); |
| 509 } | 513 } |
| 510 | 514 |
| 511 void PageLoadTracker::WebContentsShown() { | 515 void PageLoadTracker::WebContentsShown() { |
| 512 // Only log the first time we foreground in a given page load. | 516 // Only log the first time we foreground in a given page load. |
| 513 if (foreground_time_.is_null()) { | 517 if (foreground_time_.is_null()) { |
| 514 // Make sure we either started in the background and haven't been | 518 // Make sure we either started in the background and haven't been |
| 515 // backgrounded yet, or started in the foreground and have already been | 519 // backgrounded yet, or started in the foreground and have already been |
| 516 // backgrounded. | 520 // backgrounded. |
| 517 DCHECK_NE(started_in_foreground_, background_time_.is_null()); | 521 DCHECK_NE(started_in_foreground_, background_time_.is_null()); |
| 518 foreground_time_ = base::TimeTicks::Now(); | 522 foreground_time_ = base::TimeTicks::Now(); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 } | 599 } |
| 596 | 600 |
| 597 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { | 601 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { |
| 598 if (!app_entered_background_) { | 602 if (!app_entered_background_) { |
| 599 RecordAppBackgroundPageLoadCompleted(false); | 603 RecordAppBackgroundPageLoadCompleted(false); |
| 600 app_entered_background_ = true; | 604 app_entered_background_ = true; |
| 601 } | 605 } |
| 602 | 606 |
| 603 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 607 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 604 INVOKE_AND_PRUNE_OBSERVERS(observers_, FlushMetricsOnAppEnterBackground, | 608 INVOKE_AND_PRUNE_OBSERVERS(observers_, FlushMetricsOnAppEnterBackground, |
| 605 merged_page_timing_, info); | 609 *merged_page_timing_, info); |
| 606 } | 610 } |
| 607 | 611 |
| 608 void PageLoadTracker::NotifyClientRedirectTo( | 612 void PageLoadTracker::NotifyClientRedirectTo( |
| 609 const PageLoadTracker& destination) { | 613 const PageLoadTracker& destination) { |
| 610 if (merged_page_timing_.paint_timing.first_paint) { | 614 if (merged_page_timing_->paint_timing->first_paint) { |
| 611 base::TimeTicks first_paint_time = | 615 base::TimeTicks first_paint_time = |
| 612 navigation_start() + | 616 navigation_start() + |
| 613 merged_page_timing_.paint_timing.first_paint.value(); | 617 merged_page_timing_->paint_timing->first_paint.value(); |
| 614 base::TimeDelta first_paint_to_navigation; | 618 base::TimeDelta first_paint_to_navigation; |
| 615 if (destination.navigation_start() > first_paint_time) | 619 if (destination.navigation_start() > first_paint_time) |
| 616 first_paint_to_navigation = | 620 first_paint_to_navigation = |
| 617 destination.navigation_start() - first_paint_time; | 621 destination.navigation_start() - first_paint_time; |
| 618 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, | 622 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, |
| 619 first_paint_to_navigation); | 623 first_paint_to_navigation); |
| 620 } else { | 624 } else { |
| 621 UMA_HISTOGRAM_BOOLEAN(internal::kClientRedirectWithoutPaint, true); | 625 UMA_HISTOGRAM_BOOLEAN(internal::kClientRedirectWithoutPaint, true); |
| 622 } | 626 } |
| 623 } | 627 } |
| 624 | 628 |
| 625 void PageLoadTracker::UpdateSubFrameTiming( | 629 void PageLoadTracker::UpdateSubFrameTiming( |
| 626 content::RenderFrameHost* render_frame_host, | 630 content::RenderFrameHost* render_frame_host, |
| 627 const PageLoadTiming& new_timing, | 631 const mojom::PageLoadTiming& new_timing, |
| 628 const PageLoadMetadata& new_metadata) { | 632 const mojom::PageLoadMetadata& new_metadata) { |
| 629 UpdateSubFrameMetadata(new_metadata); | 633 UpdateSubFrameMetadata(new_metadata); |
| 630 const auto it = subframe_navigation_start_offset_.find( | 634 const auto it = subframe_navigation_start_offset_.find( |
| 631 render_frame_host->GetFrameTreeNodeId()); | 635 render_frame_host->GetFrameTreeNodeId()); |
| 632 if (it == subframe_navigation_start_offset_.end()) { | 636 if (it == subframe_navigation_start_offset_.end()) { |
| 633 // We received timing information for an untracked load. Ignore it. | 637 // We received timing information for an untracked load. Ignore it. |
| 634 return; | 638 return; |
| 635 } | 639 } |
| 636 | 640 |
| 637 base::TimeDelta navigation_start_offset = it->second; | 641 base::TimeDelta navigation_start_offset = it->second; |
| 638 MergePaintTiming(navigation_start_offset, new_timing.paint_timing, | 642 MergePaintTiming(navigation_start_offset, *(new_timing.paint_timing), |
| 639 false /* is_main_frame */); | 643 false /* is_main_frame */); |
| 640 | 644 |
| 641 DispatchTimingUpdates(); | 645 DispatchTimingUpdates(); |
| 642 } | 646 } |
| 643 | 647 |
| 644 void PageLoadTracker::MergePaintTiming( | 648 void PageLoadTracker::MergePaintTiming( |
| 645 base::TimeDelta navigation_start_offset, | 649 base::TimeDelta navigation_start_offset, |
| 646 const page_load_metrics::PaintTiming& new_paint_timing, | 650 const mojom::PaintTiming& new_paint_timing, |
| 647 bool is_main_frame) { | 651 bool is_main_frame) { |
| 648 MaybeUpdateTimeDelta(&merged_page_timing_.paint_timing.first_paint, | 652 MaybeUpdateTimeDelta(&merged_page_timing_->paint_timing->first_paint, |
| 649 navigation_start_offset, new_paint_timing.first_paint); | 653 navigation_start_offset, new_paint_timing.first_paint); |
| 650 MaybeUpdateTimeDelta(&merged_page_timing_.paint_timing.first_text_paint, | 654 MaybeUpdateTimeDelta(&merged_page_timing_->paint_timing->first_text_paint, |
| 651 navigation_start_offset, | 655 navigation_start_offset, |
| 652 new_paint_timing.first_text_paint); | 656 new_paint_timing.first_text_paint); |
| 653 MaybeUpdateTimeDelta(&merged_page_timing_.paint_timing.first_image_paint, | 657 MaybeUpdateTimeDelta(&merged_page_timing_->paint_timing->first_image_paint, |
| 654 navigation_start_offset, | 658 navigation_start_offset, |
| 655 new_paint_timing.first_image_paint); | 659 new_paint_timing.first_image_paint); |
| 656 MaybeUpdateTimeDelta(&merged_page_timing_.paint_timing.first_contentful_paint, | 660 MaybeUpdateTimeDelta( |
| 657 navigation_start_offset, | 661 &merged_page_timing_->paint_timing->first_contentful_paint, |
| 658 new_paint_timing.first_contentful_paint); | 662 navigation_start_offset, new_paint_timing.first_contentful_paint); |
| 659 if (is_main_frame) { | 663 if (is_main_frame) { |
| 660 // first meaningful paint is only tracked in the main frame. | 664 // first meaningful paint is only tracked in the main frame. |
| 661 merged_page_timing_.paint_timing.first_meaningful_paint = | 665 merged_page_timing_->paint_timing->first_meaningful_paint = |
| 662 new_paint_timing.first_meaningful_paint; | 666 new_paint_timing.first_meaningful_paint; |
| 663 } | 667 } |
| 664 } | 668 } |
| 665 | 669 |
| 666 void PageLoadTracker::UpdateSubFrameMetadata( | 670 void PageLoadTracker::UpdateSubFrameMetadata( |
| 667 const PageLoadMetadata& subframe_metadata) { | 671 const mojom::PageLoadMetadata& subframe_metadata) { |
| 668 // Merge the subframe loading behavior flags with any we've already observed, | 672 // Merge the subframe loading behavior flags with any we've already observed, |
| 669 // possibly from other subframes. | 673 // possibly from other subframes. |
| 670 const int last_subframe_loading_behavior_flags = | 674 const int last_subframe_loading_behavior_flags = |
| 671 subframe_metadata_.behavior_flags; | 675 subframe_metadata_.behavior_flags; |
| 672 subframe_metadata_.behavior_flags |= subframe_metadata.behavior_flags; | 676 subframe_metadata_.behavior_flags |= subframe_metadata.behavior_flags; |
| 673 if (last_subframe_loading_behavior_flags == subframe_metadata_.behavior_flags) | 677 if (last_subframe_loading_behavior_flags == subframe_metadata_.behavior_flags) |
| 674 return; | 678 return; |
| 675 | 679 |
| 676 PageLoadExtraInfo extra_info(ComputePageLoadExtraInfo()); | 680 PageLoadExtraInfo extra_info(ComputePageLoadExtraInfo()); |
| 677 for (const auto& observer : observers_) { | 681 for (const auto& observer : observers_) { |
| 678 observer->OnLoadingBehaviorObserved(extra_info); | 682 observer->OnLoadingBehaviorObserved(extra_info); |
| 679 } | 683 } |
| 680 } | 684 } |
| 681 | 685 |
| 682 void PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing, | 686 void PageLoadTracker::UpdateTiming( |
| 683 const PageLoadMetadata& new_metadata) { | 687 const mojom::PageLoadTiming& new_timing, |
| 688 const mojom::PageLoadMetadata& new_metadata) { |
| 684 // Throw away IPCs that are not relevant to the current navigation. | 689 // Throw away IPCs that are not relevant to the current navigation. |
| 685 // Two timing structures cannot refer to the same navigation if they indicate | 690 // Two timing structures cannot refer to the same navigation if they indicate |
| 686 // that a navigation started at different times, so a new timing struct with a | 691 // that a navigation started at different times, so a new timing struct with a |
| 687 // different start time from an earlier struct is considered invalid. | 692 // different start time from an earlier struct is considered invalid. |
| 688 const bool valid_timing_descendent = | 693 const bool valid_timing_descendent = |
| 689 merged_page_timing_.navigation_start.is_null() || | 694 merged_page_timing_->navigation_start.is_null() || |
| 690 merged_page_timing_.navigation_start == new_timing.navigation_start; | 695 merged_page_timing_->navigation_start == new_timing.navigation_start; |
| 691 if (!valid_timing_descendent) { | 696 if (!valid_timing_descendent) { |
| 692 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT); | 697 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT); |
| 693 return; | 698 return; |
| 694 } | 699 } |
| 695 | 700 |
| 696 // Ensure flags sent previously are still present in the new metadata fields. | 701 // Ensure flags sent previously are still present in the new metadata fields. |
| 697 const bool valid_behavior_descendent = | 702 const bool valid_behavior_descendent = |
| 698 (main_frame_metadata_.behavior_flags & new_metadata.behavior_flags) == | 703 (main_frame_metadata_.behavior_flags & new_metadata.behavior_flags) == |
| 699 main_frame_metadata_.behavior_flags; | 704 main_frame_metadata_.behavior_flags; |
| 700 if (!valid_behavior_descendent) { | 705 if (!valid_behavior_descendent) { |
| 701 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_BEHAVIOR_DESCENDENT); | 706 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_BEHAVIOR_DESCENDENT); |
| 702 return; | 707 return; |
| 703 } | 708 } |
| 704 internal::PageLoadTimingStatus status = IsValidPageLoadTiming(new_timing); | 709 internal::PageLoadTimingStatus status = IsValidPageLoadTiming(new_timing); |
| 705 UMA_HISTOGRAM_ENUMERATION(internal::kPageLoadTimingStatus, status, | 710 UMA_HISTOGRAM_ENUMERATION(internal::kPageLoadTimingStatus, status, |
| 706 internal::LAST_PAGE_LOAD_TIMING_STATUS); | 711 internal::LAST_PAGE_LOAD_TIMING_STATUS); |
| 707 if (status != internal::VALID) { | 712 if (status != internal::VALID) { |
| 708 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING); | 713 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING); |
| 709 return; | 714 return; |
| 710 } | 715 } |
| 711 | 716 |
| 712 DCHECK(did_commit_); // OnCommit() must be called first. | 717 DCHECK(did_commit_); // OnCommit() must be called first. |
| 713 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() | 718 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() |
| 714 // must be called before DispatchObserverTimingCallbacks, but its | 719 // must be called before DispatchObserverTimingCallbacks, but its |
| 715 // implementation depends on the state of main_frame_metadata_, so we need | 720 // implementation depends on the state of main_frame_metadata_, so we need |
| 716 // to update main_frame_metadata_ before calling GetPageLoadMetricsInfo. | 721 // to update main_frame_metadata_ before calling GetPageLoadMetricsInfo. |
| 717 // Thus, we make a copy of timing here, update timing_ and | 722 // Thus, we make a copy of timing here, update merged_page_timing_ and |
| 718 // main_frame_metadata_, and then proceed to dispatch the observer timing | 723 // main_frame_metadata_, and then proceed to dispatch the observer timing |
| 719 // callbacks. | 724 // callbacks. |
| 720 const PaintTiming last_paint_timing = merged_page_timing_.paint_timing; | 725 const mojom::PaintTimingPtr last_paint_timing = |
| 726 std::move(merged_page_timing_->paint_timing); |
| 721 | 727 |
| 722 // Update the merged_page_timing_, making sure to merge the previously | 728 // Update the merged_page_timing_, making sure to merge the previously |
| 723 // observed |paint_timing|, which is tracked across all frames in the page. | 729 // observed |paint_timing|, which is tracked across all frames in the page. |
| 724 merged_page_timing_ = new_timing; | 730 merged_page_timing_ = new_timing.Clone(); |
| 725 merged_page_timing_.paint_timing = last_paint_timing; | 731 merged_page_timing_->paint_timing = last_paint_timing.Clone(); |
| 726 MergePaintTiming(base::TimeDelta(), new_timing.paint_timing, | 732 MergePaintTiming(base::TimeDelta(), *new_timing.paint_timing, |
| 727 true /* is_main_frame */); | 733 true /* is_main_frame */); |
| 728 | 734 |
| 729 main_frame_metadata_ = new_metadata; | 735 main_frame_metadata_ = new_metadata; |
| 730 | 736 |
| 731 DispatchTimingUpdates(); | 737 DispatchTimingUpdates(); |
| 732 } | 738 } |
| 733 | 739 |
| 734 void PageLoadTracker::DispatchTimingUpdates() { | 740 void PageLoadTracker::DispatchTimingUpdates() { |
| 735 if (last_dispatched_merged_page_timing_ == merged_page_timing_ && | 741 if (last_dispatched_merged_page_timing_->Equals(*merged_page_timing_) && |
| 736 last_dispatched_main_frame_metadata_ == main_frame_metadata_) { | 742 last_dispatched_main_frame_metadata_->Equals(main_frame_metadata_)) { |
| 737 return; | 743 return; |
| 738 } | 744 } |
| 739 | 745 |
| 740 if (merged_page_timing_.paint_timing.first_paint) { | 746 if (merged_page_timing_->paint_timing->first_paint) { |
| 741 if (!merged_page_timing_.parse_timing.parse_start || | 747 if (!merged_page_timing_->parse_timing->parse_start || |
| 742 !merged_page_timing_.document_timing.first_layout) { | 748 !merged_page_timing_->document_timing->first_layout) { |
| 743 // When merging paint events across frames, we can sometimes encounter | 749 // When merging paint events across frames, we can sometimes encounter |
| 744 // cases where we've received a first paint event for a child frame before | 750 // cases where we've received a first paint event for a child frame before |
| 745 // receiving required earlier events in the main frame, due to buffering | 751 // receiving required earlier events in the main frame, due to buffering |
| 746 // in the render process which results in out of order delivery. For | 752 // in the render process which results in out of order delivery. For |
| 747 // example, we may receive a notification for a first paint in a child | 753 // example, we may receive a notification for a first paint in a child |
| 748 // frame before we've received a notification for parse start or first | 754 // frame before we've received a notification for parse start or first |
| 749 // layout in the main frame. In these cases, we delay sending timing | 755 // layout in the main frame. In these cases, we delay sending timing |
| 750 // updates until we've received all expected events (e.g. wait to receive | 756 // updates until we've received all expected events (e.g. wait to receive |
| 751 // a parse or layout event before dispatching a paint event), so observers | 757 // a parse or layout event before dispatching a paint event), so observers |
| 752 // can make assumptions about ordering of these events in their callbacks. | 758 // can make assumptions about ordering of these events in their callbacks. |
| 753 return; | 759 return; |
| 754 } | 760 } |
| 755 } | 761 } |
| 756 | 762 |
| 757 internal::PageLoadTimingStatus status = | 763 internal::PageLoadTimingStatus status = |
| 758 IsValidPageLoadTiming(merged_page_timing_); | 764 IsValidPageLoadTiming(*merged_page_timing_); |
| 759 UMA_HISTOGRAM_ENUMERATION(internal::kPageLoadTimingDispatchStatus, status, | 765 UMA_HISTOGRAM_ENUMERATION(internal::kPageLoadTimingDispatchStatus, status, |
| 760 internal::LAST_PAGE_LOAD_TIMING_STATUS); | 766 internal::LAST_PAGE_LOAD_TIMING_STATUS); |
| 761 | 767 |
| 762 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 768 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 763 for (const auto& observer : observers_) { | 769 for (const auto& observer : observers_) { |
| 764 DispatchObserverTimingCallbacks( | 770 DispatchObserverTimingCallbacks( |
| 765 observer.get(), last_dispatched_merged_page_timing_, | 771 observer.get(), *last_dispatched_merged_page_timing_, |
| 766 merged_page_timing_, last_dispatched_main_frame_metadata_, info); | 772 *merged_page_timing_, *last_dispatched_main_frame_metadata_, info); |
| 767 } | 773 } |
| 768 last_dispatched_merged_page_timing_ = merged_page_timing_; | 774 last_dispatched_merged_page_timing_ = merged_page_timing_->Clone(); |
| 769 last_dispatched_main_frame_metadata_ = main_frame_metadata_; | 775 last_dispatched_main_frame_metadata_ = main_frame_metadata_.Clone(); |
| 770 } | 776 } |
| 771 | 777 |
| 772 void PageLoadTracker::OnStartedResource( | 778 void PageLoadTracker::OnStartedResource( |
| 773 const ExtraRequestStartInfo& extra_request_start_info) { | 779 const ExtraRequestStartInfo& extra_request_start_info) { |
| 774 for (const auto& observer : observers_) { | 780 for (const auto& observer : observers_) { |
| 775 observer->OnStartedResource(extra_request_start_info); | 781 observer->OnStartedResource(extra_request_start_info); |
| 776 } | 782 } |
| 777 } | 783 } |
| 778 | 784 |
| 779 void PageLoadTracker::OnLoadedResource( | 785 void PageLoadTracker::OnLoadedResource( |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 observer->MediaStartedPlaying(video_type, is_in_main_frame); | 960 observer->MediaStartedPlaying(video_type, is_in_main_frame); |
| 955 } | 961 } |
| 956 | 962 |
| 957 void PageLoadTracker::OnNavigationDelayComplete(base::TimeDelta scheduled_delay, | 963 void PageLoadTracker::OnNavigationDelayComplete(base::TimeDelta scheduled_delay, |
| 958 base::TimeDelta actual_delay) { | 964 base::TimeDelta actual_delay) { |
| 959 for (const auto& observer : observers_) | 965 for (const auto& observer : observers_) |
| 960 observer->OnNavigationDelayComplete(scheduled_delay, actual_delay); | 966 observer->OnNavigationDelayComplete(scheduled_delay, actual_delay); |
| 961 } | 967 } |
| 962 | 968 |
| 963 } // namespace page_load_metrics | 969 } // namespace page_load_metrics |
| OLD | NEW |