Bug 1638988: Add SpecialPowers.spawnChrome. r=mccr8

Differential Revision: https://phabricator.services.mozilla.com/D75832
This commit is contained in:
Kris Maglione 2020-05-18 21:00:51 +00:00
parent 06a240a0f3
commit 58a72e8979
6 changed files with 123 additions and 24 deletions

View File

@ -25,6 +25,7 @@ support-files =
[test_SpecialPowersSandbox.html]
[test_SpecialPowersSpawn.html]
support-files = file_spawn.html
[test_SpecialPowersSpawnChrome.html]
[test_SimpletestGetTestFileURL.html]
[test_SpecialPowersLoadChromeScript.html]
support-files = SpecialPowersLoadChromeScript.js

View File

@ -87,6 +87,14 @@ add_task(async function() {
});
});
},
"SpecialPowers.spawnChrome": () => {
return SpecialPowers.spawnChrome([], async () => {
Assert.equal(1, 2, "Thing");
Assert.equal(1, 1, "Hmm");
Assert.ok(true, "Yay.");
Assert.ok(false, "Boo!.");
});
},
"SpecialPowers.loadChromeScript": async () => {
let script = SpecialPowers.loadChromeScript(() => {
this.addMessageListener("ping", () => "pong");

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SpecialPowers.spawnChrome</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
/* eslint-disable prettier/prettier */
add_task(async function() {
let { browsingContextId, innerWindowId } = await SpecialPowers.spawnChrome([12, { b: 42 }], (a, b) => {
Assert.equal(a, 12, "Arg 1");
Assert.equal(b.b, 42, "Arg 2");
Assert.equal(Services.appinfo.processType,
Services.appinfo.PROCESS_TYPE_DEFAULT,
"Task runs in correct process");
return {
browsingContextId: browsingContext.id,
innerWindowId: windowGlobalParent.innerWindowId,
};
});
let wgc = SpecialPowers.wrap(window).windowGlobalChild;
is(browsingContextId, wgc.browsingContext.id, "Correct browsing context id");
is(innerWindowId, wgc.innerWindowId, "Correct inner window id");
});
</script>
</body>
</html>

View File

@ -1696,6 +1696,21 @@ class SpecialPowersChild extends JSWindowActorChild {
});
}
/**
* Like `spawn`, but spawns a chrome task in the parent process,
* instead. The task additionally has access to `windowGlobalParent`
* and `browsingContext` globals corresponding to the window from
* which the task was spawned.
*/
spawnChrome(args, task) {
return this.sendQuery("SpawnChrome", {
args,
task: String(task),
caller: Cu.getFunctionSourceLocation(task),
imports: this._spawnTaskImports,
});
}
snapshotContext(target, rect, background) {
let browsingContext = this._browsingContextForTarget(target);

View File

@ -608,6 +608,30 @@ class SpecialPowersParent extends JSWindowActorParent {
}
}
_spawnChrome(task, args, caller, imports) {
let sb = new SpecialPowersSandbox(
null,
data => {
this.sendAsyncMessage("Assert", data);
},
{ imports }
);
for (let [global, prop] of Object.entries({
windowGlobalParent: "manager",
browsingContext: "browsingContext",
})) {
Object.defineProperty(sb.sandbox, global, {
get: () => {
return this[prop];
},
enumerable: true,
});
}
return sb.execute(task, args, caller);
}
/**
* messageManager callback function
* This will get requests from our API in the window and process them in chrome for it
@ -1120,6 +1144,12 @@ class SpecialPowersParent extends JSWindowActorParent {
.finally(() => spParent._taskActors.delete(taskId));
}
case "SpawnChrome": {
let { task, args, caller, imports } = aMessage.data;
return this._spawnChrome(task, args, caller, imports);
}
case "Snapshot": {
let { browsingContext, rect, background } = aMessage.data;

View File

@ -19,6 +19,30 @@
var helpers = require("../helpers");
var frameScriptEnv = require("../environments/frame-script");
// The global environment of SpecialPowers.spawn tasks is
// controlled by the Sandbox environment created by
// SpecialPowersSandbox.jsm. This list should be kept in sync with
// that module.
var sandboxGlobals = [
"Assert",
"Blob",
"BrowsingContext",
"ChromeUtils",
"ContentTaskUtils",
"EventUtils",
"Services",
"TextDecoder",
"TextEncoder",
"URL",
"assert",
"info",
"is",
"isnot",
"ok",
"todo",
"todo_is",
];
module.exports = function(context) {
// ---------------------------------------------------------------------------
// Public
@ -39,31 +63,18 @@ module.exports = function(context) {
"CallExpression[callee.object.name='SpecialPowers'][callee.property.name='spawn']": function(
node
) {
// The global environment of SpecialPowers.spawn tasks is
// controlled by the Sandbox environment created by
// SpecialPowersSandbox.jsm. This list should be kept in sync with
// that module.
let globals = [...sandboxGlobals, "SpecialPowers", "content", "docShell"];
for (let global of globals) {
helpers.addVarToScope(global, context.getScope(), false);
}
},
"CallExpression[callee.object.name='SpecialPowers'][callee.property.name='spawnChrome']": function(
node
) {
let globals = [
"Assert",
"Blob",
"BrowsingContext",
"ChromeUtils",
"ContentTaskUtils",
"EventUtils",
"Services",
"SpecialPowers",
"TextDecoder",
"TextEncoder",
"URL",
"assert",
"content",
"docShell",
"info",
"is",
"isnot",
"ok",
"todo",
"todo_is",
...sandboxGlobals,
"browsingContext",
"windowGlobalParent",
];
for (let global of globals) {
helpers.addVarToScope(global, context.getScope(), false);