Bug 1038620 - Add --nested-oop option to mach test commands - v5. r=ted.mielczarek

This commit is contained in:
Kershaw Chang 2014-12-12 01:30:00 +01:00
parent 6780c59fb4
commit 78d7b20ea0
9 changed files with 152 additions and 6 deletions

View File

@ -15,6 +15,7 @@ mochikit.jar:
content/server.js (server.js)
content/chunkifyTests.js (chunkifyTests.js)
content/manifestLibrary.js (manifestLibrary.js)
content/nested_setup.js (nested_setup.js)
content/dynamic/getMyDirectory.sjs (dynamic/getMyDirectory.sjs)
content/static/harness.css (static/harness.css)
content/tests/SimpleTest/ChromePowers.js (tests/SimpleTest/ChromePowers.js)

View File

@ -191,7 +191,7 @@ class MochitestRunner(MozbuildObject):
rerun_failures=False, no_autorun=False, repeat=0, run_until_failure=False,
slow=False, chunk_by_dir=0, total_chunks=None, this_chunk=None, extraPrefs=[],
jsdebugger=False, debug_on_failure=False, start_at=None, end_at=None,
e10s=False, strict_content_sandbox=False, dmd=False, dump_output_directory=None,
e10s=False, strict_content_sandbox=False, nested_oop=False, dmd=False, dump_output_directory=None,
dump_about_memory_after_test=False, dump_dmd_after_test=False,
install_extension=None, quiet=False, environment=[], app_override=None, bisectChunk=None, runByDir=False,
useTestMediaDevices=False, timeout=None, **kwargs):
@ -314,6 +314,7 @@ class MochitestRunner(MozbuildObject):
options.endAt = end_at
options.e10s = e10s
options.strictContentSandbox = strict_content_sandbox
options.nested_oop = nested_oop
options.dumpAboutMemoryAfterTest = dump_about_memory_after_test
options.dumpDMDAfterTest = dump_dmd_after_test
options.dumpOutputDirectory = dump_output_directory
@ -508,6 +509,10 @@ def MochitestCommand(func):
help='Run tests with a more strict content sandbox (Windows only).')
func = strict_content_sandbox(func)
this_chunk = CommandArgument('--nested-oop', action='store_true',
help='Run tests with nested oop preferences and test filtering enabled.')
func = this_chunk(func)
dmd = CommandArgument('--dmd', action='store_true',
help='Run tests with DMD active.')
func = dmd(func)

View File

