зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1445551: Part 1a - Add uses-unsafe-cpows annotation to mochitest harness. r=mconley
This allows us to specifically whitelist browser mochitests which still rely on unsafe CPOWs, and run them in a separate Sandbox global with permissive CPOWs enabled. The test harness and most of the in-tree tests will run with permissive CPOWs disabled, like the rest of the browser. MozReview-Commit-ID: CxIkuxr5PXJ --HG-- extra : rebase_source : 897c951e5ea84db58e92c8b627679f029ebf4a42
This commit is contained in:
Родитель
41ec48d989
Коммит
63ee0f9a5a
|
@ -110,6 +110,7 @@
|
|||
function browserTest(aTestFile) {
|
||||
this.path = aTestFile['url'];
|
||||
this.expected = aTestFile['expected'];
|
||||
this.usesUnsafeCPOWs = aTestFile['uses-unsafe-cpows'] || false;
|
||||
this.dumper = gDumper;
|
||||
this.results = [];
|
||||
this.scope = null;
|
||||
|
|
|
@ -379,6 +379,16 @@ function Tester(aTests, structuredLogger, aCallback) {
|
|||
this._scriptLoader = Services.scriptloader;
|
||||
this.EventUtils = {};
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", this.EventUtils);
|
||||
|
||||
// In order to allow existing tests to continue using unsafe CPOWs
|
||||
// with EventUtils, we need to load a separate copy into a sandbox
|
||||
// which has unsafe CPOW usage whitelisted.
|
||||
this.cpowSandbox = Cu.Sandbox(window, {sandboxPrototype: window});
|
||||
Cu.permitCPOWsInScope(this.cpowSandbox);
|
||||
|
||||
this.cpowEventUtils = new this.cpowSandbox.Object();
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", this.cpowEventUtils);
|
||||
|
||||
var simpleTestScope = {};
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js", simpleTestScope);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js", simpleTestScope);
|
||||
|
@ -970,16 +980,17 @@ Tester.prototype = {
|
|||
let currentTest = this.currentTest;
|
||||
|
||||
// Import utils in the test scope.
|
||||
this.currentTest.scope.EventUtils = this.EventUtils;
|
||||
this.currentTest.scope.SimpleTest = this.SimpleTest;
|
||||
this.currentTest.scope.gTestPath = this.currentTest.path;
|
||||
this.currentTest.scope.Task = this.Task;
|
||||
this.currentTest.scope.ContentTask = this.ContentTask;
|
||||
this.currentTest.scope.BrowserTestUtils = this.BrowserTestUtils;
|
||||
this.currentTest.scope.TestUtils = this.TestUtils;
|
||||
this.currentTest.scope.ExtensionTestUtils = this.ExtensionTestUtils;
|
||||
let {scope} = this.currentTest;
|
||||
scope.EventUtils = this.currentTest.usesUnsafeCPOWs ? this.cpowEventUtils : this.EventUtils;
|
||||
scope.SimpleTest = this.SimpleTest;
|
||||
scope.gTestPath = this.currentTest.path;
|
||||
scope.Task = this.Task;
|
||||
scope.ContentTask = this.ContentTask;
|
||||
scope.BrowserTestUtils = this.BrowserTestUtils;
|
||||
scope.TestUtils = this.TestUtils;
|
||||
scope.ExtensionTestUtils = this.ExtensionTestUtils;
|
||||
// Pass a custom report function for mochitest style reporting.
|
||||
this.currentTest.scope.Assert = new this.Assert(function(err, message, stack) {
|
||||
scope.Assert = new this.Assert(function(err, message, stack) {
|
||||
currentTest.addResult(new testResult(err ? {
|
||||
name: err.message,
|
||||
ex: err.stack,
|
||||
|
@ -996,7 +1007,7 @@ Tester.prototype = {
|
|||
this.ContentTask.setTestScope(currentScope);
|
||||
|
||||
// Allow Assert.jsm methods to be tacked to the current scope.
|
||||
this.currentTest.scope.export_assertions = function() {
|
||||
scope.export_assertions = function() {
|
||||
for (let func in this.Assert) {
|
||||
this[func] = this.Assert[func].bind(this.Assert);
|
||||
}
|
||||
|
@ -1005,11 +1016,11 @@ Tester.prototype = {
|
|||
// Override SimpleTest methods with ours.
|
||||
SIMPLETEST_OVERRIDES.forEach(function(m) {
|
||||
this.SimpleTest[m] = this[m];
|
||||
}, this.currentTest.scope);
|
||||
}, scope);
|
||||
|
||||
//load the tools to work with chrome .jar and remote
|
||||
try {
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/chrome-harness.js", this.currentTest.scope);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/chrome-harness.js", scope);
|
||||
} catch (ex) { /* no chrome-harness tools */ }
|
||||
|
||||
// Import head.js script if it exists.
|
||||
|
@ -1017,7 +1028,7 @@ Tester.prototype = {
|
|||
this.currentTest.path.substr(0, this.currentTest.path.lastIndexOf("/"));
|
||||
var headPath = currentTestDirPath + "/head.js";
|
||||
try {
|
||||
this._scriptLoader.loadSubScript(headPath, this.currentTest.scope);
|
||||
this._scriptLoader.loadSubScript(headPath, scope);
|
||||
} catch (ex) {
|
||||
// Ignore if no head.js exists, but report all other errors. Note this
|
||||
// will also ignore an existing head.js attempting to import a missing
|
||||
|
@ -1032,8 +1043,7 @@ Tester.prototype = {
|
|||
|
||||
// Import the test script.
|
||||
try {
|
||||
this._scriptLoader.loadSubScript(this.currentTest.path,
|
||||
this.currentTest.scope);
|
||||
this._scriptLoader.loadSubScript(this.currentTest.path, scope);
|
||||
// Run the test
|
||||
this.lastStartTime = Date.now();
|
||||
if (this.currentTest.scope.__tasks) {
|
||||
|
@ -1091,8 +1101,8 @@ Tester.prototype = {
|
|||
}
|
||||
this.finish();
|
||||
}.bind(currentScope));
|
||||
} else if (typeof this.currentTest.scope.test == "function") {
|
||||
this.currentTest.scope.test();
|
||||
} else if (typeof scope.test == "function") {
|
||||
scope.test();
|
||||
} else {
|
||||
throw "This test didn't call add_task, nor did it define a generatorTest() function, nor did it define a test() function, so we don't know how to run it.";
|
||||
}
|
||||
|
@ -1372,6 +1382,18 @@ function testScope(aTester, aTest, expected) {
|
|||
self.__tester.structuredLogger.activateBuffering();
|
||||
})
|
||||
};
|
||||
|
||||
// If we're running a test that requires unsafe CPOWs, create a
|
||||
// separate sandbox scope, with CPOWS whitelisted, for that test, and
|
||||
// mirror all of our properties onto it. Test files will be loaded
|
||||
// into this sandbox.
|
||||
//
|
||||
// Otherwise, load test files directly into the testScope instance.
|
||||
if (aTest.usesUnsafeCPOWs) {
|
||||
let sandbox = this._createSandbox();
|
||||
Cu.permitCPOWsInScope(sandbox);
|
||||
return sandbox;
|
||||
}
|
||||
}
|
||||
|
||||
function decorateTaskFn(fn) {
|
||||
|
@ -1400,6 +1422,29 @@ testScope.prototype = {
|
|||
ExtensionTestUtils: null,
|
||||
Assert: null,
|
||||
|
||||
_createSandbox() {
|
||||
let sandbox = Cu.Sandbox(window, {sandboxPrototype: window});
|
||||
|
||||
for (let prop in this) {
|
||||
if (typeof this[prop] == "function") {
|
||||
sandbox[prop] = this[prop].bind(this);
|
||||
} else {
|
||||
Object.defineProperty(sandbox, prop, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: () => {
|
||||
return this[prop];
|
||||
},
|
||||
set: (value) => {
|
||||
this[prop] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return sandbox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a test function which is a Task function.
|
||||
*
|
||||
|
|
|
@ -26,10 +26,10 @@ function parseTestManifest(testManifest, params, callback) {
|
|||
}
|
||||
if (params.testRoot != 'tests' && params.testRoot !== undefined) {
|
||||
name = params.baseurl + '/' + params.testRoot + '/' + path;
|
||||
links[name] = {'test': {'url': name, 'expected': obj['expected']}};
|
||||
links[name] = {'test': {'url': name, 'expected': obj['expected'], 'uses-unsafe-cpows': obj['uses-unsafe-cpows']}};
|
||||
} else {
|
||||
name = params.testPrefix + path;
|
||||
paths.push({'test': {'url': name, 'expected': obj['expected']}});
|
||||
paths.push({'test': {'url': name, 'expected': obj['expected'], 'uses-unsafe-cpows': obj['uses-unsafe-cpows']}});
|
||||
}
|
||||
}
|
||||
if (paths.length > 0) {
|
||||
|
|
|
@ -1524,6 +1524,8 @@ toolbar#nav-bar {
|
|||
testob['disabled'] = test['disabled']
|
||||
if 'expected' in test:
|
||||
testob['expected'] = test['expected']
|
||||
if 'uses-unsafe-cpows' in test:
|
||||
testob['uses-unsafe-cpows'] = test['uses-unsafe-cpows'] == 'true'
|
||||
if 'scheme' in test:
|
||||
testob['scheme'] = test['scheme']
|
||||
if options.failure_pattern_file:
|
||||
|
|
|
@ -176,6 +176,10 @@ function sendMouseEvent(aEvent, aTarget, aWindow) {
|
|||
ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg,
|
||||
buttonArg, relatedTargetArg);
|
||||
|
||||
// If documentURIObject exists or `window` is a stub object, we're in
|
||||
// a chrome scope, so don't bother trying to go through SpecialPowers.
|
||||
if (!window.document || window.document.documentURIObject)
|
||||
return aTarget.dispatchEvent(event);
|
||||
return SpecialPowers.dispatchEvent(aWindow, aTarget, event);
|
||||
}
|
||||
|
||||
|
@ -1240,6 +1244,14 @@ function _getDOMWindowUtils(aWindow = window)
|
|||
aWindow = window;
|
||||
}
|
||||
|
||||
// If documentURIObject exists or `window` is a stub object, we're in
|
||||
// a chrome scope, so don't bother trying to go through SpecialPowers.
|
||||
if (!window.document || window.document.documentURIObject) {
|
||||
return aWindow
|
||||
.QueryInterface(_EU_Ci.nsIInterfaceRequestor)
|
||||
.getInterface(_EU_Ci.nsIDOMWindowUtils);
|
||||
}
|
||||
|
||||
// we need parent.SpecialPowers for:
|
||||
// layout/base/tests/test_reftests_with_caret.html
|
||||
// chrome: toolkit/content/tests/chrome/test_findbar.xul
|
||||
|
|
Загрузка…
Ссылка в новой задаче