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

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

Issue 2132603002: [page_load_metrics] Add a NavigationThrottle for richer abort metrics (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nasko@ nits Created 4 years, 4 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 181
182 void RecordInternalError(InternalErrorLoadEvent event) { 182 void RecordInternalError(InternalErrorLoadEvent event) {
183 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY); 183 UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY);
184 } 184 }
185 185
186 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) { 186 void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) {
187 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground, 187 UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground,
188 completed_after_background); 188 completed_after_background);
189 } 189 }
190 190
191 // TODO(csharrison): Add a case for client side redirects, which is what JS
192 // initiated window.location / window.history navigations get set to.
191 UserAbortType AbortTypeForPageTransition(ui::PageTransition transition) { 193 UserAbortType AbortTypeForPageTransition(ui::PageTransition transition) {
192 if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD)) 194 if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD))
193 return ABORT_RELOAD; 195 return ABORT_RELOAD;
194 if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) 196 if (transition & ui::PAGE_TRANSITION_FORWARD_BACK)
195 return ABORT_FORWARD_BACK; 197 return ABORT_FORWARD_BACK;
196 if (ui::PageTransitionIsNewNavigation(transition)) 198 if (ui::PageTransitionIsNewNavigation(transition))
197 return ABORT_NEW_NAVIGATION; 199 return ABORT_NEW_NAVIGATION;
198 NOTREACHED() 200 NOTREACHED()
199 << "AbortTypeForPageTransition received unexpected ui::PageTransition: " 201 << "AbortTypeForPageTransition received unexpected ui::PageTransition: "
200 << transition; 202 << transition;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 const GURL& currently_committed_url, 248 const GURL& currently_committed_url,
247 content::NavigationHandle* navigation_handle, 249 content::NavigationHandle* navigation_handle,
248 int aborted_chain_size, 250 int aborted_chain_size,
249 int aborted_chain_size_same_url) 251 int aborted_chain_size_same_url)
250 : did_stop_tracking_(false), 252 : did_stop_tracking_(false),
251 app_entered_background_(false), 253 app_entered_background_(false),
252 navigation_start_(navigation_handle->NavigationStart()), 254 navigation_start_(navigation_handle->NavigationStart()),
253 url_(navigation_handle->GetURL()), 255 url_(navigation_handle->GetURL()),
254 abort_type_(ABORT_NONE), 256 abort_type_(ABORT_NONE),
255 started_in_foreground_(in_foreground), 257 started_in_foreground_(in_foreground),
258 page_transition_(navigation_handle->GetPageTransition()),
256 aborted_chain_size_(aborted_chain_size), 259 aborted_chain_size_(aborted_chain_size),
257 aborted_chain_size_same_url_(aborted_chain_size_same_url), 260 aborted_chain_size_same_url_(aborted_chain_size_same_url),
258 embedder_interface_(embedder_interface) { 261 embedder_interface_(embedder_interface) {
259 DCHECK(!navigation_handle->HasCommitted()); 262 DCHECK(!navigation_handle->HasCommitted());
260 embedder_interface_->RegisterObservers(this); 263 embedder_interface_->RegisterObservers(this);
261 for (const auto& observer : observers_) { 264 for (const auto& observer : observers_) {
262 observer->OnStart(navigation_handle, currently_committed_url, 265 observer->OnStart(navigation_handle, currently_committed_url,
263 started_in_foreground_); 266 started_in_foreground_);
264 } 267 }
265 } 268 }
266 269
267 PageLoadTracker::~PageLoadTracker() { 270 PageLoadTracker::~PageLoadTracker() {
268 if (app_entered_background_) { 271 if (app_entered_background_) {
269 RecordAppBackgroundPageLoadCompleted(true); 272 RecordAppBackgroundPageLoadCompleted(true);
270 } 273 }
271 274
272 if (did_stop_tracking_) 275 if (did_stop_tracking_)
273 return; 276 return;
274 277
275 if (commit_time_.is_null()) { 278 if (commit_time_.is_null()) {
276 if (!failed_provisional_load_info_) 279 if (!failed_provisional_load_info_)
277 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD); 280 RecordInternalError(ERR_NO_COMMIT_OR_FAILED_PROVISIONAL_LOAD);
278 281
279 // Recall that trackers that are given ABORT_UNKNOWN_NAVIGATION have their 282 // Don't include any aborts that resulted in a new navigation, as the chain
280 // chain length added to the next navigation. Take care not to double count 283 // length will be included in the aborter PageLoadTracker.
281 // them. Also do not double count committed loads, which call this already. 284 if (abort_type_ != ABORT_RELOAD && abort_type_ != ABORT_FORWARD_BACK &&
282 if (abort_type_ != ABORT_UNKNOWN_NAVIGATION) 285 abort_type_ != ABORT_NEW_NAVIGATION) {
283 LogAbortChainHistograms(nullptr); 286 LogAbortChainHistograms(nullptr);
287 }
284 } else if (timing_.IsEmpty()) { 288 } else if (timing_.IsEmpty()) {
285 RecordInternalError(ERR_NO_IPCS_RECEIVED); 289 RecordInternalError(ERR_NO_IPCS_RECEIVED);
286 PAGE_LOAD_HISTOGRAM(internal::kCommitToCompleteNoTimingIPCs, 290 PAGE_LOAD_HISTOGRAM(internal::kCommitToCompleteNoTimingIPCs,
287 base::TimeTicks::Now() - commit_time_); 291 base::TimeTicks::Now() - commit_time_);
288 } 292 }
289 293
290 const PageLoadExtraInfo info = ComputePageLoadExtraInfo(); 294 const PageLoadExtraInfo info = ComputePageLoadExtraInfo();
291 for (const auto& observer : observers_) { 295 for (const auto& observer : observers_) {
292 if (failed_provisional_load_info_) { 296 if (failed_provisional_load_info_) {
293 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info); 297 observer->OnFailedProvisionalLoad(*failed_provisional_load_info_, info);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 for (const auto& observer : observers_) 375 for (const auto& observer : observers_)
372 observer->OnShown(); 376 observer->OnShown();
373 } 377 }
374 378
375 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) { 379 void PageLoadTracker::Commit(content::NavigationHandle* navigation_handle) {
376 // TODO(bmcquade): To improve accuracy, consider adding commit time to 380 // TODO(bmcquade): To improve accuracy, consider adding commit time to
377 // NavigationHandle. Taking a timestamp here should be close enough for now. 381 // NavigationHandle. Taking a timestamp here should be close enough for now.
378 commit_time_ = base::TimeTicks::Now(); 382 commit_time_ = base::TimeTicks::Now();
379 ClampBrowserTimestampIfInterProcessTimeTickSkew(&commit_time_); 383 ClampBrowserTimestampIfInterProcessTimeTickSkew(&commit_time_);
380 url_ = navigation_handle->GetURL(); 384 url_ = navigation_handle->GetURL();
385 // Some transitions (like CLIENT_REDIRECT) are only known at commit time.
386 page_transition_ = navigation_handle->GetPageTransition();
381 for (const auto& observer : observers_) { 387 for (const auto& observer : observers_) {
382 observer->OnCommit(navigation_handle); 388 observer->OnCommit(navigation_handle);
383 } 389 }
384 LogAbortChainHistograms(navigation_handle); 390 LogAbortChainHistograms(navigation_handle);
385 } 391 }
386 392
387 void PageLoadTracker::FailedProvisionalLoad( 393 void PageLoadTracker::FailedProvisionalLoad(
388 content::NavigationHandle* navigation_handle) { 394 content::NavigationHandle* navigation_handle) {
389 DCHECK(!failed_provisional_load_info_); 395 DCHECK(!failed_provisional_load_info_);
390 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo( 396 failed_provisional_load_info_.reset(new FailedProvisionalLoadInfo(
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 DCHECK_EQ(abort_type_, ABORT_OTHER); 558 DCHECK_EQ(abort_type_, ABORT_OTHER);
553 559
554 // For some aborts (e.g. navigations), the initiated timestamp can be earlier 560 // For some aborts (e.g. navigations), the initiated timestamp can be earlier
555 // than the timestamp that aborted the load. Taking the minimum gives the 561 // than the timestamp that aborted the load. Taking the minimum gives the
556 // closest user initiated time known. 562 // closest user initiated time known.
557 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp), 563 UpdateAbortInternal(abort_type, std::min(abort_time_, timestamp),
558 is_certainly_browser_timestamp); 564 is_certainly_browser_timestamp);
559 } 565 }
560 566
561 bool PageLoadTracker::IsLikelyProvisionalAbort( 567 bool PageLoadTracker::IsLikelyProvisionalAbort(
562 base::TimeTicks abort_cause_time) { 568 base::TimeTicks abort_cause_time) const {
563 // Note that |abort_cause_time - abort_time| can be negative. 569 // Note that |abort_cause_time - abort_time| can be negative.
564 return abort_type_ == ABORT_OTHER && 570 return abort_type_ == ABORT_OTHER &&
565 (abort_cause_time - abort_time_).InMilliseconds() < 100; 571 (abort_cause_time - abort_time_).InMilliseconds() < 100;
566 } 572 }
567 573
568 bool PageLoadTracker::MatchesOriginalNavigation( 574 bool PageLoadTracker::MatchesOriginalNavigation(
569 content::NavigationHandle* navigation_handle) { 575 content::NavigationHandle* navigation_handle) {
570 // Neither navigation should have committed. 576 // Neither navigation should have committed.
571 DCHECK(!navigation_handle->HasCommitted()); 577 DCHECK(!navigation_handle->HasCommitted());
572 DCHECK(commit_time_.is_null()); 578 DCHECK(commit_time_.is_null());
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 659 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
654 bool handled = true; 660 bool handled = true;
655 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message, 661 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message,
656 render_frame_host) 662 render_frame_host)
657 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated) 663 IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated)
658 IPC_MESSAGE_UNHANDLED(handled = false) 664 IPC_MESSAGE_UNHANDLED(handled = false)
659 IPC_END_MESSAGE_MAP() 665 IPC_END_MESSAGE_MAP()
660 return handled; 666 return handled;
661 } 667 }
662 668
663 void MetricsWebContentsObserver::DidStartNavigation( 669 void MetricsWebContentsObserver::WillStartNavigationRequest(
664 content::NavigationHandle* navigation_handle) { 670 content::NavigationHandle* navigation_handle) {
665 if (!navigation_handle->IsInMainFrame()) 671 if (!navigation_handle->IsInMainFrame())
666 return; 672 return;
667 673
668 std::unique_ptr<PageLoadTracker> last_aborted = 674 std::unique_ptr<PageLoadTracker> last_aborted =
669 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle); 675 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle);
670 676
671 int chain_size_same_url = 0; 677 int chain_size_same_url = 0;
672 int chain_size = 0; 678 int chain_size = 0;
673 if (last_aborted) { 679 if (last_aborted) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 } 889 }
884 890
885 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) { 891 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type) {
886 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now(), true); 892 NotifyAbortAllLoadsWithTimestamp(abort_type, base::TimeTicks::Now(), true);
887 } 893 }
888 894
889 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( 895 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp(
890 UserAbortType abort_type, 896 UserAbortType abort_type,
891 base::TimeTicks timestamp, 897 base::TimeTicks timestamp,
892 bool is_certainly_browser_timestamp) { 898 bool is_certainly_browser_timestamp) {
893 if (committed_load_) 899 if (committed_load_) {
894 committed_load_->NotifyAbort(abort_type, timestamp, 900 committed_load_->NotifyAbort(abort_type, timestamp,
895 is_certainly_browser_timestamp); 901 is_certainly_browser_timestamp);
902 }
896 for (const auto& kv : provisional_loads_) { 903 for (const auto& kv : provisional_loads_) {
897 kv.second->NotifyAbort(abort_type, timestamp, 904 kv.second->NotifyAbort(abort_type, timestamp,
898 is_certainly_browser_timestamp); 905 is_certainly_browser_timestamp);
899 } 906 }
900 for (const auto& tracker : aborted_provisional_loads_) { 907 for (const auto& tracker : aborted_provisional_loads_) {
901 if (tracker->IsLikelyProvisionalAbort(timestamp)) 908 if (tracker->IsLikelyProvisionalAbort(timestamp)) {
902 tracker->UpdateAbort(abort_type, timestamp, 909 tracker->UpdateAbort(abort_type, timestamp,
903 is_certainly_browser_timestamp); 910 is_certainly_browser_timestamp);
911 }
904 } 912 }
905 aborted_provisional_loads_.clear(); 913 aborted_provisional_loads_.clear();
906 } 914 }
907 915
908 std::unique_ptr<PageLoadTracker> 916 std::unique_ptr<PageLoadTracker>
909 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( 917 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation(
910 content::NavigationHandle* new_navigation) { 918 content::NavigationHandle* new_navigation) {
911 // If there are multiple aborted loads that can be attributed to this one, 919 // If there are multiple aborted loads that can be attributed to this one,
912 // just count the latest one for simplicity. Other loads will fall into the 920 // just count the latest one for simplicity. Other loads will fall into the
913 // OTHER bucket, though there shouldn't be very many. 921 // OTHER bucket, though there shouldn't be very many.
914 if (aborted_provisional_loads_.size() == 0) 922 if (aborted_provisional_loads_.size() == 0)
915 return nullptr; 923 return nullptr;
916 if (aborted_provisional_loads_.size() > 1) 924 if (aborted_provisional_loads_.size() > 1)
917 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); 925 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS);
918 926
919 std::unique_ptr<PageLoadTracker> last_aborted_load = 927 std::unique_ptr<PageLoadTracker> last_aborted_load =
920 std::move(aborted_provisional_loads_.back()); 928 std::move(aborted_provisional_loads_.back());
921 aborted_provisional_loads_.pop_back(); 929 aborted_provisional_loads_.pop_back();
922 930
923 base::TimeTicks timestamp = new_navigation->NavigationStart(); 931 base::TimeTicks timestamp = new_navigation->NavigationStart();
924 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) 932 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) {
925 last_aborted_load->UpdateAbort(ABORT_UNKNOWN_NAVIGATION, timestamp, false); 933 last_aborted_load->UpdateAbort(
934 AbortTypeForPageTransition(new_navigation->GetPageTransition()),
935 timestamp, false);
936 }
926 937
927 aborted_provisional_loads_.clear(); 938 aborted_provisional_loads_.clear();
928 return last_aborted_load; 939 return last_aborted_load;
929 } 940 }
930 941
931 void MetricsWebContentsObserver::OnTimingUpdated( 942 void MetricsWebContentsObserver::OnTimingUpdated(
932 content::RenderFrameHost* render_frame_host, 943 content::RenderFrameHost* render_frame_host,
933 const PageLoadTiming& timing, 944 const PageLoadTiming& timing,
934 const PageLoadMetadata& metadata) { 945 const PageLoadMetadata& metadata) {
935 // We may receive notifications from frames that have been navigated away 946 // We may receive notifications from frames that have been navigated away
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 if (navigation_handle->IsSamePage() || navigation_handle->IsErrorPage()) 987 if (navigation_handle->IsSamePage() || navigation_handle->IsErrorPage())
977 return false; 988 return false;
978 const std::string& mime_type = web_contents()->GetContentsMimeType(); 989 const std::string& mime_type = web_contents()->GetContentsMimeType();
979 if (mime_type != "text/html" && mime_type != "application/xhtml+xml") 990 if (mime_type != "text/html" && mime_type != "application/xhtml+xml")
980 return false; 991 return false;
981 } 992 }
982 return true; 993 return true;
983 } 994 }
984 995
985 } // namespace page_load_metrics 996 } // namespace page_load_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698