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 |