зеркало из https://github.com/mozilla/gecko-dev.git
870 строки
21 KiB
JavaScript
870 строки
21 KiB
JavaScript
/* 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/. */
|
|
|
|
// Ideally this would be an xpcshell test, but Troubleshoot relies on things
|
|
// that aren't initialized outside of a XUL app environment like AddonManager
|
|
// and the "@mozilla.org/xre/app-info;1" component.
|
|
|
|
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
ChromeUtils.import("resource://gre/modules/Troubleshoot.jsm");
|
|
|
|
function test() {
|
|
waitForExplicitFinish();
|
|
function doNextTest() {
|
|
if (!tests.length) {
|
|
finish();
|
|
return;
|
|
}
|
|
tests.shift()(doNextTest);
|
|
}
|
|
doNextTest();
|
|
}
|
|
|
|
registerCleanupFunction(function() {
|
|
// Troubleshoot.jsm is imported into the global scope -- the window -- above.
|
|
// If it's not deleted, it outlives the test and is reported as a leak.
|
|
delete window.Troubleshoot;
|
|
});
|
|
|
|
var tests = [
|
|
|
|
function snapshotSchema(done) {
|
|
Troubleshoot.snapshot(function(snapshot) {
|
|
try {
|
|
validateObject(snapshot, SNAPSHOT_SCHEMA);
|
|
ok(true, "The snapshot should conform to the schema.");
|
|
} catch (err) {
|
|
ok(false, "Schema mismatch, " + err);
|
|
}
|
|
done();
|
|
});
|
|
},
|
|
|
|
function modifiedPreferences(done) {
|
|
let prefs = [
|
|
"javascript.troubleshoot",
|
|
"troubleshoot.foo",
|
|
"javascript.print_to_filename",
|
|
"network.proxy.troubleshoot",
|
|
];
|
|
prefs.forEach(function(p) {
|
|
Services.prefs.setBoolPref(p, true);
|
|
is(Services.prefs.getBoolPref(p), true, "The pref should be set: " + p);
|
|
});
|
|
Troubleshoot.snapshot(function(snapshot) {
|
|
let p = snapshot.modifiedPreferences;
|
|
is(p["javascript.troubleshoot"], true,
|
|
"The pref should be present because it's whitelisted " +
|
|
"but not blacklisted.");
|
|
ok(!("troubleshoot.foo" in p),
|
|
"The pref should be absent because it's not in the whitelist.");
|
|
ok(!("javascript.print_to_filename" in p),
|
|
"The pref should be absent because it's blacklisted.");
|
|
ok(!("network.proxy.troubleshoot" in p),
|
|
"The pref should be absent because it's blacklisted.");
|
|
prefs.forEach(p => Services.prefs.deleteBranch(p));
|
|
done();
|
|
});
|
|
},
|
|
|
|
function unicodePreferences(done) {
|
|
let name = "font.name.sans-serif.x-western";
|
|
let utf8Value = "\xc4\x8capk\xc5\xafv Krasopis";
|
|
let unicodeValue = "\u010Capk\u016Fv Krasopis";
|
|
|
|
// set/getCharPref work with 8bit strings (utf8)
|
|
Services.prefs.setCharPref(name, utf8Value);
|
|
|
|
Troubleshoot.snapshot(function(snapshot) {
|
|
let p = snapshot.modifiedPreferences;
|
|
is(p[name], unicodeValue, "The pref should have correct Unicode value.");
|
|
Services.prefs.deleteBranch(name);
|
|
done();
|
|
});
|
|
}
|
|
];
|
|
|
|
// This is inspired by JSON Schema, or by the example on its Wikipedia page
|
|
// anyway.
|
|
const SNAPSHOT_SCHEMA = {
|
|
type: "object",
|
|
required: true,
|
|
properties: {
|
|
application: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
buildID: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
userAgent: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
osVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
vendor: {
|
|
type: "string",
|
|
},
|
|
updateChannel: {
|
|
type: "string",
|
|
},
|
|
supportURL: {
|
|
type: "string",
|
|
},
|
|
remoteAutoStart: {
|
|
type: "boolean",
|
|
required: true,
|
|
},
|
|
autoStartStatus: {
|
|
type: "number",
|
|
},
|
|
numTotalWindows: {
|
|
type: "number",
|
|
},
|
|
numRemoteWindows: {
|
|
type: "number",
|
|
},
|
|
currentContentProcesses: {
|
|
type: "number",
|
|
},
|
|
maxContentProcesses: {
|
|
type: "number",
|
|
},
|
|
policiesStatus: {
|
|
type: "number",
|
|
},
|
|
keyGoogleFound: {
|
|
type: "boolean",
|
|
},
|
|
keyMozillaFound: {
|
|
type: "boolean",
|
|
},
|
|
safeMode: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
crashes: {
|
|
required: false,
|
|
type: "object",
|
|
properties: {
|
|
pending: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
submitted: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
id: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
date: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
pending: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
extensions: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
id: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
isActive: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
securitySoftware: {
|
|
required: false,
|
|
type: "object",
|
|
properties: {
|
|
registeredAntiVirus: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
registeredAntiSpyware: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
registeredFirewall: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
features: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
id: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
modifiedPreferences: {
|
|
required: true,
|
|
type: "object",
|
|
},
|
|
lockedPreferences: {
|
|
required: true,
|
|
type: "object",
|
|
},
|
|
graphics: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
numTotalWindows: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
numAcceleratedWindows: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
windowLayerManagerType: {
|
|
type: "string",
|
|
},
|
|
windowLayerManagerRemote: {
|
|
type: "boolean",
|
|
},
|
|
windowUsingAdvancedLayers: {
|
|
type: "boolean",
|
|
},
|
|
numAcceleratedWindowsMessage: {
|
|
type: "array",
|
|
},
|
|
adapterDescription: {
|
|
type: "string",
|
|
},
|
|
adapterVendorID: {
|
|
type: "string",
|
|
},
|
|
adapterDeviceID: {
|
|
type: "string",
|
|
},
|
|
adapterSubsysID: {
|
|
type: "string",
|
|
},
|
|
adapterRAM: {
|
|
type: "string",
|
|
},
|
|
adapterDrivers: {
|
|
type: "string",
|
|
},
|
|
driverVersion: {
|
|
type: "string",
|
|
},
|
|
driverDate: {
|
|
type: "string",
|
|
},
|
|
adapterDescription2: {
|
|
type: "string",
|
|
},
|
|
adapterVendorID2: {
|
|
type: "string",
|
|
},
|
|
adapterDeviceID2: {
|
|
type: "string",
|
|
},
|
|
adapterSubsysID2: {
|
|
type: "string",
|
|
},
|
|
adapterRAM2: {
|
|
type: "string",
|
|
},
|
|
adapterDrivers2: {
|
|
type: "string",
|
|
},
|
|
driverVersion2: {
|
|
type: "string",
|
|
},
|
|
driverDate2: {
|
|
type: "string",
|
|
},
|
|
isGPU2Active: {
|
|
type: "boolean",
|
|
},
|
|
direct2DEnabled: {
|
|
type: "boolean",
|
|
},
|
|
directWriteEnabled: {
|
|
type: "boolean",
|
|
},
|
|
directWriteVersion: {
|
|
type: "string",
|
|
},
|
|
usesTiling: {
|
|
type: "boolean",
|
|
},
|
|
contentUsesTiling: {
|
|
type: "boolean",
|
|
},
|
|
offMainThreadPaintEnabled: {
|
|
type: "boolean",
|
|
},
|
|
offMainThreadPaintWorkerCount: {
|
|
type: "number",
|
|
},
|
|
clearTypeParameters: {
|
|
type: "string",
|
|
},
|
|
webgl1Renderer: {
|
|
type: "string",
|
|
},
|
|
webgl1Version: {
|
|
type: "string",
|
|
},
|
|
webgl1DriverExtensions: {
|
|
type: "string",
|
|
},
|
|
webgl1Extensions: {
|
|
type: "string",
|
|
},
|
|
webgl1WSIInfo: {
|
|
type: "string",
|
|
},
|
|
webgl2Renderer: {
|
|
type: "string",
|
|
},
|
|
webgl2Version: {
|
|
type: "string",
|
|
},
|
|
webgl2DriverExtensions: {
|
|
type: "string",
|
|
},
|
|
webgl2Extensions: {
|
|
type: "string",
|
|
},
|
|
webgl2WSIInfo: {
|
|
type: "string",
|
|
},
|
|
info: {
|
|
type: "object",
|
|
},
|
|
failures: {
|
|
type: "array",
|
|
items: {
|
|
type: "string",
|
|
},
|
|
},
|
|
indices: {
|
|
type: "array",
|
|
items: {
|
|
type: "number",
|
|
},
|
|
},
|
|
featureLog: {
|
|
type: "object",
|
|
},
|
|
crashGuards: {
|
|
type: "array",
|
|
},
|
|
direct2DEnabledMessage: {
|
|
type: "array",
|
|
},
|
|
},
|
|
},
|
|
media: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
currentAudioBackend: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
currentMaxAudioChannels: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
currentPreferredSampleRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
audioOutputDevices: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
groupId: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
vendor: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
type: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
state: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
preferred: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
supportedFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxChannels: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxLatency: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minLatency: {
|
|
required: true,
|
|
type: "number",
|
|
}
|
|
},
|
|
},
|
|
},
|
|
audioInputDevices: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
groupId: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
vendor: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
type: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
state: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
preferred: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
supportedFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultFormat: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxChannels: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
defaultRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minRate: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
maxLatency: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
minLatency: {
|
|
required: true,
|
|
type: "number",
|
|
}
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
javaScript: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
incrementalGCEnabled: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
accessibility: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
isActive: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
forceDisabled: {
|
|
type: "number",
|
|
},
|
|
handlerUsed: {
|
|
type: "boolean",
|
|
},
|
|
instantiator: {
|
|
type: "string"
|
|
}
|
|
},
|
|
},
|
|
libraryVersions: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
NSPR: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSS: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSSUTIL: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSSSSL: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
NSSSMIME: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
minVersion: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
version: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
userJS: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
exists: {
|
|
required: true,
|
|
type: "boolean",
|
|
},
|
|
},
|
|
},
|
|
sandbox: {
|
|
required: false,
|
|
type: "object",
|
|
properties: {
|
|
hasSeccompBPF: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean"
|
|
},
|
|
hasSeccompTSync: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean"
|
|
},
|
|
hasUserNamespaces: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean"
|
|
},
|
|
hasPrivilegedUserNamespaces: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "boolean"
|
|
},
|
|
canSandboxContent: {
|
|
required: false,
|
|
type: "boolean"
|
|
},
|
|
canSandboxMedia: {
|
|
required: false,
|
|
type: "boolean"
|
|
},
|
|
contentSandboxLevel: {
|
|
required: AppConstants.MOZ_CONTENT_SANDBOX,
|
|
type: "number"
|
|
},
|
|
effectiveContentSandboxLevel: {
|
|
required: AppConstants.MOZ_CONTENT_SANDBOX,
|
|
type: "number"
|
|
},
|
|
syscallLog: {
|
|
required: AppConstants.platform == "linux",
|
|
type: "array",
|
|
items: {
|
|
type: "object",
|
|
properties: {
|
|
index: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
pid: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
tid: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
procType: {
|
|
required: true,
|
|
type: "string",
|
|
},
|
|
syscall: {
|
|
required: true,
|
|
type: "number",
|
|
},
|
|
args: {
|
|
required: true,
|
|
type: "array",
|
|
items: {
|
|
type: "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
intl: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
localeService: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
requested: {
|
|
required: true,
|
|
type: "array"
|
|
},
|
|
available: {
|
|
required: true,
|
|
type: "array"
|
|
},
|
|
supported: {
|
|
required: true,
|
|
type: "array"
|
|
},
|
|
regionalPrefs: {
|
|
required: true,
|
|
type: "array"
|
|
},
|
|
defaultLocale: {
|
|
required: true,
|
|
type: "string"
|
|
},
|
|
},
|
|
},
|
|
osPrefs: {
|
|
required: true,
|
|
type: "object",
|
|
properties: {
|
|
systemLocales: {
|
|
required: true,
|
|
type: "array"
|
|
},
|
|
regionalPrefsLocales: {
|
|
required: true,
|
|
type: "array"
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Throws an Error if obj doesn't conform to schema. That way you get a nice
|
|
* error message and a stack to help you figure out what went wrong, which you
|
|
* wouldn't get if this just returned true or false instead. There's still
|
|
* room for improvement in communicating validation failures, however.
|
|
*
|
|
* @param obj The object to validate.
|
|
* @param schema The schema that obj should conform to.
|
|
*/
|
|
function validateObject(obj, schema) {
|
|
if (obj === undefined && !schema.required)
|
|
return;
|
|
if (typeof(schema.type) != "string")
|
|
throw schemaErr("'type' must be a string", schema);
|
|
if (objType(obj) != schema.type)
|
|
throw validationErr("Object is not of the expected type", obj, schema);
|
|
let validatorFnName = "validateObject_" + schema.type;
|
|
if (!(validatorFnName in this))
|
|
throw schemaErr("Validator function not defined for type", schema);
|
|
this[validatorFnName](obj, schema);
|
|
}
|
|
|
|
function validateObject_object(obj, schema) {
|
|
if (typeof(schema.properties) != "object")
|
|
// Don't care what obj's properties are.
|
|
return;
|
|
// First check that all the schema's properties match the object.
|
|
for (let prop in schema.properties)
|
|
validateObject(obj[prop], schema.properties[prop]);
|
|
// Now check that the object doesn't have any properties not in the schema.
|
|
for (let prop in obj)
|
|
if (!(prop in schema.properties))
|
|
throw validationErr("Object has property " + prop + " not in schema", obj, schema);
|
|
}
|
|
|
|
function validateObject_array(array, schema) {
|
|
if (typeof(schema.items) != "object")
|
|
// Don't care what the array's elements are.
|
|
return;
|
|
array.forEach(elt => validateObject(elt, schema.items));
|
|
}
|
|
|
|
function validateObject_string(str, schema) {}
|
|
function validateObject_boolean(bool, schema) {}
|
|
function validateObject_number(num, schema) {}
|
|
|
|
function validationErr(msg, obj, schema) {
|
|
return new Error("Validation error: " + msg +
|
|
": object=" + JSON.stringify(obj) +
|
|
", schema=" + JSON.stringify(schema));
|
|
}
|
|
|
|
function schemaErr(msg, schema) {
|
|
return new Error("Schema error: " + msg + ": " + JSON.stringify(schema));
|
|
}
|
|
|
|
function objType(obj) {
|
|
let type = typeof(obj);
|
|
if (type != "object")
|
|
return type;
|
|
if (Array.isArray(obj))
|
|
return "array";
|
|
if (obj === null)
|
|
return "null";
|
|
return type;
|
|
}
|