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

Unified Diff: components/page_load_metrics/browser/metrics_web_contents_observer.cc

Issue 1384213002: Page Abort Events for relevant navigations (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments/name changes. Don't track non html mimes Created 5 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: components/page_load_metrics/browser/metrics_web_contents_observer.cc
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
index 2961f1ecb5dd766e48da0cd1dc87bd6f8ba53cb7..2b23acd681952f2ea77c0da5da68563bddb434c8 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -64,45 +64,53 @@ base::Time WallTimeFromTimeTicks(base::TimeTicks time) {
base::TimeDelta::FromMinutes(10), 100)
PageLoadTracker::PageLoadTracker(bool in_foreground)
- : has_commit_(false), started_in_foreground_(in_foreground) {
- RecordEvent(PAGE_LOAD_STARTED);
-}
+ : has_commit_(false), started_in_foreground_(in_foreground) {}
PageLoadTracker::~PageLoadTracker() {
- // Even a load that failed a provisional load should log
- // that it aborted before first layout.
- if (timing_.first_layout.is_zero())
- RecordEvent(PAGE_LOAD_ABORTED_BEFORE_FIRST_LAYOUT);
-
if (has_commit_)
RecordTimingHistograms();
}
void PageLoadTracker::WebContentsHidden() {
// Only log the first time we background in a given page load.
- if (background_time_.is_null()) {
+ if (started_in_foreground_ && background_time_.is_null())
background_time_ = base::TimeTicks::Now();
- }
+}
+
+void PageLoadTracker::WebContentsShown() {
+ // Only log the first time we foreground in a given page load.
+ // Don't log foreground time if we started foregrounded.
+ if (!started_in_foreground_ && foreground_time_.is_null())
+ foreground_time_ = base::TimeTicks::Now();
}
void PageLoadTracker::Commit() {
has_commit_ = true;
+ // We log the event that this load started. Because we don't know if a load is
+ // relevant or if it will commit before now, we have to log this event at
+ // commit time.
+ RecordCommittedEvent(COMMITTED_LOAD_STARTED, !started_in_foreground_);
}
-bool PageLoadTracker::UpdateTiming(const PageLoadTiming& timing) {
+bool PageLoadTracker::UpdateTiming(const PageLoadTiming& new_timing) {
// Throw away IPCs that are not relevant to the current navigation.
- if (!timing_.navigation_start.is_null() &&
- timing_.navigation_start != timing.navigation_start) {
- // TODO(csharrison) uma log a counter here
- return false;
- }
- if (IsValidPageLoadTiming(timing)) {
- timing_ = timing;
+ // Two timing structures cannot refer to the same navigation if they indicate
+ // that a navigation started at different times, so a new timing struct with a
+ // different start time from an earlier struct is considered invalid.
+ bool valid_timing_descendent =
+ timing_.navigation_start.is_null() ||
+ timing_.navigation_start == new_timing.navigation_start;
+ if (IsValidPageLoadTiming(new_timing) && valid_timing_descendent) {
+ timing_ = new_timing;
return true;
}
return false;
}
+bool PageLoadTracker::HasBackgrounded() {
+ return !(started_in_foreground_ && background_time_.is_null());
Alexei Svitkine (slow) 2015/10/16 15:43:14 Nit: !(a && b) -> !a || !b
Charlie Harrison 2015/10/16 16:05:06 Done.
+}
+
void PageLoadTracker::RecordTimingHistograms() {
DCHECK(has_commit_);
// This method is similar to how blink converts TimeTicks to epoch time.
@@ -122,7 +130,7 @@ void PageLoadTracker::RecordTimingHistograms() {
timing_.dom_content_loaded_event_start);
} else {
PAGE_LOAD_HISTOGRAM(
- "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired.BG",
+ "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired.Background",
timing_.dom_content_loaded_event_start);
}
}
@@ -131,19 +139,23 @@ void PageLoadTracker::RecordTimingHistograms() {
PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToLoadEventFired",
timing_.load_event_start);
} else {
- PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToLoadEventFired.BG",
- timing_.load_event_start);
+ PAGE_LOAD_HISTOGRAM(
+ "PageLoad.Timing2.NavigationToLoadEventFired.Background",
+ timing_.load_event_start);
}
}
- if (!timing_.first_layout.is_zero()) {
+ if (timing_.first_layout.is_zero()) {
+ RecordCommittedEvent(COMMITTED_LOAD_FAILED_BEFORE_FIRST_LAYOUT,
+ HasBackgrounded());
+ } else {
if (timing_.first_layout < background_delta) {
PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout",
timing_.first_layout);
- RecordEvent(PAGE_LOAD_SUCCESSFUL_FIRST_LAYOUT_FOREGROUND);
+ RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, false);
} else {
- PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout.BG",
+ PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout.Background",
timing_.first_layout);
- RecordEvent(PAGE_LOAD_SUCCESSFUL_FIRST_LAYOUT_BACKGROUND);
+ RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, true);
}
}
if (!timing_.first_text_paint.is_zero()) {
@@ -151,15 +163,45 @@ void PageLoadTracker::RecordTimingHistograms() {
PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstTextPaint",
timing_.first_text_paint);
} else {
- PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstTextPaint.BG",
- timing_.first_text_paint);
+ PAGE_LOAD_HISTOGRAM(
+ "PageLoad.Timing2.NavigationToFirstTextPaint.Background",
+ timing_.first_text_paint);
}
}
+ // Log time to first foreground / time to first background. Log counts that we
+ // started a relevant page load in the foreground / background.
+ if (!background_time_.is_null()) {
+ PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstBackground",
+ background_delta);
+ } else if (!foreground_time_.is_null()) {
+ PAGE_LOAD_HISTOGRAM(
+ "PageLoad.Timing2.NavigationToFirstForeground",
+ WallTimeFromTimeTicks(foreground_time_) - timing_.navigation_start);
+ }
}
-void PageLoadTracker::RecordEvent(PageLoadEvent event) {
- UMA_HISTOGRAM_ENUMERATION(
- "PageLoad.EventCounts", event, PAGE_LOAD_LAST_ENTRY);
+void PageLoadTracker::RecordProvisionalEvent(ProvisionalLoadEvent event) {
+ if (HasBackgrounded()) {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Provisional.Background", event,
+ PROVISIONAL_LOAD_LAST_ENTRY);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Provisional", event,
+ PROVISIONAL_LOAD_LAST_ENTRY);
+ }
+}
+
+// RecordCommittedEvent needs a backgrounded input because we need to special
+// case a few events that need either precise timing measurements, or different
+// logic than simply "Did I background before logging this event?"
+void PageLoadTracker::RecordCommittedEvent(CommittedLoadEvent event,
+ bool backgrounded) {
+ if (backgrounded) {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Committed.Background", event,
+ COMMITTED_LOAD_LAST_ENTRY);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Committed", event,
+ COMMITTED_LOAD_LAST_ENTRY);
+ }
}
MetricsWebContentsObserver::MetricsWebContentsObserver(
@@ -203,13 +245,17 @@ void MetricsWebContentsObserver::DidFinishNavigation(
DCHECK(finished_nav);
// Handle a pre-commit error here. Navigations that result in an error page
- // will be ignored.
+ // will be ignored. Note that downloads/204s will result in HasCommitted()
+ // returning false.
if (!navigation_handle->HasCommitted()) {
- finished_nav->RecordEvent(PAGE_LOAD_FAILED_BEFORE_COMMIT);
- if (navigation_handle->GetNetErrorCode() == net::ERR_ABORTED)
- finished_nav->RecordEvent(PAGE_LOAD_ABORTED_BEFORE_COMMIT);
+ net::Error error = navigation_handle->GetNetErrorCode();
+ finished_nav->RecordProvisionalEvent(
+ error == net::OK ? PROVISIONAL_LOAD_STOPPED
+ : error == net::ERR_ABORTED ? PROVISIONAL_LOAD_ERR_ABORTED
+ : PROVISIONAL_LOAD_ERR_FAILED_NON_ABORT);
return;
}
+ finished_nav->RecordProvisionalEvent(PROVISIONAL_LOAD_COMMITTED);
// Don't treat a same-page nav as a new page load.
if (navigation_handle->IsSamePage())
@@ -228,6 +274,11 @@ void MetricsWebContentsObserver::DidFinishNavigation(
void MetricsWebContentsObserver::WasShown() {
in_foreground_ = true;
+ if (committed_load_)
+ committed_load_->WebContentsShown();
+ for (const auto& kv : provisional_loads_) {
+ kv.second->WebContentsShown();
+ }
}
void MetricsWebContentsObserver::WasHidden() {
@@ -250,21 +301,40 @@ void MetricsWebContentsObserver::RenderProcessGone(
void MetricsWebContentsObserver::OnTimingUpdated(
content::RenderFrameHost* render_frame_host,
const PageLoadTiming& timing) {
- if (!committed_load_)
- return;
+ bool error = false;
+ if (!committed_load_) {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.InternalError",
+ ERR_IPC_WITH_NO_COMMITTED_LOAD, ERR_LAST_ENTRY);
+ error = true;
+ }
// We may receive notifications from frames that have been navigated away
// from. We simply ignore them.
- if (render_frame_host != web_contents()->GetMainFrame())
- return;
+ if (render_frame_host != web_contents()->GetMainFrame()) {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.InternalError",
+ ERR_IPC_FROM_WRONG_FRAME, ERR_LAST_ENTRY);
Alexei Svitkine (slow) 2015/10/16 15:43:15 Please make a helper function for this histogram,
Charlie Harrison 2015/10/16 16:05:06 Done. Good call.
+ error = true;
+ }
// For urls like chrome://newtab, the renderer and browser disagree,
// so we have to double check that the renderer isn't sending data from a
// bad url like https://www.google.com/_/chrome/newtab.
- if (!web_contents()->GetLastCommittedURL().SchemeIsHTTPOrHTTPS())
+ if (!web_contents()->GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.InternalError",
+ ERR_IPC_FROM_BAD_URL_SCHEME, ERR_LAST_ENTRY);
+ error = true;
+ }
+
+ if (error)
return;
- committed_load_->UpdateTiming(timing);
+ if (!committed_load_->UpdateTiming(timing)) {
+ // If the page load tracker cannot update its timing, something is wrong
+ // with the IPC (it's from another load, or it's invalid in some other way).
+ // We expect this to be a rare occurrence.
+ UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.InternalError",
+ ERR_BAD_TIMING_IPC, ERR_LAST_ENTRY);
+ }
}
bool MetricsWebContentsObserver::IsRelevantNavigation(
@@ -273,11 +343,13 @@ bool MetricsWebContentsObserver::IsRelevantNavigation(
// we see from the browser side (e.g. chrome://newtab). We want to be
// sure here that we aren't logging UMA for internal pages.
const GURL& browser_url = web_contents()->GetLastCommittedURL();
+ std::string mime = web_contents()->GetContentsMimeType();
Bryan McQuade 2015/10/16 15:01:29 GetContentsMimeType only returns the correct value
Bryan McQuade 2015/10/16 15:17:10 nit: since GetContentsMimeType returns a const std
Charlie Harrison 2015/10/16 16:05:06 Done.
return navigation_handle->IsInMainFrame() &&
!navigation_handle->IsSamePage() &&
!navigation_handle->IsErrorPage() &&
navigation_handle->GetURL().SchemeIsHTTPOrHTTPS() &&
- browser_url.SchemeIsHTTPOrHTTPS();
+ browser_url.SchemeIsHTTPOrHTTPS() &&
+ (mime == "text/html" || mime == "application/xhtml+xml");
}
} // namespace page_load_metrics

Powered by Google App Engine
This is Rietveld 408576698