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

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

Powered by Google App Engine
This is Rietveld 408576698