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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 // second. | 121 // second. |
122 bool EventsInOrder(const base::Optional<base::TimeDelta>& first, | 122 bool EventsInOrder(const base::Optional<base::TimeDelta>& first, |
123 const base::Optional<base::TimeDelta>& second) { | 123 const base::Optional<base::TimeDelta>& second) { |
124 if (!second) { | 124 if (!second) { |
125 return true; | 125 return true; |
126 } | 126 } |
127 return first && first <= second; | 127 return first && first <= second; |
128 } | 128 } |
129 | 129 |
130 internal::PageLoadTimingStatus IsValidPageLoadTiming( | 130 internal::PageLoadTimingStatus IsValidPageLoadTiming( |
131 const PageLoadTiming& timing) { | 131 const mojom::PageLoadTiming& timing) { |
132 if (timing.IsEmpty()) | 132 if (page_load_metrics::IsEmpty(timing)) |
133 return internal::INVALID_EMPTY_TIMING; | 133 return internal::INVALID_EMPTY_TIMING; |
134 | 134 |
135 // If we have a non-empty timing, it should always have a navigation start. | 135 // If we have a non-empty timing, it should always have a navigation start. |
136 if (timing.navigation_start.is_null()) { | 136 if (timing.navigation_start.is_null()) { |
137 LOG(ERROR) << "Received null navigation_start."; | 137 LOG(ERROR) << "Received null navigation_start."; |
138 return internal::INVALID_NULL_NAVIGATION_START; | 138 return internal::INVALID_NULL_NAVIGATION_START; |
139 } | 139 } |
140 | 140 |
141 // Verify proper ordering between the various timings. | 141 // Verify proper ordering between the various timings. |
142 | 142 |
143 if (!EventsInOrder(timing.response_start, timing.parse_timing.parse_start)) { | 143 if (!EventsInOrder(timing.response_start, timing.parse_timing->parse_start)) { |
144 // We sometimes get a zero response_start with a non-zero parse start. See | 144 // We sometimes get a zero response_start with a non-zero parse start. See |
145 // crbug.com/590212. | 145 // crbug.com/590212. |
146 LOG(ERROR) << "Invalid response_start " << timing.response_start | 146 LOG(ERROR) << "Invalid response_start " << timing.response_start |
147 << " for parse_start " << timing.parse_timing.parse_start; | 147 << " for parse_start " << timing.parse_timing->parse_start; |
148 // When browser-side navigation is enabled, we sometimes encounter this | 148 // When browser-side navigation is enabled, we sometimes encounter this |
149 // error case. For now, we disable reporting of this error, since most | 149 // error case. For now, we disable reporting of this error, since most |
150 // PageLoadMetricsObservers don't care about response_start and we want to | 150 // PageLoadMetricsObservers don't care about response_start and we want to |
151 // see how much closer fixing this error will get us to page load metrics | 151 // see how much closer fixing this error will get us to page load metrics |
152 // being consistent with and without browser side navigation enabled. See | 152 // being consistent with and without browser side navigation enabled. See |
153 // crbug.com/716587 for more details. | 153 // crbug.com/716587 for more details. |
154 // | 154 // |
155 // return internal::INVALID_ORDER_RESPONSE_START_PARSE_START; | 155 // return internal::INVALID_ORDER_RESPONSE_START_PARSE_START; |
156 } | 156 } |
157 | 157 |
158 if (!EventsInOrder(timing.parse_timing.parse_start, | 158 if (!EventsInOrder(timing.parse_timing->parse_start, |
159 timing.parse_timing.parse_stop)) { | 159 timing.parse_timing->parse_stop)) { |
160 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing.parse_start | 160 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing->parse_start |
161 << " for parse_stop " << timing.parse_timing.parse_stop; | 161 << " for parse_stop " << timing.parse_timing->parse_stop; |
162 return internal::INVALID_ORDER_PARSE_START_PARSE_STOP; | 162 return internal::INVALID_ORDER_PARSE_START_PARSE_STOP; |
163 } | 163 } |
164 | 164 |
165 if (timing.parse_timing.parse_stop) { | 165 if (timing.parse_timing->parse_stop) { |
166 const base::TimeDelta parse_duration = | 166 const base::TimeDelta parse_duration = |
167 timing.parse_timing.parse_stop.value() - | 167 timing.parse_timing->parse_stop.value() - |
168 timing.parse_timing.parse_start.value(); | 168 timing.parse_timing->parse_start.value(); |
169 if (timing.parse_timing.parse_blocked_on_script_load_duration > | 169 if (timing.parse_timing->parse_blocked_on_script_load_duration > |
170 parse_duration) { | 170 parse_duration) { |
171 LOG(ERROR) << "Invalid parse_blocked_on_script_load_duration " | 171 LOG(ERROR) << "Invalid parse_blocked_on_script_load_duration " |
172 << timing.parse_timing.parse_blocked_on_script_load_duration | 172 << timing.parse_timing->parse_blocked_on_script_load_duration |
173 << " for parse duration " << parse_duration; | 173 << " for parse duration " << parse_duration; |
174 return internal::INVALID_SCRIPT_LOAD_LONGER_THAN_PARSE; | 174 return internal::INVALID_SCRIPT_LOAD_LONGER_THAN_PARSE; |
175 } | 175 } |
176 if (timing.parse_timing.parse_blocked_on_script_execution_duration > | 176 if (timing.parse_timing->parse_blocked_on_script_execution_duration > |
177 parse_duration) { | 177 parse_duration) { |
178 LOG(ERROR) | 178 LOG(ERROR) |
179 << "Invalid parse_blocked_on_script_execution_duration " | 179 << "Invalid parse_blocked_on_script_execution_duration " |
180 << timing.parse_timing.parse_blocked_on_script_execution_duration | 180 << timing.parse_timing->parse_blocked_on_script_execution_duration |
181 << " for parse duration " << parse_duration; | 181 << " for parse duration " << parse_duration; |
182 return internal::INVALID_SCRIPT_EXEC_LONGER_THAN_PARSE; | 182 return internal::INVALID_SCRIPT_EXEC_LONGER_THAN_PARSE; |
183 } | 183 } |
184 } | 184 } |
185 | 185 |
186 if (timing.parse_timing | 186 if (timing.parse_timing |
187 .parse_blocked_on_script_load_from_document_write_duration > | 187 ->parse_blocked_on_script_load_from_document_write_duration > |
188 timing.parse_timing.parse_blocked_on_script_load_duration) { | 188 timing.parse_timing->parse_blocked_on_script_load_duration) { |
189 LOG(ERROR) | 189 LOG(ERROR) |
190 << "Invalid parse_blocked_on_script_load_from_document_write_duration " | 190 << "Invalid parse_blocked_on_script_load_from_document_write_duration " |
191 << timing.parse_timing | 191 << timing.parse_timing |
192 .parse_blocked_on_script_load_from_document_write_duration | 192 ->parse_blocked_on_script_load_from_document_write_duration |
193 << " for parse_blocked_on_script_load_duration " | 193 << " for parse_blocked_on_script_load_duration " |
194 << timing.parse_timing.parse_blocked_on_script_load_duration; | 194 << timing.parse_timing->parse_blocked_on_script_load_duration; |
195 return internal::INVALID_SCRIPT_LOAD_DOC_WRITE_LONGER_THAN_SCRIPT_LOAD; | 195 return internal::INVALID_SCRIPT_LOAD_DOC_WRITE_LONGER_THAN_SCRIPT_LOAD; |
196 } | 196 } |
197 | 197 |
198 if (timing.parse_timing | 198 if (timing.parse_timing |
199 .parse_blocked_on_script_execution_from_document_write_duration > | 199 ->parse_blocked_on_script_execution_from_document_write_duration > |
200 timing.parse_timing.parse_blocked_on_script_execution_duration) { | 200 timing.parse_timing->parse_blocked_on_script_execution_duration) { |
201 LOG(ERROR) | 201 LOG(ERROR) |
202 << "Invalid " | 202 << "Invalid " |
203 "parse_blocked_on_script_execution_from_document_write_duration " | 203 "parse_blocked_on_script_execution_from_document_write_duration " |
204 << timing.parse_timing | 204 << timing.parse_timing |
205 .parse_blocked_on_script_execution_from_document_write_duration | 205 ->parse_blocked_on_script_execution_from_document_write_duration |
206 << " for parse_blocked_on_script_execution_duration " | 206 << " for parse_blocked_on_script_execution_duration " |
207 << timing.parse_timing.parse_blocked_on_script_execution_duration; | 207 << timing.parse_timing->parse_blocked_on_script_execution_duration; |
208 return internal::INVALID_SCRIPT_EXEC_DOC_WRITE_LONGER_THAN_SCRIPT_EXEC; | 208 return internal::INVALID_SCRIPT_EXEC_DOC_WRITE_LONGER_THAN_SCRIPT_EXEC; |
209 } | 209 } |
210 | 210 |
211 if (!EventsInOrder(timing.parse_timing.parse_stop, | 211 if (!EventsInOrder(timing.parse_timing->parse_stop, |
212 timing.document_timing.dom_content_loaded_event_start)) { | 212 timing.document_timing->dom_content_loaded_event_start)) { |
213 LOG(ERROR) << "Invalid parse_stop " << timing.parse_timing.parse_stop | 213 LOG(ERROR) << "Invalid parse_stop " << timing.parse_timing->parse_stop |
214 << " for dom_content_loaded_event_start " | 214 << " for dom_content_loaded_event_start " |
215 << timing.document_timing.dom_content_loaded_event_start; | 215 << timing.document_timing->dom_content_loaded_event_start; |
216 return internal::INVALID_ORDER_PARSE_STOP_DOM_CONTENT_LOADED; | 216 return internal::INVALID_ORDER_PARSE_STOP_DOM_CONTENT_LOADED; |
217 } | 217 } |
218 | 218 |
219 if (!EventsInOrder(timing.document_timing.dom_content_loaded_event_start, | 219 if (!EventsInOrder(timing.document_timing->dom_content_loaded_event_start, |
220 timing.document_timing.load_event_start)) { | 220 timing.document_timing->load_event_start)) { |
221 LOG(ERROR) << "Invalid dom_content_loaded_event_start " | 221 LOG(ERROR) << "Invalid dom_content_loaded_event_start " |
222 << timing.document_timing.dom_content_loaded_event_start | 222 << timing.document_timing->dom_content_loaded_event_start |
223 << " for load_event_start " | 223 << " for load_event_start " |
224 << timing.document_timing.load_event_start; | 224 << timing.document_timing->load_event_start; |
225 return internal::INVALID_ORDER_DOM_CONTENT_LOADED_LOAD; | 225 return internal::INVALID_ORDER_DOM_CONTENT_LOADED_LOAD; |
226 } | 226 } |
227 | 227 |
228 if (!EventsInOrder(timing.parse_timing.parse_start, | 228 if (!EventsInOrder(timing.parse_timing->parse_start, |
229 timing.document_timing.first_layout)) { | 229 timing.document_timing->first_layout)) { |
230 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing.parse_start | 230 LOG(ERROR) << "Invalid parse_start " << timing.parse_timing->parse_start |
231 << " for first_layout " << timing.document_timing.first_layout; | 231 << " for first_layout " << timing.document_timing->first_layout; |
232 return internal::INVALID_ORDER_PARSE_START_FIRST_LAYOUT; | 232 return internal::INVALID_ORDER_PARSE_START_FIRST_LAYOUT; |
233 } | 233 } |
234 | 234 |
235 if (!EventsInOrder(timing.document_timing.first_layout, | 235 if (!EventsInOrder(timing.document_timing->first_layout, |
236 timing.paint_timing.first_paint)) { | 236 timing.paint_timing->first_paint)) { |
237 // This can happen when we process an XHTML document that doesn't contain | 237 // This can happen when we process an XHTML document that doesn't contain |
238 // well formed XML. See crbug.com/627607. | 238 // well formed XML. See crbug.com/627607. |
239 DLOG(ERROR) << "Invalid first_layout " | 239 DLOG(ERROR) << "Invalid first_layout " |
240 << timing.document_timing.first_layout << " for first_paint " | 240 << timing.document_timing->first_layout << " for first_paint " |
241 << timing.paint_timing.first_paint; | 241 << timing.paint_timing->first_paint; |
242 return internal::INVALID_ORDER_FIRST_LAYOUT_FIRST_PAINT; | 242 return internal::INVALID_ORDER_FIRST_LAYOUT_FIRST_PAINT; |
243 } | 243 } |
244 | 244 |
245 if (!EventsInOrder(timing.paint_timing.first_paint, | 245 if (!EventsInOrder(timing.paint_timing->first_paint, |
246 timing.paint_timing.first_text_paint)) { | 246 timing.paint_timing->first_text_paint)) { |
247 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 247 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
248 << " for first_text_paint " | 248 << " for first_text_paint " |
249 << timing.paint_timing.first_text_paint; | 249 << timing.paint_timing->first_text_paint; |
250 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_TEXT_PAINT; | 250 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_TEXT_PAINT; |
251 } | 251 } |
252 | 252 |
253 if (!EventsInOrder(timing.paint_timing.first_paint, | 253 if (!EventsInOrder(timing.paint_timing->first_paint, |
254 timing.paint_timing.first_image_paint)) { | 254 timing.paint_timing->first_image_paint)) { |
255 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 255 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
256 << " for first_image_paint " | 256 << " for first_image_paint " |
257 << timing.paint_timing.first_image_paint; | 257 << timing.paint_timing->first_image_paint; |
258 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_IMAGE_PAINT; | 258 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_IMAGE_PAINT; |
259 } | 259 } |
260 | 260 |
261 if (!EventsInOrder(timing.paint_timing.first_paint, | 261 if (!EventsInOrder(timing.paint_timing->first_paint, |
262 timing.paint_timing.first_contentful_paint)) { | 262 timing.paint_timing->first_contentful_paint)) { |
263 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 263 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
264 << " for first_contentful_paint " | 264 << " for first_contentful_paint " |
265 << timing.paint_timing.first_contentful_paint; | 265 << timing.paint_timing->first_contentful_paint; |
266 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_CONTENTFUL_PAINT; | 266 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_CONTENTFUL_PAINT; |
267 } | 267 } |
268 | 268 |
269 if (!EventsInOrder(timing.paint_timing.first_paint, | 269 if (!EventsInOrder(timing.paint_timing->first_paint, |
270 timing.paint_timing.first_meaningful_paint)) { | 270 timing.paint_timing->first_meaningful_paint)) { |
271 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing.first_paint | 271 LOG(ERROR) << "Invalid first_paint " << timing.paint_timing->first_paint |
272 << " for first_meaningful_paint " | 272 << " for first_meaningful_paint " |
273 << timing.paint_timing.first_meaningful_paint; | 273 << timing.paint_timing->first_meaningful_paint; |
274 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_MEANINGFUL_PAINT; | 274 return internal::INVALID_ORDER_FIRST_PAINT_FIRST_MEANINGFUL_PAINT; |
275 } | 275 } |
276 | 276 |
277 return internal::VALID; | 277 return internal::VALID; |
278 } | 278 } |
279 | 279 |
280 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { | 280 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { |
281 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, | 281 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, |
282 completed_after_background); | 282 completed_after_background); |
283 } | 283 } |
284 | 284 |
285 void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer, | 285 void DispatchObserverTimingCallbacks( |
286 const PageLoadTiming& last_timing, | 286 PageLoadMetricsObserver* observer, |
287 const PageLoadTiming& new_timing, | 287 const mojom::PageLoadTiming& last_timing, |
288 const PageLoadMetadata& last_metadata, | 288 const mojom::PageLoadTiming& new_timing, |
289 const PageLoadExtraInfo& extra_info) { | 289 const mojom::PageLoadMetadata& last_metadata, |
| 290 const PageLoadExtraInfo& extra_info) { |
290 if (extra_info.main_frame_metadata.behavior_flags != | 291 if (extra_info.main_frame_metadata.behavior_flags != |
291 last_metadata.behavior_flags) | 292 last_metadata.behavior_flags) |
292 observer->OnLoadingBehaviorObserved(extra_info); | 293 observer->OnLoadingBehaviorObserved(extra_info); |
293 if (last_timing != new_timing) | 294 if (!last_timing.Equals(new_timing)) |
294 observer->OnTimingUpdate(new_timing, extra_info); | 295 observer->OnTimingUpdate(new_timing, extra_info); |
295 if (new_timing.document_timing.dom_content_loaded_event_start && | 296 if (new_timing.document_timing->dom_content_loaded_event_start && |
296 !last_timing.document_timing.dom_content_loaded_event_start) | 297 !last_timing.document_timing->dom_content_loaded_event_start) |
297 observer->OnDomContentLoadedEventStart(new_timing, extra_info); | 298 observer->OnDomContentLoadedEventStart(new_timing, extra_info); |
298 if (new_timing.document_timing.load_event_start && | 299 if (new_timing.document_timing->load_event_start && |
299 !last_timing.document_timing.load_event_start) | 300 !last_timing.document_timing->load_event_start) |
300 observer->OnLoadEventStart(new_timing, extra_info); | 301 observer->OnLoadEventStart(new_timing, extra_info); |
301 if (new_timing.document_timing.first_layout && | 302 if (new_timing.document_timing->first_layout && |
302 !last_timing.document_timing.first_layout) | 303 !last_timing.document_timing->first_layout) |
303 observer->OnFirstLayout(new_timing, extra_info); | 304 observer->OnFirstLayout(new_timing, extra_info); |
304 if (new_timing.paint_timing.first_paint && | 305 if (new_timing.paint_timing->first_paint && |
305 !last_timing.paint_timing.first_paint) | 306 !last_timing.paint_timing->first_paint) |
306 observer->OnFirstPaint(new_timing, extra_info); | 307 observer->OnFirstPaint(new_timing, extra_info); |
307 if (new_timing.paint_timing.first_text_paint && | 308 if (new_timing.paint_timing->first_text_paint && |
308 !last_timing.paint_timing.first_text_paint) | 309 !last_timing.paint_timing->first_text_paint) |
309 observer->OnFirstTextPaint(new_timing, extra_info); | 310 observer->OnFirstTextPaint(new_timing, extra_info); |
310 if (new_timing.paint_timing.first_image_paint && | 311 if (new_timing.paint_timing->first_image_paint && |
311 !last_timing.paint_timing.first_image_paint) | 312 !last_timing.paint_timing->first_image_paint) |
312 observer->OnFirstImagePaint(new_timing, extra_info); | 313 observer->OnFirstImagePaint(new_timing, extra_info); |
313 if (new_timing.paint_timing.first_contentful_paint && | 314 if (new_timing.paint_timing->first_contentful_paint && |
314 !last_timing.paint_timing.first_contentful_paint) | 315 !last_timing.paint_timing->first_contentful_paint) |
315 observer->OnFirstContentfulPaint(new_timing, extra_info); | 316 observer->OnFirstContentfulPaint(new_timing, extra_info); |
316 if (new_timing.paint_timing.first_meaningful_paint && | 317 if (new_timing.paint_timing->first_meaningful_paint && |
317 !last_timing.paint_timing.first_meaningful_paint) | 318 !last_timing.paint_timing->first_meaningful_paint) |
318 observer->OnFirstMeaningfulPaint(new_timing, extra_info); | 319 observer->OnFirstMeaningfulPaint(new_timing, extra_info); |
319 if (new_timing.parse_timing.parse_start && | 320 if (new_timing.parse_timing->parse_start && |
320 !last_timing.parse_timing.parse_start) | 321 !last_timing.parse_timing->parse_start) |
321 observer->OnParseStart(new_timing, extra_info); | 322 observer->OnParseStart(new_timing, extra_info); |
322 if (new_timing.parse_timing.parse_stop && | 323 if (new_timing.parse_timing->parse_stop && |
323 !last_timing.parse_timing.parse_stop) | 324 !last_timing.parse_timing->parse_stop) |
324 observer->OnParseStop(new_timing, extra_info); | 325 observer->OnParseStop(new_timing, extra_info); |
325 } | 326 } |
326 | 327 |
327 } // namespace | 328 } // namespace |
328 | 329 |
329 PageLoadTracker::PageLoadTracker( | 330 PageLoadTracker::PageLoadTracker( |
330 bool in_foreground, | 331 bool in_foreground, |
331 PageLoadMetricsEmbedderInterface* embedder_interface, | 332 PageLoadMetricsEmbedderInterface* embedder_interface, |
332 const GURL& currently_committed_url, | 333 const GURL& currently_committed_url, |
333 content::NavigationHandle* navigation_handle, | 334 content::NavigationHandle* navigation_handle, |
334 UserInitiatedInfo user_initiated_info, | 335 UserInitiatedInfo user_initiated_info, |
335 int aborted_chain_size, | 336 int aborted_chain_size, |
336 int aborted_chain_size_same_url) | 337 int aborted_chain_size_same_url) |
337 : did_stop_tracking_(false), | 338 : did_stop_tracking_(false), |
338 app_entered_background_(false), | 339 app_entered_background_(false), |
339 navigation_start_(navigation_handle->NavigationStart()), | 340 navigation_start_(navigation_handle->NavigationStart()), |
340 url_(navigation_handle->GetURL()), | 341 url_(navigation_handle->GetURL()), |
341 start_url_(navigation_handle->GetURL()), | 342 start_url_(navigation_handle->GetURL()), |
342 did_commit_(false), | 343 did_commit_(false), |
343 page_end_reason_(END_NONE), | 344 page_end_reason_(END_NONE), |
344 page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), | 345 page_end_user_initiated_info_(UserInitiatedInfo::NotUserInitiated()), |
345 started_in_foreground_(in_foreground), | 346 started_in_foreground_(in_foreground), |
| 347 timing_(CreatePageLoadTiming()), |
346 page_transition_(navigation_handle->GetPageTransition()), | 348 page_transition_(navigation_handle->GetPageTransition()), |
347 user_initiated_info_(user_initiated_info), | 349 user_initiated_info_(user_initiated_info), |
348 aborted_chain_size_(aborted_chain_size), | 350 aborted_chain_size_(aborted_chain_size), |
349 aborted_chain_size_same_url_(aborted_chain_size_same_url), | 351 aborted_chain_size_same_url_(aborted_chain_size_same_url), |
350 embedder_interface_(embedder_interface) { | 352 embedder_interface_(embedder_interface) { |
351 DCHECK(!navigation_handle->HasCommitted()); | 353 DCHECK(!navigation_handle->HasCommitted()); |
352 embedder_interface_->RegisterObservers(this); | 354 embedder_interface_->RegisterObservers(this); |
353 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, | 355 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnStart, navigation_handle, |
354 currently_committed_url, started_in_foreground_); | 356 currently_committed_url, started_in_foreground_); |
355 | 357 |
(...skipping 27 matching lines...) Expand all Loading... |
383 if (!failed_provisional_load_info_) | 385 if (!failed_provisional_load_info_) |
384 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); | 386 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); |
385 | 387 |
386 // Don't include any aborts that resulted in a new navigation, as the chain | 388 // Don't include any aborts that resulted in a new navigation, as the chain |
387 // length will be included in the aborter PageLoadTracker. | 389 // length will be included in the aborter PageLoadTracker. |
388 if (page_end_reason_ != END_RELOAD && | 390 if (page_end_reason_ != END_RELOAD && |
389 page_end_reason_ != END_FORWARD_BACK && | 391 page_end_reason_ != END_FORWARD_BACK && |
390 page_end_reason_ != END_NEW_NAVIGATION) { | 392 page_end_reason_ != END_NEW_NAVIGATION) { |
391 LogAbortChainHistograms(nullptr); | 393 LogAbortChainHistograms(nullptr); |
392 } | 394 } |
393 } else if (timing_.IsEmpty()) { | 395 } else if (page_load_metrics::IsEmpty(*timing_)) { |
394 RecordInternalError(ERR_NO_IPCS_RECEIVED); | 396 RecordInternalError(ERR_NO_IPCS_RECEIVED); |
395 } | 397 } |
396 | 398 |
397 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 399 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
398 for (const auto& observer : observers_) { | 400 for (const auto& observer : observers_) { |
399 if (failed_provisional_load_info_) { | 401 if (failed_provisional_load_info_) { |
400 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); | 402 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); |
401 } else if (did_commit_) { | 403 } else if (did_commit_) { |
402 observer->OnComplete(timing_, info); | 404 observer->OnComplete(*timing_, info); |
403 } | 405 } |
404 } | 406 } |
405 } | 407 } |
406 | 408 |
407 void PageLoadTracker::LogAbortChainHistograms( | 409 void PageLoadTracker::LogAbortChainHistograms( |
408 content::NavigationHandle* final_navigation) { | 410 content::NavigationHandle* final_navigation) { |
409 if (aborted_chain_size_ == 0) | 411 if (aborted_chain_size_ == 0) |
410 return; | 412 return; |
411 // Note that this could be broken out by this navigation's abort type, if more | 413 // Note that this could be broken out by this navigation's abort type, if more |
412 // granularity is needed. Add one to the chain size to count the current | 414 // 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... |
459 // Only log the first time we background in a given page load. | 461 // Only log the first time we background in a given page load. |
460 if (background_time_.is_null()) { | 462 if (background_time_.is_null()) { |
461 // Make sure we either started in the foreground and haven't been | 463 // Make sure we either started in the foreground and haven't been |
462 // foregrounded yet, or started in the background and have already been | 464 // foregrounded yet, or started in the background and have already been |
463 // foregrounded. | 465 // foregrounded. |
464 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); | 466 DCHECK_EQ(started_in_foreground_, foreground_time_.is_null()); |
465 background_time_ = base::TimeTicks::Now(); | 467 background_time_ = base::TimeTicks::Now(); |
466 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); | 468 ClampBrowserTimestampIfInterProcessTimeTickSkew(&background_time_); |
467 } | 469 } |
468 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 470 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
469 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, timing_, info); | 471 INVOKE_AND_PRUNE_OBSERVERS(observers_, OnHidden, *timing_, info); |
470 } | 472 } |
471 | 473 |
472 void PageLoadTracker::WebContentsShown() { | 474 void PageLoadTracker::WebContentsShown() { |
473 // Only log the first time we foreground in a given page load. | 475 // Only log the first time we foreground in a given page load. |
474 if (foreground_time_.is_null()) { | 476 if (foreground_time_.is_null()) { |
475 // Make sure we either started in the background and haven't been | 477 // Make sure we either started in the background and haven't been |
476 // backgrounded yet, or started in the foreground and have already been | 478 // backgrounded yet, or started in the foreground and have already been |
477 // backgrounded. | 479 // backgrounded. |
478 DCHECK_NE(started_in_foreground_, background_time_.is_null()); | 480 DCHECK_NE(started_in_foreground_, background_time_.is_null()); |
479 foreground_time_ = base::TimeTicks::Now(); | 481 foreground_time_ = base::TimeTicks::Now(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 } | 544 } |
543 | 545 |
544 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { | 546 void PageLoadTracker::FlushMetricsOnAppEnterBackground() { |
545 if (!app_entered_background_) { | 547 if (!app_entered_background_) { |
546 RecordAppBackgroundPageLoadCompleted(false); | 548 RecordAppBackgroundPageLoadCompleted(false); |
547 app_entered_background_ = true; | 549 app_entered_background_ = true; |
548 } | 550 } |
549 | 551 |
550 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 552 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
551 INVOKE_AND_PRUNE_OBSERVERS(observers_, FlushMetricsOnAppEnterBackground, | 553 INVOKE_AND_PRUNE_OBSERVERS(observers_, FlushMetricsOnAppEnterBackground, |
552 timing_, info); | 554 *timing_, info); |
553 } | 555 } |
554 | 556 |
555 void PageLoadTracker::NotifyClientRedirectTo( | 557 void PageLoadTracker::NotifyClientRedirectTo( |
556 const PageLoadTracker& destination) { | 558 const PageLoadTracker& destination) { |
557 if (timing_.paint_timing.first_paint) { | 559 if (timing_->paint_timing->first_paint) { |
558 base::TimeTicks first_paint_time = | 560 base::TimeTicks first_paint_time = |
559 navigation_start() + timing_.paint_timing.first_paint.value(); | 561 navigation_start() + timing_->paint_timing->first_paint.value(); |
560 base::TimeDelta first_paint_to_navigation; | 562 base::TimeDelta first_paint_to_navigation; |
561 if (destination.navigation_start() > first_paint_time) | 563 if (destination.navigation_start() > first_paint_time) |
562 first_paint_to_navigation = | 564 first_paint_to_navigation = |
563 destination.navigation_start() - first_paint_time; | 565 destination.navigation_start() - first_paint_time; |
564 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, | 566 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, |
565 first_paint_to_navigation); | 567 first_paint_to_navigation); |
566 } else { | 568 } else { |
567 UMA_HISTOGRAM_BOOLEAN(internal::kClientRedirectWithoutPaint, true); | 569 UMA_HISTOGRAM_BOOLEAN(internal::kClientRedirectWithoutPaint, true); |
568 } | 570 } |
569 } | 571 } |
570 | 572 |
571 void PageLoadTracker::UpdateChildFrameMetadata( | 573 void PageLoadTracker::UpdateChildFrameMetadata( |
572 const PageLoadMetadata& child_metadata) { | 574 const mojom::PageLoadMetadata& child_metadata) { |
573 // Merge the child loading behavior flags with any we've already observed, | 575 // Merge the child loading behavior flags with any we've already observed, |
574 // possibly from other child frames. | 576 // possibly from other child frames. |
575 const int last_child_loading_behavior_flags = | 577 const int last_child_loading_behavior_flags = |
576 child_frame_metadata_.behavior_flags; | 578 child_frame_metadata_.behavior_flags; |
577 child_frame_metadata_.behavior_flags |= child_metadata.behavior_flags; | 579 child_frame_metadata_.behavior_flags |= child_metadata.behavior_flags; |
578 if (last_child_loading_behavior_flags == child_frame_metadata_.behavior_flags) | 580 if (last_child_loading_behavior_flags == child_frame_metadata_.behavior_flags) |
579 return; | 581 return; |
580 | 582 |
581 PageLoadExtraInfo extra_info(ComputePageLoadExtraInfo()); | 583 PageLoadExtraInfo extra_info(ComputePageLoadExtraInfo()); |
582 for (const auto& observer : observers_) { | 584 for (const auto& observer : observers_) { |
583 observer->OnLoadingBehaviorObserved(extra_info); | 585 observer->OnLoadingBehaviorObserved(extra_info); |
584 } | 586 } |
585 } | 587 } |
586 | 588 |
587 void PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing, | 589 void PageLoadTracker::UpdateTiming( |
588 const PageLoadMetadata& new_metadata) { | 590 const mojom::PageLoadTiming& new_timing, |
| 591 const mojom::PageLoadMetadata& new_metadata) { |
589 // Throw away IPCs that are not relevant to the current navigation. | 592 // Throw away IPCs that are not relevant to the current navigation. |
590 // Two timing structures cannot refer to the same navigation if they indicate | 593 // Two timing structures cannot refer to the same navigation if they indicate |
591 // that a navigation started at different times, so a new timing struct with a | 594 // that a navigation started at different times, so a new timing struct with a |
592 // different start time from an earlier struct is considered invalid. | 595 // different start time from an earlier struct is considered invalid. |
593 const bool valid_timing_descendent = | 596 const bool valid_timing_descendent = |
594 timing_.navigation_start.is_null() || | 597 timing_->navigation_start.is_null() || |
595 timing_.navigation_start == new_timing.navigation_start; | 598 timing_->navigation_start == new_timing.navigation_start; |
596 if (!valid_timing_descendent) { | 599 if (!valid_timing_descendent) { |
597 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT); | 600 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING_DESCENDENT); |
598 return; | 601 return; |
599 } | 602 } |
600 | 603 |
601 // Ensure flags sent previously are still present in the new metadata fields. | 604 // Ensure flags sent previously are still present in the new metadata fields. |
602 const bool valid_behavior_descendent = | 605 const bool valid_behavior_descendent = |
603 (main_frame_metadata_.behavior_flags & new_metadata.behavior_flags) == | 606 (main_frame_metadata_.behavior_flags & new_metadata.behavior_flags) == |
604 main_frame_metadata_.behavior_flags; | 607 main_frame_metadata_.behavior_flags; |
605 if (!valid_behavior_descendent) { | 608 if (!valid_behavior_descendent) { |
606 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_BEHAVIOR_DESCENDENT); | 609 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_BEHAVIOR_DESCENDENT); |
607 return; | 610 return; |
608 } | 611 } |
609 internal::PageLoadTimingStatus status = IsValidPageLoadTiming(new_timing); | 612 internal::PageLoadTimingStatus status = IsValidPageLoadTiming(new_timing); |
610 UMA_HISTOGRAM_ENUMERATION(internal::kPageLoadTimingStatus, status, | 613 UMA_HISTOGRAM_ENUMERATION(internal::kPageLoadTimingStatus, status, |
611 internal::LAST_PAGE_LOAD_TIMING_STATUS); | 614 internal::LAST_PAGE_LOAD_TIMING_STATUS); |
612 if (status != internal::VALID) { | 615 if (status != internal::VALID) { |
613 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING); | 616 RecordInternalError(ERR_BAD_TIMING_IPC_INVALID_TIMING); |
614 return; | 617 return; |
615 } | 618 } |
616 | 619 |
617 DCHECK(did_commit_); // OnCommit() must be called first. | 620 DCHECK(did_commit_); // OnCommit() must be called first. |
618 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() | 621 // There are some subtle ordering constraints here. GetPageLoadMetricsInfo() |
619 // must be called before DispatchObserverTimingCallbacks, but its | 622 // must be called before DispatchObserverTimingCallbacks, but its |
620 // implementation depends on the state of main_frame_metadata_, so we need | 623 // implementation depends on the state of main_frame_metadata_, so we need |
621 // to update main_frame_metadata_ before calling GetPageLoadMetricsInfo. | 624 // to update main_frame_metadata_ before calling GetPageLoadMetricsInfo. |
622 // Thus, we make a copy of timing here, update timing_ and | 625 // Thus, we make a copy of timing here, update timing_ and |
623 // main_frame_metadata_, and then proceed to dispatch the observer timing | 626 // main_frame_metadata_, and then proceed to dispatch the observer timing |
624 // callbacks. | 627 // callbacks. |
625 const PageLoadTiming last_timing = timing_; | 628 mojo::StructPtr<mojom::PageLoadTiming> last_timing = std::move(timing_); |
626 timing_ = new_timing; | 629 timing_ = new_timing.Clone(); |
627 | 630 |
628 const PageLoadMetadata last_metadata = main_frame_metadata_; | 631 const mojom::PageLoadMetadata last_metadata = main_frame_metadata_; |
629 main_frame_metadata_ = new_metadata; | 632 main_frame_metadata_ = new_metadata; |
630 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 633 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
631 for (const auto& observer : observers_) { | 634 for (const auto& observer : observers_) { |
632 DispatchObserverTimingCallbacks(observer.get(), last_timing, new_timing, | 635 DispatchObserverTimingCallbacks(observer.get(), *last_timing, new_timing, |
633 last_metadata, info); | 636 last_metadata, info); |
634 } | 637 } |
635 } | 638 } |
636 | 639 |
637 void PageLoadTracker::OnStartedResource( | 640 void PageLoadTracker::OnStartedResource( |
638 const ExtraRequestStartInfo& extra_request_start_info) { | 641 const ExtraRequestStartInfo& extra_request_start_info) { |
639 for (const auto& observer : observers_) { | 642 for (const auto& observer : observers_) { |
640 observer->OnStartedResource(extra_request_start_info); | 643 observer->OnStartedResource(extra_request_start_info); |
641 } | 644 } |
642 } | 645 } |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 observer->MediaStartedPlaying(video_type, is_in_main_frame); | 822 observer->MediaStartedPlaying(video_type, is_in_main_frame); |
820 } | 823 } |
821 | 824 |
822 void PageLoadTracker::OnNavigationDelayComplete(base::TimeDelta scheduled_delay, | 825 void PageLoadTracker::OnNavigationDelayComplete(base::TimeDelta scheduled_delay, |
823 base::TimeDelta actual_delay) { | 826 base::TimeDelta actual_delay) { |
824 for (const auto& observer : observers_) | 827 for (const auto& observer : observers_) |
825 observer->OnNavigationDelayComplete(scheduled_delay, actual_delay); | 828 observer->OnNavigationDelayComplete(scheduled_delay, actual_delay); |
826 } | 829 } |
827 | 830 |
828 } // namespace page_load_metrics | 831 } // namespace page_load_metrics |
OLD | NEW |