@ -369,6 +369,12 @@ class MochitestOptions(optparse.OptionParser):
"dest": "strictContentSandbox",
"help": "Run tests with a more strict content sandbox (Windows only).",
}],
[["--nested-oop"],
{ "action": "store_true",
"default": False,
"dest": "nested_oop",
"help": "Run tests with nested-oop preferences and test filtering enabled.",
}],
[["--dmd-path"],
{ "action": "store",
"default": None,
@ -481,6 +487,7 @@ class MochitestOptions(optparse.OptionParser):
mozinfo.update({"e10s": options.e10s}) # for test manifest parsing.
mozinfo.update({"strictContentSandbox": options.strictContentSandbox}) # for test manifest parsing.
mozinfo.update({"nested_oop": options.nested_oop}) # for test manifest parsing.
if options.app is None:
if build_obj is not None:

View File

@ -61,6 +61,7 @@ TEST_HARNESS_FILES.testing.mochitest += [
'manifest.webapp',
'manifestLibrary.js',
'mochitest_options.py',
'nested_setup.js',
'pywebsocket_wrapper.py',
'redirect.html',
'runtests.py',

View File

@ -0,0 +1,30 @@
var gTestURL = '';
function addPermissions()
{
SpecialPowers.pushPermissions(
[{ type: "browser", allow: true, context: document }],
addPreferences);
}
function addPreferences()
{
SpecialPowers.pushPrefEnv(
{"set": [["dom.mozBrowserFramesEnabled", true]]},
insertFrame);
}
function insertFrame()
{
var iframe = document.createElement('iframe');
iframe.id = 'nested-parent-frame';
iframe.width = "100%";
iframe.height = "100%";
iframe.scoring = "no";
iframe.setAttribute("remote", "true");
iframe.setAttribute("mozbrowser", "true");
iframe.src = gTestURL;
document.getElementById("holder-div").appendChild(iframe);
}

View File

@ -421,6 +421,7 @@ class MochitestUtilsMixin(object):
# Path to the test script on the server
TEST_PATH = "tests"
NESTED_OOP_TEST_PATH = "nested_oop"
CHROME_PATH = "redirect.html"
urlOpts = []
log = None
@ -652,6 +653,8 @@ class MochitestUtilsMixin(object):
testURL = "/".join([testHost, self.CHROME_PATH])
elif options.browserChrome or options.jetpackPackage or options.jetpackAddon:
testURL = "about:blank"
if options.nested_oop:
testURL = "/".join([testHost, self.NESTED_OOP_TEST_PATH])
return testURL
def buildTestPath(self, options, testsToFilter=None, disabled=True):
@ -1161,6 +1164,7 @@ class Mochitest(MochitestUtilsMixin):
options.extraPrefs.append("browser.tabs.remote.autostart=%s" % ('true' if options.e10s else 'false'))
if options.strictContentSandbox:
options.extraPrefs.append("security.sandbox.windows.content.moreStrict=true")
options.extraPrefs.append("dom.ipc.tabs.nested.enabled=%s" % ('true' if options.nested_oop else 'false'))
# get extensions to install
extensions = self.getExtensionsToInstall(options)

View File

@ -210,6 +210,7 @@ function createMochitestServer(serverBasePath)
server.registerDirectory("/", serverBasePath);
server.registerPathHandler("/server/shutdown", serverShutdown);
server.registerPathHandler("/server/debug", serverDebug);
server.registerPathHandler("/nested_oop", nestedTest);
server.registerContentType("sjs", "sjs"); // .sjs == CGI-like functionality
server.registerContentType("jar", "application/x-jar");
server.registerContentType("ogg", "application/ogg");
@ -598,6 +599,31 @@ function convertManifestToTestLinks(root, manifest)
paths.length];
}
/**
* Produce a test harness page that has one remote iframe
*/
function nestedTest(metadata, response)
{
response.setStatusLine("1.1", 200, "OK");
response.setHeader("Content-type", "text/html;charset=utf-8", false);
response.write(
HTML(
HEAD(
TITLE("Mochitest | ", metadata.path),
LINK({rel: "stylesheet",
type: "text/css", href: "/static/harness.css"}),
SCRIPT({type: "text/javascript",
src: "/nested_setup.js"}),
SCRIPT({type: "text/javascript"},
"window.onload = addPermissions; gTestURL = '/tests?" + metadata.queryString + "';")
),
BODY(
DIV({class: "container"},
DIV({class: "frameholder", id: "holder-div"})
)
)));
}
/**
* Produce a test harness page containing all the test cases
* below it, recursively.

View File

@ -5,6 +5,31 @@
* order to be used as a replacement for UniversalXPConnect
*/
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;
const CHILD_SCRIPT = "chrome://specialpowers/content/specialpowers.js";
const CHILD_SCRIPT_API = "chrome://specialpowers/content/specialpowersAPI.js";
const CHILD_LOGGER_SCRIPT = "chrome://specialpowers/content/MozillaLogger.js";
// All messages sent to observer should be listed here.
const SP_SYNC_MESSAGES = ["SPChromeScriptMessage",
"SPLoadChromeScript",
"SPObserverService",
"SPPermissionManager",
"SPPrefService",
"SPProcessCrashService",
"SPSetTestPluginEnabledState",
"SPWebAppService"];
const SP_ASYNC_MESSAGES = ["SpecialPowers.Focus",
"SpecialPowers.Quit",
"SPPingService",
"SPQuotaManager"];
function SpecialPowers(window) {
this.window = Components.utils.getWeakReference(window);
this._windowID = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
@ -23,6 +48,8 @@ function SpecialPowers(window) {
}});
this._pongHandlers = [];
this._messageListener = this._messageReceived.bind(this);
this._nestedFrameInjected = false;
this._grandChildFrameMM = null;
addMessageListener("SPPingService", this._messageListener);
let (self = this) {
Services.obs.addObserver(function onInnerWindowDestroyed(subject, topic, data) {
@ -37,6 +64,40 @@ function SpecialPowers(window) {
}
}
}, "inner-window-destroyed", false);
Services.obs.addObserver(function onRemoteBrowserShown(subject, topic, data) {
let frameLoader = subject;
// get a ref to the app <iframe>
frameLoader.QueryInterface(Ci.nsIFrameLoader);
let frame = frameLoader.ownerElement;
let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
var frameId = frame.getAttribute('id');
if (frameId === "nested-parent-frame" && !self._nestedFrameInjected) {
Services.obs.removeObserver(onRemoteBrowserShown, "remote-browser-shown");
self._grandChildFrameMM = mm;
mm.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
mm.loadFrameScript(CHILD_SCRIPT_API, true);
mm.loadFrameScript(CHILD_SCRIPT, true);
SP_SYNC_MESSAGES.forEach(function (msgname) {
mm.addMessageListener(msgname, function (msg) {
return self._sendSyncMessage(msgname, msg.data)[0];
});
});
SP_ASYNC_MESSAGES.forEach(function (msgname) {
mm.addMessageListener(msgname, function (msg) {
self._sendAsyncMessage(msgname, msg.data);
});
});
mm.addMessageListener("SPPAddNestedMessageListener", function(msg) {
self._addMessageListener(msg.json.name, function(aMsg) {
mm.sendAsyncMessage(aMsg.name, aMsg.data);
});
});
self._nestedFrameInjected = true;
}
}, "remote-browser-shown", false);
}
}
@ -50,15 +111,22 @@ SpecialPowers.prototype.DOMWindowUtils = undefined;
SpecialPowers.prototype.Components = undefined;
SpecialPowers.prototype._sendSyncMessage = function(msgname, msg) {
if (SP_SYNC_MESSAGES.indexOf(msgname) == -1) {
throw new Error("Unexpected SP message: " + msgname);
}
return sendSyncMessage(msgname, msg);
};
SpecialPowers.prototype._sendAsyncMessage = function(msgname, msg) {
if (SP_ASYNC_MESSAGES.indexOf(msgname) == -1) {
throw new Error("Unexpected SP message: " + msgname);
}
sendAsyncMessage(msgname, msg);
};
SpecialPowers.prototype._addMessageListener = function(msgname, listener) {
addMessageListener(msgname, listener);
sendAsyncMessage("SPPAddNestedMessageListener", { name: msgname });
};
SpecialPowers.prototype._removeMessageListener = function(msgname, listener) {
@ -91,6 +159,9 @@ SpecialPowers.prototype._messageReceived = function(aMessage) {
if (handler) {
handler();
}
if (this._grandChildFrameMM) {
this._grandChildFrameMM.sendAsyncMessage("SPPingService", { op: "pong" });
}
}
break;
}

View File

@ -213,8 +213,9 @@ function unwrapPrivileged(x) {
if (!isWrapper(x))
throw "Trying to unwrap a non-wrapped object!";
// Unwrap.
return x.SpecialPowers_wrappedObject;
var obj = x.SpecialPowers_wrappedObject;
// unwrapped.
return obj;
};
function crawlProtoChain(obj, fn) {
@ -662,10 +663,10 @@ SpecialPowersAPI.prototype = {
* we don't SpecialPowers-wrap Components.interfaces, because it's available
* to untrusted content, and wrapping it confuses QI and identity checks.
*/
get Cc() { return wrapPrivileged(this.getFullComponents()).classes; },
get Cc() { return wrapPrivileged(this.getFullComponents().classes); },
get Ci() { return this.Components.interfaces; },
get Cu() { return wrapPrivileged(this.getFullComponents()).utils; },
get Cr() { return wrapPrivileged(this.Components).results; },
get Cu() { return wrapPrivileged(this.getFullComponents().utils); },
get Cr() { return wrapPrivileged(this.Components.results); },
/*
* SpecialPowers.getRawComponents() allows content to get a reference to a