| 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 return false; | 131 return false; |
| 132 | 132 |
| 133 // If we have a non-empty timing, it should always have a navigation start. | 133 // If we have a non-empty timing, it should always have a navigation start. |
| 134 if (timing.navigation_start.is_null()) { | 134 if (timing.navigation_start.is_null()) { |
| 135 NOTREACHED() << "Received null navigation_start."; | 135 NOTREACHED() << "Received null navigation_start."; |
| 136 return false; | 136 return false; |
| 137 } | 137 } |
| 138 | 138 |
| 139 // Verify proper ordering between the various timings. | 139 // Verify proper ordering between the various timings. |
| 140 | 140 |
| 141 if (!EventsInOrder(timing.response_start, timing.parse_start)) { | 141 if (!EventsInOrder(timing.response_start, timing.parse_timing.parse_start)) { |
| 142 // We sometimes get a zero response_start with a non-zero parse start. See |
| 143 // crbug.com/590212. |
| 142 NOTREACHED() << "Invalid response_start " << timing.response_start | 144 NOTREACHED() << "Invalid response_start " << timing.response_start |
| 143 << " for parse_start " << timing.parse_start; | 145 << " for parse_start " << timing.parse_timing.parse_start; |
| 144 return false; | 146 return false; |
| 145 } | 147 } |
| 146 | 148 |
| 147 if (!EventsInOrder(timing.parse_start, timing.parse_stop)) { | 149 if (!EventsInOrder(timing.parse_timing.parse_start, |
| 148 NOTREACHED() << "Invalid parse_start " << timing.parse_start | 150 timing.parse_timing.parse_stop)) { |
| 149 << " for parse_stop " << timing.parse_stop; | 151 NOTREACHED() << "Invalid parse_start " << timing.parse_timing.parse_start |
| 152 << " for parse_stop " << timing.parse_timing.parse_stop; |
| 150 return false; | 153 return false; |
| 151 } | 154 } |
| 152 | 155 |
| 153 if (timing.parse_stop) { | 156 if (timing.parse_timing.parse_stop) { |
| 154 const base::TimeDelta parse_duration = | 157 const base::TimeDelta parse_duration = |
| 155 timing.parse_stop.value() - timing.parse_start.value(); | 158 timing.parse_timing.parse_stop.value() - |
| 156 if (timing.parse_blocked_on_script_load_duration > parse_duration) { | 159 timing.parse_timing.parse_start.value(); |
| 160 if (timing.parse_timing.parse_blocked_on_script_load_duration > |
| 161 parse_duration) { |
| 157 NOTREACHED() << "Invalid parse_blocked_on_script_load_duration " | 162 NOTREACHED() << "Invalid parse_blocked_on_script_load_duration " |
| 158 << timing.parse_blocked_on_script_load_duration | 163 << timing.parse_timing.parse_blocked_on_script_load_duration |
| 159 << " for parse duration " << parse_duration; | 164 << " for parse duration " << parse_duration; |
| 160 return false; | 165 return false; |
| 161 } | 166 } |
| 162 if (timing.parse_blocked_on_script_execution_duration > parse_duration) { | 167 if (timing.parse_timing.parse_blocked_on_script_execution_duration > |
| 163 NOTREACHED() << "Invalid parse_blocked_on_script_execution_duration " | 168 parse_duration) { |
| 164 << timing.parse_blocked_on_script_execution_duration | 169 NOTREACHED() |
| 165 << " for parse duration " << parse_duration; | 170 << "Invalid parse_blocked_on_script_execution_duration " |
| 171 << timing.parse_timing.parse_blocked_on_script_execution_duration |
| 172 << " for parse duration " << parse_duration; |
| 166 return false; | 173 return false; |
| 167 } | 174 } |
| 168 } | 175 } |
| 169 | 176 |
| 170 if (timing.parse_blocked_on_script_load_from_document_write_duration > | 177 if (timing.parse_timing |
| 171 timing.parse_blocked_on_script_load_duration) { | 178 .parse_blocked_on_script_load_from_document_write_duration > |
| 179 timing.parse_timing.parse_blocked_on_script_load_duration) { |
| 172 NOTREACHED() | 180 NOTREACHED() |
| 173 << "Invalid parse_blocked_on_script_load_from_document_write_duration " | 181 << "Invalid parse_blocked_on_script_load_from_document_write_duration " |
| 174 << timing.parse_blocked_on_script_load_from_document_write_duration | 182 << timing.parse_timing |
| 183 .parse_blocked_on_script_load_from_document_write_duration |
| 175 << " for parse_blocked_on_script_load_duration " | 184 << " for parse_blocked_on_script_load_duration " |
| 176 << timing.parse_blocked_on_script_load_duration; | 185 << timing.parse_timing.parse_blocked_on_script_load_duration; |
| 177 return false; | 186 return false; |
| 178 } | 187 } |
| 179 | 188 |
| 180 if (timing.parse_blocked_on_script_execution_from_document_write_duration > | 189 if (timing.parse_timing |
| 181 timing.parse_blocked_on_script_execution_duration) { | 190 .parse_blocked_on_script_execution_from_document_write_duration > |
| 191 timing.parse_timing.parse_blocked_on_script_execution_duration) { |
| 182 NOTREACHED() | 192 NOTREACHED() |
| 183 << "Invalid " | 193 << "Invalid " |
| 184 "parse_blocked_on_script_execution_from_document_write_duration " | 194 "parse_blocked_on_script_execution_from_document_write_duration " |
| 185 << timing.parse_blocked_on_script_execution_from_document_write_duration | 195 << timing.parse_timing |
| 196 .parse_blocked_on_script_execution_from_document_write_duration |
| 186 << " for parse_blocked_on_script_execution_duration " | 197 << " for parse_blocked_on_script_execution_duration " |
| 187 << timing.parse_blocked_on_script_execution_duration; | 198 << timing.parse_timing.parse_blocked_on_script_execution_duration; |
| 188 return false; | 199 return false; |
| 189 } | 200 } |
| 190 | 201 |
| 191 if (!EventsInOrder(timing.parse_stop, | 202 if (!EventsInOrder(timing.parse_timing.parse_stop, |
| 192 timing.dom_content_loaded_event_start)) { | 203 timing.document_timing.dom_content_loaded_event_start)) { |
| 193 NOTREACHED() << "Invalid parse_stop " << timing.parse_stop | 204 NOTREACHED() << "Invalid parse_stop " << timing.parse_timing.parse_stop |
| 194 << " for dom_content_loaded_event_start " | 205 << " for dom_content_loaded_event_start " |
| 195 << timing.dom_content_loaded_event_start; | 206 << timing.document_timing.dom_content_loaded_event_start; |
| 196 return false; | 207 return false; |
| 197 } | 208 } |
| 198 | 209 |
| 199 if (!EventsInOrder(timing.dom_content_loaded_event_start, | 210 if (!EventsInOrder(timing.document_timing.dom_content_loaded_event_start, |
| 200 timing.load_event_start)) { | 211 timing.document_timing.load_event_start)) { |
| 201 NOTREACHED() << "Invalid dom_content_loaded_event_start " | 212 NOTREACHED() << "Invalid dom_content_loaded_event_start " |
| 202 << timing.dom_content_loaded_event_start | 213 << timing.document_timing.dom_content_loaded_event_start |
| 203 << " for load_event_start " << timing.load_event_start; | 214 << " for load_event_start " |
| 215 << timing.document_timing.load_event_start; |
| 204 return false; | 216 return false; |
| 205 } | 217 } |
| 206 | 218 |
| 207 if (!EventsInOrder(timing.parse_start, timing.first_layout)) { | 219 if (!EventsInOrder(timing.parse_timing.parse_start, |
| 208 NOTREACHED() << "Invalid parse_start " << timing.parse_start | 220 timing.document_timing.first_layout)) { |
| 209 << " for first_layout " << timing.first_layout; | 221 NOTREACHED() << "Invalid parse_start " << timing.parse_timing.parse_start |
| 222 << " for first_layout " << timing.document_timing.first_layout; |
| 210 return false; | 223 return false; |
| 211 } | 224 } |
| 212 | 225 |
| 213 if (!EventsInOrder(timing.first_layout, timing.first_paint)) { | 226 if (!EventsInOrder(timing.document_timing.first_layout, |
| 227 timing.paint_timing.first_paint)) { |
| 214 // This can happen when we process an XHTML document that doesn't contain | 228 // This can happen when we process an XHTML document that doesn't contain |
| 215 // well formed XML. See crbug.com/627607. | 229 // well formed XML. See crbug.com/627607. |
| 216 DLOG(ERROR) << "Invalid first_layout " << timing.first_layout | 230 DLOG(ERROR) << "Invalid first_layout " |
| 217 << " for first_paint " << timing.first_paint; | 231 << timing.document_timing.first_layout << " for first_paint " |
| 232 << timing.paint_timing.first_paint; |
| 218 return false; | 233 return false; |
| 219 } | 234 } |
| 220 | 235 |
| 221 if (!EventsInOrder(timing.first_paint, timing.first_text_paint)) { | 236 if (!EventsInOrder(timing.paint_timing.first_paint, |
| 222 NOTREACHED() << "Invalid first_paint " << timing.first_paint | 237 timing.paint_timing.first_text_paint)) { |
| 223 << " for first_text_paint " << timing.first_text_paint; | 238 NOTREACHED() << "Invalid first_paint " << timing.paint_timing.first_paint |
| 239 << " for first_text_paint " |
| 240 << timing.paint_timing.first_text_paint; |
| 224 return false; | 241 return false; |
| 225 } | 242 } |
| 226 | 243 |
| 227 if (!EventsInOrder(timing.first_paint, timing.first_image_paint)) { | 244 if (!EventsInOrder(timing.paint_timing.first_paint, |
| 228 NOTREACHED() << "Invalid first_paint " << timing.first_paint | 245 timing.paint_timing.first_image_paint)) { |
| 229 << " for first_image_paint " << timing.first_image_paint; | 246 NOTREACHED() << "Invalid first_paint " << timing.paint_timing.first_paint |
| 247 << " for first_image_paint " |
| 248 << timing.paint_timing.first_image_paint; |
| 230 return false; | 249 return false; |
| 231 } | 250 } |
| 232 | 251 |
| 233 if (!EventsInOrder(timing.first_paint, timing.first_contentful_paint)) { | 252 if (!EventsInOrder(timing.paint_timing.first_paint, |
| 234 NOTREACHED() << "Invalid first_paint " << timing.first_paint | 253 timing.paint_timing.first_contentful_paint)) { |
| 254 NOTREACHED() << "Invalid first_paint " << timing.paint_timing.first_paint |
| 235 << " for first_contentful_paint " | 255 << " for first_contentful_paint " |
| 236 << timing.first_contentful_paint; | 256 << timing.paint_timing.first_contentful_paint; |
| 237 return false; | 257 return false; |
| 238 } | 258 } |
| 239 | 259 |
| 240 if (!EventsInOrder(timing.first_paint, timing.first_meaningful_paint)) { | 260 if (!EventsInOrder(timing.paint_timing.first_paint, |
| 241 NOTREACHED() << "Invalid first_paint " << timing.first_paint | 261 timing.paint_timing.first_meaningful_paint)) { |
| 262 NOTREACHED() << "Invalid first_paint " << timing.paint_timing.first_paint |
| 242 << " for first_meaningful_paint " | 263 << " for first_meaningful_paint " |
| 243 << timing.first_meaningful_paint; | 264 << timing.paint_timing.first_meaningful_paint; |
| 244 return false; | 265 return false; |
| 245 } | 266 } |
| 246 | 267 |
| 247 return true; | 268 return true; |
| 248 } | 269 } |
| 249 | 270 |
| 250 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { | 271 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { |
| 251 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, | 272 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, |
| 252 completed_after_background); | 273 completed_after_background); |
| 253 } | 274 } |
| 254 | 275 |
| 255 void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer, | 276 void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer, |
| 256 const PageLoadTiming& last_timing, | 277 const PageLoadTiming& last_timing, |
| 257 const PageLoadTiming& new_timing, | 278 const PageLoadTiming& new_timing, |
| 258 const PageLoadMetadata& last_metadata, | 279 const PageLoadMetadata& last_metadata, |
| 259 const PageLoadExtraInfo& extra_info) { | 280 const PageLoadExtraInfo& extra_info) { |
| 260 if (extra_info.main_frame_metadata.behavior_flags != | 281 if (extra_info.main_frame_metadata.behavior_flags != |
| 261 last_metadata.behavior_flags) | 282 last_metadata.behavior_flags) |
| 262 observer->OnLoadingBehaviorObserved(extra_info); | 283 observer->OnLoadingBehaviorObserved(extra_info); |
| 263 if (last_timing != new_timing) | 284 if (last_timing != new_timing) |
| 264 observer->OnTimingUpdate(new_timing, extra_info); | 285 observer->OnTimingUpdate(new_timing, extra_info); |
| 265 if (new_timing.dom_content_loaded_event_start && | 286 if (new_timing.document_timing.dom_content_loaded_event_start && |
| 266 !last_timing.dom_content_loaded_event_start) | 287 !last_timing.document_timing.dom_content_loaded_event_start) |
| 267 observer->OnDomContentLoadedEventStart(new_timing, extra_info); | 288 observer->OnDomContentLoadedEventStart(new_timing, extra_info); |
| 268 if (new_timing.load_event_start && !last_timing.load_event_start) | 289 if (new_timing.document_timing.load_event_start && |
| 290 !last_timing.document_timing.load_event_start) |
| 269 observer->OnLoadEventStart(new_timing, extra_info); | 291 observer->OnLoadEventStart(new_timing, extra_info); |
| 270 if (new_timing.first_layout && !last_timing.first_layout) | 292 if (new_timing.document_timing.first_layout && |
| 293 !last_timing.document_timing.first_layout) |
| 271 observer->OnFirstLayout(new_timing, extra_info); | 294 observer->OnFirstLayout(new_timing, extra_info); |
| 272 if (new_timing.first_paint && !last_timing.first_paint) | 295 if (new_timing.paint_timing.first_paint && |
| 296 !last_timing.paint_timing.first_paint) |
| 273 observer->OnFirstPaint(new_timing, extra_info); | 297 observer->OnFirstPaint(new_timing, extra_info); |
| 274 if (new_timing.first_text_paint && !last_timing.first_text_paint) | 298 if (new_timing.paint_timing.first_text_paint && |
| 299 !last_timing.paint_timing.first_text_paint) |
| 275 observer->OnFirstTextPaint(new_timing, extra_info); | 300 observer->OnFirstTextPaint(new_timing, extra_info); |
| 276 if (new_timing.first_image_paint && !last_timing.first_image_paint) | 301 if (new_timing.paint_timing.first_image_paint && |
| 302 !last_timing.paint_timing.first_image_paint) |
| 277 observer->OnFirstImagePaint(new_timing, extra_info); | 303 observer->OnFirstImagePaint(new_timing, extra_info); |
| 278 if (new_timing.first_contentful_paint && !last_timing.first_contentful_paint) | 304 if (new_timing.paint_timing.first_contentful_paint && |
| 305 !last_timing.paint_timing.first_contentful_paint) |
| 279 observer->OnFirstContentfulPaint(new_timing, extra_info); | 306 observer->OnFirstContentfulPaint(new_timing, extra_info); |
| 280 if (new_timing.first_meaningful_paint && !last_timing.first_meaningful_paint) | 307 if (new_timing.paint_timing.first_meaningful_paint && |
| 308 !last_timing.paint_timing.first_meaningful_paint) |
| 281 observer->OnFirstMeaningfulPaint(new_timing, extra_info); | 309 observer->OnFirstMeaningfulPaint(new_timing, extra_info); |
| 282 if (new_timing.parse_start && !last_timing.parse_start) | 310 if (new_timing.parse_timing.parse_start && |
| 311 !last_timing.parse_timing.parse_start) |
| 283 observer->OnParseStart(new_timing, extra_info); | 312 observer->OnParseStart(new_timing, extra_info); |
| 284 if (new_timing.parse_stop && !last_timing.parse_stop) | 313 if (new_timing.parse_timing.parse_stop && |
| 314 !last_timing.parse_timing.parse_stop) |
| 285 observer->OnParseStop(new_timing, extra_info); | 315 observer->OnParseStop(new_timing, extra_info); |
| 286 } | 316 } |
| 287 | 317 |
| 288 } // namespace | 318 } // namespace |
| 289 | 319 |
| 290 PageLoadTracker::PageLoadTracker( | 320 PageLoadTracker::PageLoadTracker( |
| 291 bool in_foreground, | 321 bool in_foreground, |
| 292 PageLoadMetricsEmbedderInterface* embedder_interface, | 322 PageLoadMetricsEmbedderInterface* embedder_interface, |
| 293 const GURL& currently_committed_url, | 323 const GURL& currently_committed_url, |
| 294 content::NavigationHandle* navigation_handle, | 324 content::NavigationHandle* navigation_handle, |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 app_entered_background_ = true; | 530 app_entered_background_ = true; |
| 501 } | 531 } |
| 502 | 532 |
| 503 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); | 533 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); |
| 504 INVOKE_AND_PRUNE_OBSERVERS(observers_, FlushMetricsOnAppEnterBackground, | 534 INVOKE_AND_PRUNE_OBSERVERS(observers_, FlushMetricsOnAppEnterBackground, |
| 505 timing_, info); | 535 timing_, info); |
| 506 } | 536 } |
| 507 | 537 |
| 508 void PageLoadTracker::NotifyClientRedirectTo( | 538 void PageLoadTracker::NotifyClientRedirectTo( |
| 509 const PageLoadTracker& destination) { | 539 const PageLoadTracker& destination) { |
| 510 if (timing_.first_paint) { | 540 if (timing_.paint_timing.first_paint) { |
| 511 base::TimeTicks first_paint_time = | 541 base::TimeTicks first_paint_time = |
| 512 navigation_start() + timing_.first_paint.value(); | 542 navigation_start() + timing_.paint_timing.first_paint.value(); |
| 513 base::TimeDelta first_paint_to_navigation; | 543 base::TimeDelta first_paint_to_navigation; |
| 514 if (destination.navigation_start() > first_paint_time) | 544 if (destination.navigation_start() > first_paint_time) |
| 515 first_paint_to_navigation = | 545 first_paint_to_navigation = |
| 516 destination.navigation_start() - first_paint_time; | 546 destination.navigation_start() - first_paint_time; |
| 517 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, | 547 PAGE_LOAD_HISTOGRAM(internal::kClientRedirectFirstPaintToNavigation, |
| 518 first_paint_to_navigation); | 548 first_paint_to_navigation); |
| 519 } else { | 549 } else { |
| 520 UMA_HISTOGRAM_BOOLEAN(internal::kClientRedirectWithoutPaint, true); | 550 UMA_HISTOGRAM_BOOLEAN(internal::kClientRedirectWithoutPaint, true); |
| 521 } | 551 } |
| 522 } | 552 } |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 observer->MediaStartedPlaying(video_type, is_in_main_frame); | 792 observer->MediaStartedPlaying(video_type, is_in_main_frame); |
| 763 } | 793 } |
| 764 | 794 |
| 765 void PageLoadTracker::OnNavigationDelayComplete(base::TimeDelta scheduled_delay, | 795 void PageLoadTracker::OnNavigationDelayComplete(base::TimeDelta scheduled_delay, |
| 766 base::TimeDelta actual_delay) { | 796 base::TimeDelta actual_delay) { |
| 767 for (const auto& observer : observers_) | 797 for (const auto& observer : observers_) |
| 768 observer->OnNavigationDelayComplete(scheduled_delay, actual_delay); | 798 observer->OnNavigationDelayComplete(scheduled_delay, actual_delay); |
| 769 } | 799 } |
| 770 | 800 |
| 771 } // namespace page_load_metrics | 801 } // namespace page_load_metrics |
| OLD | NEW |