зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1122050 - Adds addons data collection to TelemetryEnvironment. r=gfritzsche
This commit is contained in:
Родитель
8e60e95266
Коммит
485fac56a5
|
@ -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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче