Bug 1251139 - Support running a function in the parent with loadChromeScript. r=ted
MozReview-Commit-ID: 3t7g2bjaFmA
--- a/testing/mochitest/tests/Harness_sanity/mochitest.ini
+++ b/testing/mochitest/tests/Harness_sanity/mochitest.ini
@@ -27,16 +27,17 @@ skip-if = buildapp != 'mulet'
support-files =
file_app.sjs
file_app.template.webapp
app.html
[test_SpecialPowersPushPrefEnv.html]
[test_SimpletestGetTestFileURL.html]
[test_SpecialPowersLoadChromeScript.html]
support-files = SpecialPowersLoadChromeScript.js
+[test_SpecialPowersLoadChromeScript_function.html]
[test_bug649012.html]
[test_bug816847.html]
skip-if = toolkit == 'android' || e10s #No test app installed
[test_sanity_cleanup.html]
[test_sanity_cleanup2.html]
[test_sanityEventUtils.html]
skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 688052
[test_sanitySimpletest.html]
--- a/testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript.html
+++ b/testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript.html
@@ -1,12 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
- <title>Test for SpecialPowers extension</title>
+ <title>Test for SpecialPowers.loadChromeScript</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
copy from testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript.html
copy to testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript_function.html
--- a/testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript.html
+++ b/testing/mochitest/tests/Harness_sanity/test_SpecialPowersLoadChromeScript_function.html
@@ -1,23 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
- <title>Test for SpecialPowers extension</title>
+ <title>Test for SpecialPowers.loadChromeScript</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
-var url = SimpleTest.getTestFileURL("SpecialPowersLoadChromeScript.js");
-var script = SpecialPowers.loadChromeScript(url);
+
+var script = SpecialPowers.loadChromeScript(function loadChromeScriptTest() {
+ // Copied from SpecialPowersLoadChromeScript.js
+
+ // Just receive 'foo' message and forward it back
+ // as 'bar' message
+ addMessageListener("foo", function (message) {
+ sendAsyncMessage("bar", message);
+ });
+
+ addMessageListener("valid-assert", function (message) {
+ assert.ok(true, "valid assertion");
+ assert.equal(1, 1, "another valid assertion");
+ sendAsyncMessage("valid-assert-done");
+ });
+});
var MESSAGE = { bar: true };
script.addMessageListener("bar", function (message) {
is(JSON.stringify(message), JSON.stringify(MESSAGE),
"received back message from the chrome script");
checkAssert();
});
--- a/testing/specialpowers/content/SpecialPowersObserverAPI.js
+++ b/testing/specialpowers/content/SpecialPowersObserverAPI.js
@@ -419,20 +419,30 @@ SpecialPowersObserverAPI.prototype = {
break;
default:
throw new SpecialPowersError("Invalid operation for SPObserverervice");
}
return undefined; // See comment at the beginning of this function.
}
case "SPLoadChromeScript": {
- let url = aMessage.json.url;
let id = aMessage.json.id;
+ let jsScript;
+ let scriptName;
- let jsScript = this._readUrlAsString(url);
+ if (aMessage.json.url) {
+ jsScript = this._readUrlAsString(aMessage.json.url);
+ scriptName = aMessage.json.url;
+ } else if (aMessage.json.function) {
+ jsScript = aMessage.json.function.body;
+ scriptName = aMessage.json.function.name
+ || "<loadChromeScript anonymous function>";
+ } else {
+ throw new SpecialPowersError("SPLoadChromeScript: Invalid script");
+ }
// Setup a chrome sandbox that has access to sendAsyncMessage
// and addMessageListener in order to communicate with
// the mochitest.
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
let sb = Components.utils.Sandbox(systemPrincipal);
let mm = aMessage.target
.QueryInterface(Ci.nsIFrameLoaderOwner)
@@ -446,38 +456,38 @@ SpecialPowersObserverAPI.prototype = {
this._chromeScriptListeners.push({ id: id, name: name, listener: listener });
};
sb.browserElement = aMessage.target;
// Also expose assertion functions
let reporter = function (err, message, stack) {
// Pipe assertions back to parent process
mm.sendAsyncMessage("SPChromeScriptAssert",
- { id: id, url: url, err: err, message: message,
- stack: stack });
+ { id, name: scriptName, err, message,
+ stack });
};
Object.defineProperty(sb, "assert", {
get: function () {
let scope = Components.utils.createObjectIn(sb);
Services.scriptloader.loadSubScript("chrome://specialpowers/content/Assert.jsm",
scope);
let assert = new scope.Assert(reporter);
delete sb.assert;
return sb.assert = assert;
},
configurable: true
});
// Evaluate the chrome script
try {
- Components.utils.evalInSandbox(jsScript, sb, "1.8", url, 1);
+ Components.utils.evalInSandbox(jsScript, sb, "1.8", scriptName, 1);
} catch(e) {
throw new SpecialPowersError(
- "Error while executing chrome script '" + url + "':\n" +
+ "Error while executing chrome script '" + scriptName + "':\n" +
e + "\n" +
e.fileName + ":" + e.lineNumber);
}
return undefined; // See comment at the beginning of this function.
}
case "SPChromeScriptMessage": {
let id = aMessage.json.id;
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -448,25 +448,34 @@ SpecialPowersAPI.prototype = {
get MockColorPicker() {
return MockColorPicker;
},
get MockPermissionPrompt() {
return MockPermissionPrompt;
},
- loadChromeScript: function (url) {
+ loadChromeScript: function (urlOrFunction) {
// Create a unique id for this chrome script
let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
let id = uuidGenerator.generateUUID().toString();
// Tells chrome code to evaluate this chrome script
+ let scriptArgs = { id };
+ if (typeof(urlOrFunction) == "function") {
+ scriptArgs.function = {
+ body: "(" + urlOrFunction.toString() + ")();",
+ name: urlOrFunction.name,
+ };
+ } else {
+ scriptArgs.url = urlOrFunction;
+ }
this._sendSyncMessage("SPLoadChromeScript",
- { url: url, id: id });
+ scriptArgs);
// Returns a MessageManager like API in order to be
// able to communicate with this chrome script
let listeners = [];
let chromeScript = {
addMessageListener: (name, listener) => {
listeners.push({ name: name, listener: listener });
},
@@ -504,17 +513,17 @@ SpecialPowersAPI.prototype = {
}
}
};
this._addMessageListener("SPChromeScriptMessage", chromeScript);
this._addMessageListener("SPChromeScriptAssert", chromeScript);
let assert = json => {
// An assertion has been done in a mochitest chrome script
- let {url, err, message, stack} = json;
+ let {name, err, message, stack} = json;
// Try to fetch a test runner from the mochitest
// in order to properly log these assertions and notify
// all usefull log observers
let window = this.window.get();
let parentRunner, repr = o => o;
if (window) {
window = window.wrappedJSObject;
@@ -530,20 +539,20 @@ SpecialPowersAPI.prototype = {
message ? message :
("assertion @ " + stack.filename + ":" + stack.lineNumber);
if (err) {
diagnostic +=
" - got " + repr(err.actual) +
", expected " + repr(err.expected) +
" (operator " + err.operator + ")";
}
- var msg = [resultString, url, diagnostic].join(" | ");
+ var msg = [resultString, name, diagnostic].join(" | ");
if (parentRunner) {
if (err) {
- parentRunner.addFailedTest(url);
+ parentRunner.addFailedTest(name);
parentRunner.error(msg);
} else {
parentRunner.log(msg);
}
} else {
// When we are running only a single mochitest, there is no test runner
dump(msg + "\n");
}