Bug 809644 - Health Report provider for application info; r=rnewman

This commit is contained in:
Gregory Szorc 2012-11-12 15:50:04 -08:00
parent ed77007664
commit 7c16f3f755
6 changed files with 240 additions and 0 deletions

View File

@ -9,3 +9,5 @@ component {e354c59b-b252-4040-b6dd-b71864e3e35c} HealthReportService.js
contract @mozilla.org/healthreport/service;1 {e354c59b-b252-4040-b6dd-b71864e3e35c}
category app-startup HealthReportService service,@mozilla.org/healthreport/service;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
category healthreport-js-provider AppInfoProvider resource://gre/modules/services/healthreport/providers.jsm

View File

@ -12,6 +12,7 @@ include $(DEPTH)/config/autoconf.mk
modules := \
healthreporter.jsm \
policy.jsm \
providers.jsm \
$(NULL)
testing_modules := \

View File

@ -0,0 +1,154 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This file contains metrics data providers for the Firefox Health
* Report. Ideally each provider in this file exists in separate modules
* and lives close to the code it is querying. However, because of the
* overhead of JS compartments (which are created for each module), we
* currently have all the code in one file. When the overhead of
* compartments reaches a reasonable level, this file should be split
* up.
*/
"use strict";
this.EXPORTED_SYMBOLS = [
"AppInfoProvider"
];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-common/utils.js");
const REQUIRED_STRING_TYPE = {type: "TYPE_STRING"};
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
"resource://gre/modules/UpdateChannel.jsm");
/**
* Represents basic application state.
*
* This is roughly a union of nsIXULAppInfo, nsIXULRuntime, with a few extra
* pieces thrown in.
*/
function AppInfoMeasurement() {
MetricsMeasurement.call(this, "appinfo", 1);
}
AppInfoMeasurement.prototype = {
__proto__: MetricsMeasurement.prototype,
fields: {
vendor: REQUIRED_STRING_TYPE,
name: REQUIRED_STRING_TYPE,
id: REQUIRED_STRING_TYPE,
version: REQUIRED_STRING_TYPE,
appBuildID: REQUIRED_STRING_TYPE,
platformVersion: REQUIRED_STRING_TYPE,
platformBuildID: REQUIRED_STRING_TYPE,
os: REQUIRED_STRING_TYPE,
xpcomabi: REQUIRED_STRING_TYPE,
updateChannel: REQUIRED_STRING_TYPE,
distributionID: REQUIRED_STRING_TYPE,
distributionVersion: REQUIRED_STRING_TYPE,
hotfixVersion: REQUIRED_STRING_TYPE,
locale: REQUIRED_STRING_TYPE,
},
};
Object.freeze(AppInfoMeasurement.prototype);
this.AppInfoProvider = function AppInfoProvider() {
MetricsProvider.call(this, "app-info");
this._prefs = new Preferences({defaultBranch: null});
}
AppInfoProvider.prototype = {
__proto__: MetricsProvider.prototype,
appInfoFields: {
// From nsIXULAppInfo.
vendor: "vendor",
name: "name",
id: "ID",
version: "version",
appBuildID: "appBuildID",
platformVersion: "platformVersion",
platformBuildID: "platformBuildID",
// From nsIXULRuntime.
os: "OS",
xpcomabi: "XPCOMABI",
},
collectConstantMeasurements: function collectConstantMeasurements() {
let result = this.createResult();
result.expectMeasurement("appinfo");
result.populate = this._populateConstants.bind(this);
return result;
},
_populateConstants: function _populateConstants(result) {
result.addMeasurement(new AppInfoMeasurement());
let ai;
try {
ai = Services.appinfo;
} catch (ex) {
this._log.warn("Could not obtain Services.appinfo: " +
CommonUtils.exceptionStr(ex));
throw ex;
}
if (!ai) {
this._log.warn("Services.appinfo is unavailable.");
throw ex;
}
for (let [k, v] in Iterator(this.appInfoFields)) {
try {
result.setValue("appinfo", k, ai[v]);
} catch (ex) {
this._log.warn("Error obtaining Services.appinfo." + v);
result.addError(ex);
}
}
try {
result.setValue("appinfo", "updateChannel", UpdateChannel.get());
} catch (ex) {
this._log.warn("Could not obtain update channel: " +
CommonUtils.exceptionStr(ex));
result.addError(ex);
}
result.setValue("appinfo", "distributionID", this._prefs.get("distribution.id", ""));
result.setValue("appinfo", "distributionVersion", this._prefs.get("distribution.version", ""));
result.setValue("appinfo", "hotfixVersion", this._prefs.get("extensions.hotfix.lastVersion", ""));
try {
let locale = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIXULChromeRegistry)
.getSelectedLocale("global");
result.setValue("appinfo", "locale", locale);
} catch (ex) {
this._log.warn("Could not obtain application locale: " +
CommonUtils.exceptionStr(ex));
result.addError(ex);
}
result.finish();
},
};
Object.freeze(AppInfoProvider.prototype);

View File

@ -6,6 +6,7 @@
const modules = [
"healthreporter.jsm",
"policy.jsm",
"providers.jsm",
];
const test_modules = [

View File

@ -0,0 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/services/healthreport/providers.jsm");
Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm");
function run_test() {
let appInfo = {
vendor: "Mozilla",
name: "xpcshell",
ID: "xpcshell@tests.mozilla.org",
version: "1",
appBuildID: "20121107",
platformVersion: "p-ver",
platformBuildID: "20121106",
inSafeMode: false,
logConsoleErrors: true,
OS: "XPCShell",
XPCOMABI: "noarch-spidermonkey",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo, Ci.nsIXULRuntime]),
invalidateCachesOnRestart: function() {},
};
let factory = {
createInstance: function createInstance(outer, iid) {
if (outer != null) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return appInfo.QueryInterface(iid);
},
};
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"),
"XULAppInfo", "@mozilla.org/xre/app-info;1",
factory);
run_next_test();
}
add_test(function test_constructor() {
let provider = new AppInfoProvider();
run_next_test();
});
add_test(function test_collect_smoketest() {
let provider = new AppInfoProvider();
let result = provider.collectConstantMeasurements();
do_check_true(result instanceof MetricsCollectionResult);
result.onFinished(function onFinished() {
do_check_eq(result.expectedMeasurements.size, 1);
do_check_true(result.expectedMeasurements.has("appinfo"));
do_check_eq(result.measurements.size, 1);
do_check_true(result.measurements.has("appinfo"));
do_check_eq(result.errors.length, 0);
let ai = result.measurements.get("appinfo");
do_check_eq(ai.getValue("vendor"), "Mozilla");
do_check_eq(ai.getValue("name"), "xpcshell");
do_check_eq(ai.getValue("id"), "xpcshell@tests.mozilla.org");
do_check_eq(ai.getValue("version"), "1");
do_check_eq(ai.getValue("appBuildID"), "20121107");
do_check_eq(ai.getValue("platformVersion"), "p-ver");
do_check_eq(ai.getValue("platformBuildID"), "20121106");
do_check_eq(ai.getValue("os"), "XPCShell");
do_check_eq(ai.getValue("xpcomabi"), "noarch-spidermonkey");
run_next_test();
});
result.populate(result);
});

View File

@ -5,3 +5,4 @@ tail =
[test_load_modules.js]
[test_policy.js]
[test_healthreporter.js]
[test_provider_appinfo.js]