Bug 1122050 - Adds addons data collection to TelemetryEnvironment. r=gfritzsche

This commit is contained in:
Alessio Placitelli 2015-02-25 23:54:32 +01:00
Родитель 8e60e95266
Коммит 485fac56a5
4 изменённых файлов: 215 добавлений и 8 удалений

Просмотреть файл

@ -10,6 +10,7 @@ this.EXPORTED_SYMBOLS = [
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Log.jsm"); Cu.import("resource://gre/modules/Log.jsm");
@ -19,6 +20,10 @@ Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ctypes", XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
"resource://gre/modules/ctypes.jsm"); "resource://gre/modules/ctypes.jsm");
#ifndef MOZ_WIDGET_GONK
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
#endif
XPCOMUtils.defineLazyModuleGetter(this, "ProfileTimesAccessor", XPCOMUtils.defineLazyModuleGetter(this, "ProfileTimesAccessor",
"resource://gre/modules/services/healthreport/profile.jsm"); "resource://gre/modules/services/healthreport/profile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel", XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
@ -77,6 +82,17 @@ function getSystemLocale() {
} }
} }
/**
* Asynchronously get a list of addons of the specified type from the AddonManager.
* @param aTypes An array containing the types of addons to request.
* @return Promise<Array> resolved when AddonManager has finished, returning an
* array of addons.
*/
function promiseGetAddonsByTypes(aTypes) {
return new Promise((resolve) =>
AddonManager.getAddonsByTypes(aTypes, (addons) => resolve(addons)));
}
/** /**
* Safely get a sysinfo property and return its value. If the property is not * Safely get a sysinfo property and return its value. If the property is not
* available, return aDefault. * available, return aDefault.
@ -629,6 +645,181 @@ this.TelemetryEnvironment = {
}; };
}, },
/**
* Get the addon data in object form.
* @return Object containing the addon data.
*/
_getActiveAddons: Task.async(function* () {
// Request addons, asynchronously.
let allAddons = yield promiseGetAddonsByTypes(["extension", "service"]);
let activeAddons = {};
for (let addon of allAddons) {
// Skip addons which are not active.
if (!addon.isActive) {
continue;
}
activeAddons[addon.id] = {
blocklisted: (addon.blocklistState !== Ci.nsIBlocklistService.STATE_NOT_BLOCKED),
description: addon.description,
name: addon.name,
userDisabled: addon.userDisabled,
appDisabled: addon.appDisabled,
version: addon.version,
scope: addon.scope,
type: addon.type,
foreignInstall: addon.foreignInstall,
hasBinaryComponents: addon.hasBinaryComponents,
installDay: truncateToDays(addon.installDate.getTime()),
updateDay: truncateToDays(addon.updateDate.getTime()),
};
}
return activeAddons;
}),
/**
* Get the currently active theme data in object form.
* @return Object containing the active theme data.
*/
_getActiveTheme: Task.async(function* () {
// Request themes, asynchronously.
let themes = yield promiseGetAddonsByTypes(["theme"]);
let activeTheme = {};
// We only store information about the active theme.
let theme = themes.find(theme => theme.isActive);
if (theme) {
activeTheme = {
id: theme.id,
blocklisted: (theme.blocklistState !== Ci.nsIBlocklistService.STATE_NOT_BLOCKED),
description: theme.description,
name: theme.name,
userDisabled: theme.userDisabled,
appDisabled: theme.appDisabled,
version: theme.version,
scope: theme.scope,
foreignInstall: theme.foreignInstall,
hasBinaryComponents: theme.hasBinaryComponents,
installDay: truncateToDays(theme.installDate.getTime()),
updateDay: truncateToDays(theme.updateDate.getTime()),
};
}
return activeTheme;
}),
/**
* Get the plugins data in object form.
* @return Object containing the plugins data.
*/
_getActivePlugins: function () {
let pluginTags =
Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost).getPluginTags({});
let activePlugins = [];
for (let tag of pluginTags) {
// Skip plugins which are not active.
if (tag.disabled) {
continue;
}
// Make sure to have a valid date.
let updateDate = new Date(Math.max(0, tag.lastModifiedTime));
activePlugins.push({
name: tag.name,
version: tag.version,
description: tag.description,
blocklisted: tag.blocklisted,
disabled: tag.disabled,
clicktoplay: tag.clicktoplay,
mimeTypes: tag.getMimeTypes({}),
updateDay: truncateToDays(updateDate.getTime()),
});
}
return activePlugins;
},
/**
* Get the GMPlugins data in object form.
* @return Object containing the GMPlugins data.
*/
_getActiveGMPlugins: Task.async(function* () {
// Request plugins, asynchronously.
let allPlugins = yield promiseGetAddonsByTypes(["plugin"]);
let activeGMPlugins = {};
for (let plugin of allPlugins) {
// Only get GM Plugin info.
if (!plugin.isGMPlugin) {
continue;
}
activeGMPlugins[plugin.id] = {
version: plugin.version,
userDisabled: plugin.userDisabled,
applyBackgroundUpdates: plugin.applyBackgroundUpdates,
};
}
return activeGMPlugins;
}),
/**
* Get the active experiment data in object form.
* @return Object containing the active experiment data.
*/
_getActiveExperiment: function () {
let experimentInfo = {};
try {
let scope = {};
Cu.import("resource:///modules/experiments/Experiments.jsm", scope);
let experiments = scope.Experiments.instance()
let activeExperiment = experiments.getActiveExperimentID();
if (activeExperiment) {
experimentInfo.id = activeExperiment;
experimentInfo.branch = experiments.getActiveExperimentBranch();
}
} catch(e) {
// If this is not Firefox, the import will fail.
return experimentInfo;
}
return experimentInfo;
},
/**
* Get the addon data in object form.
* @return Object containing the addon data.
*/
_getAddons: Task.async(function* () {
let activeAddons = yield this._getActiveAddons();
let activeTheme = yield this._getActiveTheme();
let activeGMPlugins = yield this._getActiveGMPlugins();
let personaId = null;
#ifndef MOZ_WIDGET_GONK
let theme = LightweightThemeManager.currentTheme;
if (theme) {
personaId = theme.id;
}
#endif
let addonData = {
activeAddons: activeAddons,
theme: activeTheme,
activePlugins: this._getActivePlugins(),
activeGMPlugins: activeGMPlugins,
activeExperiment: this._getActiveExperiment(),
persona: personaId,
};
return addonData;
}),
/** /**
* Get the environment data in object form. * Get the environment data in object form.
* @return Promise<Object> Resolved with the data on success, otherwise rejected. * @return Promise<Object> Resolved with the data on success, otherwise rejected.
@ -660,6 +851,7 @@ this.TelemetryEnvironment = {
"profile": () => this._getProfile(), "profile": () => this._getProfile(),
"partner": () => this._getPartner(), "partner": () => this._getPartner(),
"system": () => this._getSystem(), "system": () => this._getSystem(),
"addons": () => this._getAddons(),
}; };
let data = {}; let data = {};

Просмотреть файл

@ -123,7 +123,7 @@ Structure::
activeAddons: { // the currently enabled addons activeAddons: { // the currently enabled addons
<addon id>: { <addon id>: {
blocklisted: <bool>, blocklisted: <bool>,
description: <string>, description: <string>, // null if not available
name: <string>, name: <string>,
userDisabled: <bool>, userDisabled: <bool>,
appDisabled: <bool>, appDisabled: <bool>,

Просмотреть файл

@ -4,14 +4,29 @@
Components.utils.import("resource://gre/modules/TelemetryPing.jsm", this); Components.utils.import("resource://gre/modules/TelemetryPing.jsm", this);
Components.utils.import("resource://gre/modules/Services.jsm", this); Components.utils.import("resource://gre/modules/Services.jsm", this);
// copied from toolkit/mozapps/extensions/test/xpcshell/head_addons.js let gOldAppInfo = null;
const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1"; let gGlobalScope = this;
const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
let gAppInfo; function loadAddonManager(id, name, version, platformVersion) {
let gOldAppInfo = Components.classes[XULAPPINFO_CONTRACTID] let ns = {};
.getService(Components.interfaces.nsIXULRuntime); Cu.import("resource://gre/modules/Services.jsm", ns);
let head = "../../../../mozapps/extensions/test/xpcshell/head_addons.js";
let file = do_get_file(head);
let uri = ns.Services.io.newFileURI(file);
ns.Services.scriptloader.loadSubScript(uri.spec, gGlobalScope);
createAppInfo(id, name, version, platformVersion);
startupManager();
}
function createAppInfo(id, name, version, platformVersion) { function createAppInfo(id, name, version, platformVersion) {
const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
let gAppInfo;
if (!gOldAppInfo) {
gOldAppInfo = Components.classes[XULAPPINFO_CONTRACTID]
.getService(Components.interfaces.nsIXULRuntime);
}
gAppInfo = { gAppInfo = {
// nsIXULAppInfo // nsIXULAppInfo
vendor: "Mozilla", vendor: "Mozilla",

Просмотреть файл

@ -319,7 +319,7 @@ function run_test() {
do_test_pending(); do_test_pending();
spoofGfxAdapter(); spoofGfxAdapter();
do_get_profile(); do_get_profile();
createAppInfo(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION); loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION);
spoofPartnerInfo(); spoofPartnerInfo();
// Spoof the the hotfixVersion // Spoof the the hotfixVersion
Preferences.set("extensions.hotfix.lastVersion", APP_HOTFIX_VERSION); Preferences.set("extensions.hotfix.lastVersion", APP_HOTFIX_VERSION);