OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |