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

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

Issue 2699933003: Generalize abort tracking to page end state tracking (Closed)
Patch Set: add additional histogram Created 3 years, 10 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/metrics_web_contents_observer.h" 5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 if (!metrics) { 75 if (!metrics) {
76 metrics = new MetricsWebContentsObserver(web_contents, 76 metrics = new MetricsWebContentsObserver(web_contents,
77 std::move(embedder_interface)); 77 std::move(embedder_interface));
78 web_contents->SetUserData(UserDataKey(), metrics); 78 web_contents->SetUserData(UserDataKey(), metrics);
79 } 79 }
80 return metrics; 80 return metrics;
81 } 81 }
82 82
83 MetricsWebContentsObserver::~MetricsWebContentsObserver() { 83 MetricsWebContentsObserver::~MetricsWebContentsObserver() {
84 // TODO(csharrison): Use a more user-initiated signal for CLOSE. 84 // TODO(csharrison): Use a more user-initiated signal for CLOSE.
85 NotifyAbortAllLoads(ABORT_CLOSE, UserInitiatedInfo::NotUserInitiated()); 85 NotifyPageEndAllLoads(END_CLOSE, UserInitiatedInfo::NotUserInitiated());
86 } 86 }
87 87
88 void MetricsWebContentsObserver::RegisterInputEventObserver( 88 void MetricsWebContentsObserver::RegisterInputEventObserver(
89 content::RenderViewHost* host) { 89 content::RenderViewHost* host) {
90 if (host != nullptr) 90 if (host != nullptr)
91 host->GetWidget()->AddInputEventObserver(this); 91 host->GetWidget()->AddInputEventObserver(this);
92 } 92 }
93 93
94 void MetricsWebContentsObserver::UnregisterInputEventObserver( 94 void MetricsWebContentsObserver::UnregisterInputEventObserver(
95 content::RenderViewHost* host) { 95 content::RenderViewHost* host) {
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 286
287 if (navigation_handle->HasCommitted()) { 287 if (navigation_handle->HasCommitted()) {
288 UserInitiatedInfo user_initiated_info = 288 UserInitiatedInfo user_initiated_info =
289 finished_nav 289 finished_nav
290 ? finished_nav->user_initiated_info() 290 ? finished_nav->user_initiated_info()
291 : CreateUserInitiatedInfo(navigation_handle, committed_load_.get()); 291 : CreateUserInitiatedInfo(navigation_handle, committed_load_.get());
292 292
293 // Notify other loads that they may have been aborted by this committed 293 // Notify other loads that they may have been aborted by this committed
294 // load. is_certainly_browser_timestamp is set to false because 294 // load. is_certainly_browser_timestamp is set to false because
295 // NavigationStart() could be set in either the renderer or browser process. 295 // NavigationStart() could be set in either the renderer or browser process.
296 NotifyAbortAllLoadsWithTimestamp( 296 NotifyPageEndAllLoadsWithTimestamp(
297 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), 297 EndReasonForPageTransition(navigation_handle->GetPageTransition()),
298 user_initiated_info, navigation_handle->NavigationStart(), false); 298 user_initiated_info, navigation_handle->NavigationStart(), false);
299 299
300 if (should_track) { 300 if (should_track) {
301 HandleCommittedNavigationForTrackedLoad(navigation_handle, 301 HandleCommittedNavigationForTrackedLoad(navigation_handle,
302 std::move(finished_nav)); 302 std::move(finished_nav));
303 } else { 303 } else {
304 committed_load_.reset(); 304 committed_load_.reset();
305 } 305 }
306 } else if (should_track) { 306 } else if (should_track) {
307 HandleFailedNavigationForTrackedLoad(navigation_handle, 307 HandleFailedNavigationForTrackedLoad(navigation_handle,
308 std::move(finished_nav)); 308 std::move(finished_nav));
309 } 309 }
310 } 310 }
311 311
312 // Handle a pre-commit error. Navigations that result in an error page will be 312 // Handle a pre-commit error. Navigations that result in an error page will be
313 // ignored. 313 // ignored.
314 void MetricsWebContentsObserver::HandleFailedNavigationForTrackedLoad( 314 void MetricsWebContentsObserver::HandleFailedNavigationForTrackedLoad(
315 content::NavigationHandle* navigation_handle, 315 content::NavigationHandle* navigation_handle,
316 std::unique_ptr<PageLoadTracker> tracker) { 316 std::unique_ptr<PageLoadTracker> tracker) {
317 tracker->FailedProvisionalLoad(navigation_handle); 317 const base::TimeTicks now = base::TimeTicks::Now();
318 tracker->FailedProvisionalLoad(navigation_handle, now);
318 319
319 net::Error error = navigation_handle->GetNetErrorCode(); 320 const net::Error error = navigation_handle->GetNetErrorCode();
320 321
321 // net::OK: This case occurs when the NavigationHandle finishes and reports 322 // net::OK: This case occurs when the NavigationHandle finishes and reports
322 // !HasCommitted(), but reports no net::Error. This should not occur 323 // !HasCommitted(), but reports no net::Error. This should not occur
323 // pre-PlzNavigate, but afterwards it should represent the navigation stopped 324 // pre-PlzNavigate, but afterwards it should represent the navigation stopped
324 // by the user before it was ready to commit. 325 // by the user before it was ready to commit.
325 // net::ERR_ABORTED: An aborted provisional load has error 326 // net::ERR_ABORTED: An aborted provisional load has error net::ERR_ABORTED.
326 // net::ERR_ABORTED. 327 const bool is_aborted_provisional_load =
327 if ((error == net::OK) || (error == net::ERR_ABORTED)) { 328 error == net::OK || error == net::ERR_ABORTED;
328 tracker->NotifyAbort(ABORT_OTHER, UserInitiatedInfo::NotUserInitiated(), 329
329 base::TimeTicks::Now(), true); 330 // If is_aborted_provisional_load, the page end reason is not yet known, and
331 // will be updated as additional information is available from subsequent
332 // navigations.
333 tracker->NotifyPageEnd(
334 is_aborted_provisional_load ? END_OTHER : END_PROVISIONAL_LOAD_FAILED,
335 UserInitiatedInfo::NotUserInitiated(), now, true);
336
337 if (is_aborted_provisional_load)
330 aborted_provisional_loads_.push_back(std::move(tracker)); 338 aborted_provisional_loads_.push_back(std::move(tracker));
331 }
332 } 339 }
333 340
334 void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad( 341 void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad(
335 content::NavigationHandle* navigation_handle, 342 content::NavigationHandle* navigation_handle,
336 std::unique_ptr<PageLoadTracker> tracker) { 343 std::unique_ptr<PageLoadTracker> tracker) {
337 if (!IsNavigationUserInitiated(navigation_handle) && 344 if (!IsNavigationUserInitiated(navigation_handle) &&
338 (navigation_handle->GetPageTransition() & 345 (navigation_handle->GetPageTransition() &
339 ui::PAGE_TRANSITION_CLIENT_REDIRECT) != 0 && 346 ui::PAGE_TRANSITION_CLIENT_REDIRECT) != 0 &&
340 committed_load_) { 347 committed_load_) {
341 // TODO(bmcquade): consider carrying the user_gesture bit forward to the 348 // TODO(bmcquade): consider carrying the user_gesture bit forward to the
342 // redirected navigation. 349 // redirected navigation.
343 committed_load_->NotifyClientRedirectTo(*tracker); 350 committed_load_->NotifyClientRedirectTo(*tracker);
344 } 351 }
345 352
346 committed_load_ = std::move(tracker); 353 committed_load_ = std::move(tracker);
347 committed_load_->Commit(navigation_handle); 354 committed_load_->Commit(navigation_handle);
348 DCHECK(committed_load_->did_commit()); 355 DCHECK(committed_load_->did_commit());
349 } 356 }
350 357
351 void MetricsWebContentsObserver::NavigationStopped() { 358 void MetricsWebContentsObserver::NavigationStopped() {
352 // TODO(csharrison): Use a more user-initiated signal for STOP. 359 // TODO(csharrison): Use a more user-initiated signal for STOP.
353 NotifyAbortAllLoads(ABORT_STOP, UserInitiatedInfo::NotUserInitiated()); 360 NotifyPageEndAllLoads(END_STOP, UserInitiatedInfo::NotUserInitiated());
354 } 361 }
355 362
356 void MetricsWebContentsObserver::OnInputEvent( 363 void MetricsWebContentsObserver::OnInputEvent(
357 const blink::WebInputEvent& event) { 364 const blink::WebInputEvent& event) {
358 // Ignore browser navigation or reload which comes with type Undefined. 365 // Ignore browser navigation or reload which comes with type Undefined.
359 if (event.type() == blink::WebInputEvent::Type::Undefined) 366 if (event.type() == blink::WebInputEvent::Type::Undefined)
360 return; 367 return;
361 368
362 if (committed_load_) 369 if (committed_load_)
363 committed_load_->OnInputEvent(event); 370 committed_load_->OnInputEvent(event);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 in_foreground_ = false; 414 in_foreground_ = false;
408 if (committed_load_) 415 if (committed_load_)
409 committed_load_->WebContentsHidden(); 416 committed_load_->WebContentsHidden();
410 for (const auto& kv : provisional_loads_) { 417 for (const auto& kv : provisional_loads_) {
411 kv.second->WebContentsHidden(); 418 kv.second->WebContentsHidden();
412 } 419 }
413 } 420 }
414 421
415 // This will occur when the process for the main RenderFrameHost exits, either 422 // This will occur when the process for the main RenderFrameHost exits, either
416 // normally or from a crash. We eagerly log data from the last committed load if 423 // normally or from a crash. We eagerly log data from the last committed load if
417 // we have one. Don't notify aborts here because this is probably not user 424 // we have one.
418 // initiated. If it is (e.g. browser shutdown), other code paths will take care
419 // of notifying.
420 void MetricsWebContentsObserver::RenderProcessGone( 425 void MetricsWebContentsObserver::RenderProcessGone(
421 base::TerminationStatus status) { 426 base::TerminationStatus status) {
422 // Other code paths will be run for normal renderer shutdown. Note that we 427 // Other code paths will be run for normal renderer shutdown. Note that we
423 // sometimes get the STILL_RUNNING value on fast shutdown. 428 // sometimes get the STILL_RUNNING value on fast shutdown.
424 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION || 429 if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
425 status == base::TERMINATION_STATUS_STILL_RUNNING) { 430 status == base::TERMINATION_STATUS_STILL_RUNNING) {
426 return; 431 return;
427 } 432 }
428 433
434 if (committed_load_) {
Charlie Harrison 2017/02/21 19:49:31 Why not propagate this to all loads, including the
Bryan McQuade 2017/02/21 21:51:59 RenderProcessGone associated with the render frame
435 committed_load_->NotifyPageEnd(END_RENDER_PROCESS_GONE,
436 UserInitiatedInfo::NotUserInitiated(),
437 base::TimeTicks::Now(), true);
438 }
439
429 // If this is a crash, eagerly log the aborted provisional loads and the 440 // If this is a crash, eagerly log the aborted provisional loads and the
430 // committed load. |provisional_loads_| don't need to be destroyed here 441 // committed load. |provisional_loads_| don't need to be destroyed here
431 // because their lifetime is tied to the NavigationHandle. 442 // because their lifetime is tied to the NavigationHandle.
432 committed_load_.reset(); 443 committed_load_.reset();
433 aborted_provisional_loads_.clear(); 444 aborted_provisional_loads_.clear();
434 } 445 }
435 446
436 void MetricsWebContentsObserver::NotifyAbortAllLoads( 447 void MetricsWebContentsObserver::NotifyPageEndAllLoads(
437 UserAbortType abort_type, 448 PageEndReason page_end_reason,
438 UserInitiatedInfo user_initiated_info) { 449 UserInitiatedInfo user_initiated_info) {
439 NotifyAbortAllLoadsWithTimestamp(abort_type, user_initiated_info, 450 NotifyPageEndAllLoadsWithTimestamp(page_end_reason, user_initiated_info,
440 base::TimeTicks::Now(), true); 451 base::TimeTicks::Now(), true);
441 } 452 }
442 453
443 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( 454 void MetricsWebContentsObserver::NotifyPageEndAllLoadsWithTimestamp(
444 UserAbortType abort_type, 455 PageEndReason page_end_reason,
445 UserInitiatedInfo user_initiated_info, 456 UserInitiatedInfo user_initiated_info,
446 base::TimeTicks timestamp, 457 base::TimeTicks timestamp,
447 bool is_certainly_browser_timestamp) { 458 bool is_certainly_browser_timestamp) {
448 if (committed_load_) { 459 if (committed_load_) {
449 committed_load_->NotifyAbort(abort_type, user_initiated_info, timestamp, 460 committed_load_->NotifyPageEnd(page_end_reason, user_initiated_info,
450 is_certainly_browser_timestamp); 461 timestamp, is_certainly_browser_timestamp);
451 } 462 }
452 for (const auto& kv : provisional_loads_) { 463 for (const auto& kv : provisional_loads_) {
453 kv.second->NotifyAbort(abort_type, user_initiated_info, timestamp, 464 kv.second->NotifyPageEnd(page_end_reason, user_initiated_info, timestamp,
454 is_certainly_browser_timestamp); 465 is_certainly_browser_timestamp);
455 } 466 }
456 for (const auto& tracker : aborted_provisional_loads_) { 467 for (const auto& tracker : aborted_provisional_loads_) {
457 if (tracker->IsLikelyProvisionalAbort(timestamp)) { 468 if (tracker->IsLikelyProvisionalAbort(timestamp)) {
458 tracker->UpdateAbort(abort_type, user_initiated_info, timestamp, 469 tracker->UpdatePageEnd(page_end_reason, user_initiated_info, timestamp,
459 is_certainly_browser_timestamp); 470 is_certainly_browser_timestamp);
460 } 471 }
461 } 472 }
462 aborted_provisional_loads_.clear(); 473 aborted_provisional_loads_.clear();
463 } 474 }
464 475
465 std::unique_ptr<PageLoadTracker> 476 std::unique_ptr<PageLoadTracker>
466 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( 477 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation(
467 content::NavigationHandle* new_navigation, 478 content::NavigationHandle* new_navigation,
468 UserInitiatedInfo user_initiated_info) { 479 UserInitiatedInfo user_initiated_info) {
469 // If there are multiple aborted loads that can be attributed to this one, 480 // If there are multiple aborted loads that can be attributed to this one,
470 // just count the latest one for simplicity. Other loads will fall into the 481 // just count the latest one for simplicity. Other loads will fall into the
471 // OTHER bucket, though there shouldn't be very many. 482 // OTHER bucket, though there shouldn't be very many.
472 if (aborted_provisional_loads_.size() == 0) 483 if (aborted_provisional_loads_.size() == 0)
473 return nullptr; 484 return nullptr;
474 if (aborted_provisional_loads_.size() > 1) 485 if (aborted_provisional_loads_.size() > 1)
475 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); 486 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS);
476 487
477 std::unique_ptr<PageLoadTracker> last_aborted_load = 488 std::unique_ptr<PageLoadTracker> last_aborted_load =
478 std::move(aborted_provisional_loads_.back()); 489 std::move(aborted_provisional_loads_.back());
479 aborted_provisional_loads_.pop_back(); 490 aborted_provisional_loads_.pop_back();
480 491
481 base::TimeTicks timestamp = new_navigation->NavigationStart(); 492 base::TimeTicks timestamp = new_navigation->NavigationStart();
482 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) { 493 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) {
483 last_aborted_load->UpdateAbort( 494 last_aborted_load->UpdatePageEnd(
484 AbortTypeForPageTransition(new_navigation->GetPageTransition()), 495 EndReasonForPageTransition(new_navigation->GetPageTransition()),
485 user_initiated_info, timestamp, false); 496 user_initiated_info, timestamp, false);
486 } 497 }
487 498
488 aborted_provisional_loads_.clear(); 499 aborted_provisional_loads_.clear();
489 return last_aborted_load; 500 return last_aborted_load;
490 } 501 }
491 502
492 void MetricsWebContentsObserver::OnTimingUpdated( 503 void MetricsWebContentsObserver::OnTimingUpdated(
493 content::RenderFrameHost* render_frame_host, 504 content::RenderFrameHost* render_frame_host,
494 const PageLoadTiming& timing, 505 const PageLoadTiming& timing,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 content::NavigationHandle* navigation_handle) const { 541 content::NavigationHandle* navigation_handle) const {
531 DCHECK(navigation_handle->IsInMainFrame()); 542 DCHECK(navigation_handle->IsInMainFrame());
532 DCHECK(!navigation_handle->HasCommitted() || 543 DCHECK(!navigation_handle->HasCommitted() ||
533 !navigation_handle->IsSamePage()); 544 !navigation_handle->IsSamePage());
534 545
535 return BrowserPageTrackDecider(embedder_interface_.get(), web_contents(), 546 return BrowserPageTrackDecider(embedder_interface_.get(), web_contents(),
536 navigation_handle).ShouldTrack(); 547 navigation_handle).ShouldTrack();
537 } 548 }
538 549
539 } // namespace page_load_metrics 550 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698