Bug 1307689 - Add telemetry to detect when user abandons an in-progress page load. data-review=bsmedberg, r?Mossop
MozReview-Commit-ID: D8emwJriu4m
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -869,16 +869,22 @@ function serializeInputStream(aStream) {
}
return data;
}
// A shared function used by both remote and non-remote browser XBL bindings to
// load a URI or redirect it to the correct process.
function _loadURIWithFlags(browser, uri, params) {
+ let tab = gBrowser.getTabForBrowser(browser);
+ // Preloaded browsers don't have tabs, so we ignore those.
+ if (tab) {
+ maybeRecordAbandonmentTelemetry(tab, "newURI");
+ }
+
if (!uri) {
uri = "about:blank";
}
let triggeringPrincipal = params.triggeringPrincipal || null;
let flags = params.flags || 0;
let referrer = params.referrerURI;
let referrerPolicy = ("referrerPolicy" in params ? params.referrerPolicy :
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
@@ -1784,27 +1790,39 @@ function HandleAppCommandEvent(evt) {
break;
default:
return;
}
evt.stopPropagation();
evt.preventDefault();
}
+function maybeRecordAbandonmentTelemetry(tab, type) {
+ if (!tab.hasAttribute("busy")) {
+ return;
+ }
+
+ let histogram = Services.telemetry
+ .getHistogramById("BUSY_TAB_ABANDONED");
+ histogram.add(type);
+}
+
function gotoHistoryIndex(aEvent) {
let index = aEvent.target.getAttribute("index");
if (!index)
return false;
let where = whereToOpenLink(aEvent);
if (where == "current") {
// Normal click. Go there in the current tab and update session history.
try {
+ maybeRecordAbandonmentTelemetry(gBrowser.selectedTab,
+ "historyNavigation");
gBrowser.gotoIndex(index);
} catch (ex) {
return false;
}
return true;
}
// Modified click. Go there in a new tab/window.
@@ -1813,29 +1831,31 @@ function gotoHistoryIndex(aEvent) {
return true;
}
function BrowserForward(aEvent) {
let where = whereToOpenLink(aEvent, false, true);
if (where == "current") {
try {
+ maybeRecordAbandonmentTelemetry(gBrowser.selectedTab, "forward");
gBrowser.goForward();
} catch (ex) {
}
} else {
duplicateTabIn(gBrowser.selectedTab, where, 1);
}
}
function BrowserBack(aEvent) {
let where = whereToOpenLink(aEvent, false, true);
if (where == "current") {
try {
+ maybeRecordAbandonmentTelemetry(gBrowser.selectedTab, "back");
gBrowser.goBack();
} catch (ex) {
}
} else {
duplicateTabIn(gBrowser.selectedTab, where, -1);
}
}
@@ -1858,16 +1878,17 @@ function BrowserHandleShiftBackspace() {
case 1:
goDoCommand("cmd_scrollPageDown");
break;
}
}
function BrowserStop() {
const stopFlags = nsIWebNavigation.STOP_ALL;
+ maybeRecordAbandonmentTelemetry(gBrowser.selectedTab, "stop");
gBrowser.webNavigation.stop(stopFlags);
}
function BrowserReloadOrDuplicate(aEvent) {
let metaKeyPressed = AppConstants.platform == "macosx"
? aEvent.metaKey
: aEvent.ctrlKey;
var backgroundTabModifier = aEvent.button == 1 || metaKeyPressed;
@@ -3250,16 +3271,22 @@ function BrowserReloadWithFlags(reloadFl
if (gBrowser.updateBrowserRemotenessByURL(gBrowser.selectedBrowser, url)) {
// If the remoteness has changed, the new browser doesn't have any
// information of what was loaded before, so we need to load the previous
// URL again.
gBrowser.loadURIWithFlags(url, reloadFlags);
return;
}
+ // Do this after the above case where we might flip remoteness.
+ // Unfortunately, we'll count the remoteness flip case as a
+ // "newURL" load, since we're using loadURIWithFlags, but hopefully
+ // that's rare enough to not matter.
+ maybeRecordAbandonmentTelemetry(gBrowser.selectedTab, "reload");
+
// Reset temporary permissions on the current tab. This is done here
// because we only want to reset permissions on user reload.
SitePermissions.clearTemporaryPermissions(gBrowser.selectedBrowser);
let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
gBrowser.selectedBrowser
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2496,16 +2496,18 @@
<body>
<![CDATA[
if (aParams) {
var animate = aParams.animate;
var byMouse = aParams.byMouse;
var skipPermitUnload = aParams.skipPermitUnload;
}
+ window.maybeRecordAbandonmentTelemetry(aTab, "tabClosed");
+
// Handle requests for synchronously removing an already
// asynchronously closing tab.
if (!animate &&
aTab.closing) {
this._endRemoveTab(aTab);
return;
}
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -10740,10 +10740,18 @@
},
"MOZ_CHUNKED_ARRAYBUFFER_IN_XHR": {
"alert_emails": ["amarchesini@mozilla.com"],
"expires_in_version": "58",
"kind": "boolean",
"bug_numbers": [1335365],
"releaseChannelCollection": "opt-out",
"description": "XMLHttpRequest.responseType set to moz-chunked-arraybuffer"
+ },
+ "BUSY_TAB_ABANDONED": {
+ "alert_emails": ["hkirschner@mozilla.com"],
+ "expires_in_version": "60",
+ "kind": "categorical",
+ "bug_numbers": [1307689],
+ "description": "Records a value each time a tab that is showing the loading throbber is interrupted. Desktop only.",
+ "labels": ["stop", "back", "forward", "historyNavigation", "reload", "tabClosed", "newURI"]
}
}