Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: chrome/browser/page_load_metrics/page_load_tracker.cc

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

Powered by Google App Engine
This is Rietveld 408576698