Merge pull request #163 from mozilla/testpilot-metrics-117

for #117: start telemetry with testpilot-metrics
This commit is contained in:
Andrea Marchesini
2017-02-15 17:37:56 +01:00
committed by GitHub
6 changed files with 481 additions and 8 deletions
+140 -6
View File
@@ -35,6 +35,7 @@ const PREFS = [
const { attachTo, detachFrom } = require("sdk/content/mod");
const { ContextualIdentityService } = require("resource://gre/modules/ContextualIdentityService.jsm");
const { getFavicon } = require("sdk/places/favicon");
const Metrics = require("./testpilot-metrics");
const { modelFor } = require("sdk/model/core");
const prefService = require("sdk/preferences/service");
const self = require("sdk/self");
@@ -42,11 +43,13 @@ const ss = require("sdk/simple-storage");
const { Style } = require("sdk/stylesheet/style");
const tabs = require("sdk/tabs");
const tabsUtils = require("sdk/tabs/utils");
const uuid = require("sdk/util/uuid");
const { viewFor } = require("sdk/view/core");
const webExtension = require("sdk/webextension");
const windows = require("sdk/windows");
const windowUtils = require("sdk/window/utils");
// ----------------------------------------------------------------------------
// ContainerService
@@ -61,7 +64,8 @@ const ContainerService = {
if (installation) {
const object = {
version: 1,
prefs: {}
prefs: {},
metricsUUID: uuid.uuid().toString(),
};
PREFS.forEach(pref => {
@@ -77,6 +81,8 @@ const ContainerService = {
prefService.set(pref[0], pref[1]);
});
this._metricsUUID = ss.storage.savedConfiguration.metricsUUID;
// Message routing
// only these methods are allowed. We have a 1:1 mapping between messages
@@ -95,6 +101,7 @@ const ContainerService = {
"removeIdentity",
"updateIdentity",
"getPreference",
"sendTelemetryPayload"
];
// Map of identities.
@@ -159,10 +166,65 @@ const ContainerService = {
}).catch(() => {
throw new Error("WebExtension startup failed. Unable to continue.");
});
this._sendEvent = new Metrics({
type: "sdk",
id: self.id,
version: self.version
}).sendEvent;
},
// utility methods
_containerTabCount(userContextId) {
// Returns the total of open and hidden tabs with this userContextId
let containerTabsCount = 0;
containerTabsCount += this._identitiesState[userContextId].openTabs;
containerTabsCount += this._identitiesState[userContextId].hiddenTabs.length;
return containerTabsCount;
},
_totalContainerTabsCount() {
// Returns the number of total open tabs across ALL containers
let totalContainerTabsCount = 0;
for (const userContextId in this._identitiesState) {
totalContainerTabsCount += this._identitiesState[userContextId].openTabs;
}
return totalContainerTabsCount;
},
_totalNonContainerTabsCount() {
// Returns the number of open tabs NOT IN a container
let totalNonContainerTabsCount = 0;
for (const tab of tabs) {
if (this._getUserContextIdFromTab(tab) === 0) {
++totalNonContainerTabsCount;
}
}
return totalNonContainerTabsCount;
},
_containersCounts() {
let containersCounts = { // eslint-disable-line prefer-const
"shown": 0,
"hidden": 0,
"total": 0
};
for (const userContextId in this._identitiesState) {
if (this._identitiesState[userContextId].openTabs > 0) {
++containersCounts.shown;
++containersCounts.total;
continue;
} else if (this._identitiesState[userContextId].hiddenTabs.length > 0) {
++containersCounts.hidden;
++containersCounts.total;
continue;
}
}
return containersCounts;
},
_convert(identity) {
// Let's convert the known colors to their color names.
return {
@@ -291,6 +353,17 @@ const ContainerService = {
ss.storage.identitiesData = this._identitiesState;
},
sendTelemetryPayload(args = {}) {
// when pings come from popup, delete "method" prop
delete args.method;
let payload = { // eslint-disable-line prefer-const
"uuid": this._metricsUUID
};
Object.assign(payload, args);
this._sendEvent(payload);
},
// Tabs management
hideTabs(args) {
@@ -303,6 +376,16 @@ const ContainerService = {
return Promise.resolve(null);
}
const containersCounts = this._containersCounts();
this.sendTelemetryPayload({
"event": "hide-tabs",
"userContextId": args.userContextId,
"clickedContainerTabCount": this._containerTabCount(args.userContextId),
"shownContainersCount": containersCounts.shown,
"hiddenContainersCount": containersCounts.hidden,
"totalContainersCount": containersCounts.total
});
const tabsToClose = [];
this._containerTabIterator(args.userContextId, tab => {
@@ -337,6 +420,16 @@ const ContainerService = {
return Promise.resolve(null);
}
const containersCounts = this._containersCounts();
this.sendTelemetryPayload({
"event": "show-tabs",
"userContextId": args.userContextId,
"clickedContainerTabCount": this._containerTabCount(args.userContextId),
"shownContainersCount": containersCounts.shown,
"hiddenContainersCount": containersCounts.hidden,
"totalContainersCount": containersCounts.total
});
const promises = [];
for (let object of this._identitiesState[args.userContextId].hiddenTabs) { // eslint-disable-line prefer-const
@@ -351,6 +444,13 @@ const ContainerService = {
},
sortTabs() {
const containersCounts = this._containersCounts();
this.sendTelemetryPayload({
"event": "sort-tabs",
"shownContainersCount": containersCounts.shown,
"totalContainerTabsCount": this._totalContainerTabsCount(),
"totalNonContainerTabsCount": this._totalNonContainerTabsCount()
});
return new Promise(resolve => {
for (let window of windows.browserWindows) { // eslint-disable-line prefer-const
// First the pinned tabs, then the normal ones.
@@ -460,6 +560,12 @@ const ContainerService = {
return;
}
this.sendTelemetryPayload({
"event": "move-tabs-to-window",
"userContextId": args.userContextId,
"clickedContainerTabCount": this._containerTabCount(args.userContextId),
});
// Let's create a list of the tabs.
const list = [];
this._containerTabIterator(args.userContextId, tab => {
@@ -500,9 +606,17 @@ const ContainerService = {
openTab(args) {
return this._recentBrowserWindow().then(browserWin => {
let userContextId = 0;
if ("userContextId" in args) {
userContextId = args.userContextId;
const userContextId = ("userContextId" in args) ? args.userContextId : 0;
const source = ("source" in args) ? args.source : null;
// Only send telemetry for tabs opened by UI - i.e., not via showTabs
if (source) {
this.sendTelemetryPayload({
"event": "open-tab",
"eventSource": source,
"userContextId": userContextId,
"clickedContainerTabCount": this._containerTabCount(userContextId)
});
}
const tab = browserWin.gBrowser.addTab(args.url || DEFAULT_TAB, { userContextId });
@@ -538,6 +652,10 @@ const ContainerService = {
},
createIdentity(args) {
this.sendTelemetryPayload({
"event": "add-container",
});
for (let arg of [ "name", "color", "icon"]) { // eslint-disable-line prefer-const
if (!(arg in args)) {
return Promise.reject("createIdentity must be called with " + arg + " argument.");
@@ -563,6 +681,11 @@ const ContainerService = {
return Promise.reject("updateIdentity must be called with userContextId argument.");
}
this.sendTelemetryPayload({
"event": "edit-container",
"userContextId": args.userContextId
});
const identity = ContextualIdentityService.getIdentityFromId(args.userContextId);
for (let arg of [ "name", "color", "icon"]) { // eslint-disable-line prefer-const
if ((arg in args)) {
@@ -589,6 +712,11 @@ const ContainerService = {
return Promise.reject("removeIdentity must be called with userContextId argument.");
}
this.sendTelemetryPayload({
"event": "delete-container",
"userContextId": args.userContextId
});
const tabsToClose = [];
this._containerTabIterator(args.userContextId, tab => {
tabsToClose.push(tab);
@@ -837,7 +965,10 @@ ContainerWindow.prototype = {
menuItemElement.setAttribute("data-identity-color", identity.color);
menuItemElement.addEventListener("command", (e) => {
ContainerService.openTab({userContextId: identity.userContextId});
ContainerService.openTab({
userContextId: identity.userContextId,
source: "tab-bar"
});
e.stopPropagation();
});
@@ -870,7 +1001,10 @@ ContainerWindow.prototype = {
_configureFileMenu() {
return this._configureMenu("menu_newUserContext", null, e => {
const userContextId = parseInt(e.target.getAttribute("data-usercontextid"), 10);
ContainerService.openTab({ userContextId });
ContainerService.openTab({
userContextId: userContextId,
source: "file-menu"
});
}, "_fileMenuElements");
},