diff --git a/testing/mochitest/Makefile.in b/testing/mochitest/Makefile.in
index fd832d89a7c1..e2017013ecc5 100644
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -74,6 +74,8 @@ _SERV_FILES = \
harness.xul \
browser-test-overlay.xul \
browser-test.js \
+ ipc-overlay.xul \
+ ipc.js \
browser-harness.xul \
redirect-a11y.html \
redirect.html \
diff --git a/testing/mochitest/ipc-overlay.xul b/testing/mochitest/ipc-overlay.xul
new file mode 100644
index 000000000000..c3480415b468
--- /dev/null
+++ b/testing/mochitest/ipc-overlay.xul
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/mochitest/ipc.js b/testing/mochitest/ipc.js
new file mode 100644
index 000000000000..0a95b6f43d6a
--- /dev/null
+++ b/testing/mochitest/ipc.js
@@ -0,0 +1,215 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla's layout acceptance tests.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Joel Maher , Mozilla Corporation (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+if (Cc === undefined) {
+ var Cc = Components.classes;
+ var Ci = Components.interfaces;
+}
+
+function ipcEvent(e) {
+ var sync = e.getData("sync");
+ var type = e.getData("type");
+ var data = JSON.parse(e.getData("data"));
+
+ switch(type) {
+ case 'LoggerInit':
+ MozillaFileLogger.init(data.filename);
+ break;
+ case 'Logger':
+ var logger = MozillaFileLogger.getLogCallback();
+ logger({"num":data.num, "level":data.level, "info": Array(data.info)});
+ break;
+ case 'LoggerClose':
+ MozillaFileLogger.close();
+ break;
+ case 'waitForFocus':
+ if (content)
+ var wrapper = content.wrappedJSObject.frames[0].SimpleTest;
+ else
+ var wrapper = SimpleTest;
+ ipctest.waitForFocus(wrapper[data.callback], data.targetWindow, data.expectBlankPage);
+ break;
+ default:
+ if (type == 'QuitApplication') {
+ removeEventListener("contentEvent", function (e) { ipcEvent(e); }, false, true);
+ }
+
+ if (sync == 1) {
+ return sendSyncMessage("chromeEvent", {"type":type, "data":data});
+ } else {
+ sendAsyncMessage("chromeEvent", {"type":type, "data":data});
+ }
+ }
+};
+
+var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
+ .getService(Components.interfaces.nsIXULRuntime);
+
+//check if we are in content process
+if (xulRuntime.processType == 2) {
+ addEventListener("contentEvent", function (e) { ipcEvent(e); }, false, true);
+}
+
+var ipctest = {};
+
+ipctest.waitForFocus_started = false;
+ipctest.waitForFocus_loaded = false;
+ipctest.waitForFocus_focused = false;
+
+ipctest.waitForFocus = function (callback, targetWindow, expectBlankPage) {
+
+ if (targetWindow && targetWindow != undefined) {
+ var tempID = targetWindow;
+ targetWindow = null;
+ var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator);
+ var wm_enum = wm.getXULWindowEnumerator(null);
+
+ while(wm_enum.hasMoreElements()) {
+ var win = wm_enum.getNext().QueryInterface(Ci.nsIXULWindow)
+ .docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow)
+ .content.wrappedJSObject;
+
+ var domutils = win.QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIDOMWindowUtils);
+
+ if (domutils.outerWindowID == tempID) {
+ targetWindow = win;
+ }
+ }
+ }
+
+ if (targetWindow == null || targetWindow == undefined)
+ if (content)
+ targetWindow = content.document.defaultView;
+ else
+ targetWindow = window;
+
+ ipctest.waitForFocus_started = false;
+ expectBlankPage = !!expectBlankPage;
+
+ var fm = Cc["@mozilla.org/focus-manager;1"].
+ getService(Ci.nsIFocusManager);
+
+ var childTargetWindow = { };
+ fm.getFocusedElementForWindow(targetWindow, true, childTargetWindow);
+ childTargetWindow = childTargetWindow.value;
+
+ function debugFocusLog(prefix) {
+ if (content)
+ var wrapper = content.wrappedJSObject.frames[0].SimpleTest;
+ else
+ var wrapper = SimpleTest;
+ wrapper.ok(true, prefix + " -- loaded: " + targetWindow.document.readyState +
+ " active window: " +
+ (fm.activeWindow ? "(" + fm.activeWindow + ") " + fm.activeWindow.location : "") +
+ " focused window: " +
+ (fm.focusedWindow ? "(" + fm.focusedWindow + ") " + fm.focusedWindow.location : "") +
+ " desired window: (" + targetWindow + ") " + targetWindow.location +
+ " child window: (" + childTargetWindow + ") " + childTargetWindow.location);
+ }
+
+ debugFocusLog("before wait for focus");
+
+ function maybeRunTests() {
+ debugFocusLog("maybe run tests ");
+ if (ipctest.waitForFocus_loaded &&
+ ipctest.waitForFocus_focused &&
+ !ipctest.waitForFocus_started) {
+ ipctest.waitForFocus_started = true;
+ if (content)
+ content.setTimeout(function() { callback(); }, 0, targetWindow);
+ else
+ setTimeout(function() { callback(); }, 0, targetWindow);
+ }
+ }
+
+ function waitForEvent(event) {
+ try {
+ debugFocusLog("waitForEvent called ");
+
+ // Check to make sure that this isn't a load event for a blank or
+ // non-blank page that wasn't desired.
+ if (event.type == "load" && (expectBlankPage != (event.target.location == "about:blank")))
+ return;
+
+ ipctest["waitForFocus_" + event.type + "ed"] = true;
+ var win = (event.type == "load") ? targetWindow : childTargetWindow;
+ win.removeEventListener(event.type, waitForEvent, true);
+ maybeRunTests();
+ } catch (e) {
+ }
+ }
+
+ // If the current document is about:blank and we are not expecting a blank
+ // page (or vice versa), and the document has not yet loaded, wait for the
+ // page to load. A common situation is to wait for a newly opened window
+ // to load its content, and we want to skip over any intermediate blank
+ // pages that load. This issue is described in bug 554873.
+ ipctest.waitForFocus_loaded =
+ (expectBlankPage == (targetWindow.location == "about:blank")) &&
+ targetWindow.document.readyState == "complete";
+ if (!ipctest.waitForFocus_loaded) {
+ targetWindow.addEventListener("load", waitForEvent, true);
+ }
+
+ // Check if the desired window is already focused.
+ var focusedChildWindow = { };
+ if (fm.activeWindow) {
+ fm.getFocusedElementForWindow(fm.activeWindow, true, focusedChildWindow);
+ focusedChildWindow = focusedChildWindow.value;
+ }
+
+ // If this is a child frame, ensure that the frame is focused.
+ ipctest.waitForFocus_focused = (focusedChildWindow == childTargetWindow);
+ if (ipctest.waitForFocus_focused) {
+ maybeRunTests();
+ }
+ else {
+ //TODO: is this really the childTargetWindow
+ // and are we really doing something with it here?
+ if (content) {
+ var wr = childTargetWindow.wrappedJSObject;
+ wr.addEventListener("focus", waitForEvent, true);
+ sendAsyncMessage("chromeEvent", {"type":"Focus", "data":{}});
+ wr.focus();
+ } else {
+ childTargetWindow.addEventListener("focus", waitForEvent, true);
+ childTargetWindow.focus();
+ }
+ }
+};
diff --git a/testing/mochitest/runtests.py.in b/testing/mochitest/runtests.py.in
index 7626efb7dd77..0936a40b21f9 100644
--- a/testing/mochitest/runtests.py.in
+++ b/testing/mochitest/runtests.py.in
@@ -167,6 +167,7 @@ class MochitestOptions(optparse.OptionParser):
self.add_option("--a11y",
action = "store_true", dest = "a11y",
help = "run accessibility Mochitests");
+ defaults["a11y"] = False
self.add_option("--setenv",
action = "append", type = "string",
@@ -695,6 +696,11 @@ toolbar#nav-bar {
manifestFile.write("""overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
""")
+ elif ((options.chrome == False) and (options.a11y == False)):
+ #only do the ipc-overlay.xul for mochitest-plain.
+ #Currently there are focus issues in chrome tests and issues with new windows and dialogs when using ipc
+ manifestFile.write("overlay chrome://browser/content/browser.xul chrome://mochikit/content/ipc-overlay.xul")
+
manifestFile.close()
return self.installChromeFile(temp_file, options)
diff --git a/testing/mochitest/tests/SimpleTest/MozillaFileLogger.js b/testing/mochitest/tests/SimpleTest/MozillaFileLogger.js
index 4bc1cff9ceef..76322351ec58 100644
--- a/testing/mochitest/tests/SimpleTest/MozillaFileLogger.js
+++ b/testing/mochitest/tests/SimpleTest/MozillaFileLogger.js
@@ -1,10 +1,17 @@
/**
* MozillaFileLogger, a log listener that can write to a local file.
*/
+
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- const Cc = Components.classes;
- const Ci = Components.interfaces;
+
+ if (Cc === undefined) {
+ var Cc = Components.classes;
+ var Ci = Components.interfaces;
+ }
+} catch (ex) {} //running in ipcMode-chrome
+
+try {
const FOSTREAM_CID = "@mozilla.org/network/file-output-stream;1";
const LF_CID = "@mozilla.org/file/local;1";
@@ -32,15 +39,29 @@ try {
// exists, no action and NULL is returned.
const PR_EXCL = 0x80;
} catch (ex) {
- // probably not running in the test harness
+ // probably not running in the test harness
}
/** Init the file logger with the absolute path to the file.
It will create and append if the file already exists **/
-var MozillaFileLogger = {}
+var MozillaFileLogger = {};
+
+var ipcMode = false;
+try {
+ if (typeof(TestRunner) != undefined)
+ ipcMode = TestRunner.ipcMode;
+} catch(e) { };
MozillaFileLogger.init = function(path) {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (ipcMode) {
+ contentAsyncEvent("LoggerInit", {"filename": path});
+ return;
+ }
+
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ } catch (ex) {} //running in ipcMode-chrome
+
MozillaFileLogger._file = Cc[LF_CID].createInstance(Ci.nsILocalFile);
MozillaFileLogger._file.initWithPath(path);
MozillaFileLogger._foStream = Cc[FOSTREAM_CID].createInstance(Ci.nsIFileOutputStream);
@@ -49,8 +70,17 @@ MozillaFileLogger.init = function(path) {
}
MozillaFileLogger.getLogCallback = function() {
+ if (ipcMode) {
+ return function(msg) {
+ contentAsyncEvent("Logger", {"num": msg.num, "level": msg.level, "info": msg.info.join(' ')});
+ }
+ }
+
return function (msg) {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ } catch(ex) {} //running in ipcMode-chrome
+
var data = msg.num + " " + msg.level + " " + msg.info.join(' ') + "\n";
MozillaFileLogger._foStream.write(data, data.length);
if (data.indexOf("SimpleTest FINISH") >= 0) {
@@ -60,7 +90,15 @@ MozillaFileLogger.getLogCallback = function() {
}
MozillaFileLogger.close = function() {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ if (ipcMode) {
+ contentAsyncEvent("LoggerClose");
+ return;
+ }
+
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ } catch(ex) {} //running in ipcMode-chrome
+
MozillaFileLogger._foStream.close();
MozillaFileLogger._foStream = null;
MozillaFileLogger._file = null;
diff --git a/testing/mochitest/tests/SimpleTest/SimpleTest.js b/testing/mochitest/tests/SimpleTest/SimpleTest.js
index 753a4cf0f58d..8991a211e94d 100644
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -26,6 +26,12 @@ if (typeof(parent) != "undefined" && parent.TestRunner) {
parentRunner = parent.wrappedJSObject.TestRunner;
}
+//Simple test to see if we are running in e10s IPC
+var ipcMode = false;
+if (parentRunner) {
+ ipcMode = parentRunner.ipcMode;
+}
+
// Check to see if the TestRunner is present and has logging
if (parentRunner) {
SimpleTest._logEnabled = parentRunner.logEnabled;
@@ -258,6 +264,17 @@ SimpleTest.waitForFocus = function (callback, targetWindow, expectBlankPage) {
if (!targetWindow)
targetWindow = window;
+ if (ipcMode) {
+ var domutils = targetWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+
+ //TODO: make this support scenarios where we run test standalone and not inside of TestRunner only
+ if (parent && parent.ipcWaitForFocus != undefined) {
+ parent.contentAsyncEvent("waitForFocus", {"callback":callback, "targetWindow":domutils.outerWindowID});
+ }
+ return;
+ }
+
SimpleTest.waitForFocus_started = false;
expectBlankPage = !!expectBlankPage;
@@ -372,6 +389,12 @@ SimpleTest.waitForClipboard_polls = 0;
* within 5s. It can also be called if the known value can't be found.
*/
SimpleTest.waitForClipboard = function(aExpectedVal, aSetupFn, aSuccessFn, aFailureFn) {
+ if (ipcMode) {
+ //TODO: support waitForClipboard via events to chrome
+ dump("E10S_TODO: bug 573735 addresses adding support for this");
+ return;
+ }
+
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var cbSvc = Components.classes["@mozilla.org/widget/clipboard;1"].
diff --git a/testing/mochitest/tests/SimpleTest/TestRunner.js b/testing/mochitest/tests/SimpleTest/TestRunner.js
index 73641f64bf3e..ef27592303e6 100644
--- a/testing/mochitest/tests/SimpleTest/TestRunner.js
+++ b/testing/mochitest/tests/SimpleTest/TestRunner.js
@@ -1,3 +1,30 @@
+/*
+ * e10s event dispatcher from content->chrome
+ *
+ * type = eventName (QuitApplication, LoggerInit, LoggerClose, Logger, GetPref, SetPref)
+ * data = json object {"filename":filename} <- for LoggerInit
+ */
+function contentDispatchEvent(type, data, sync) {
+ if (typeof(data) == "undefined") {
+ data = {};
+ }
+
+ var element = document.createEvent("datacontainerevent");
+ element.initEvent("contentEvent", true, false);
+ element.setData("sync", sync);
+ element.setData("type", type);
+ element.setData("data", JSON.stringify(data));
+ document.dispatchEvent(element);
+}
+
+function contentSyncEvent(type, data) {
+ contentDispatchEvent(type, data, 1);
+}
+
+function contentAsyncEvent(type, data) {
+ contentDispatchEvent(type, data, 0);
+}
+
/**
* TestRunner: A test runner for SimpleTest
* TODO:
@@ -15,6 +42,16 @@ TestRunner._urls = [];
TestRunner.timeout = 5 * 60 * 1000; // 5 minutes.
TestRunner.maxTimeouts = 4; // halt testing after too many timeouts
+TestRunner.ipcMode = false; // running in e10s build and need to use IPC?
+try {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var ipcsanity = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch);
+ ipcsanity.setIntPref("mochitest.ipcmode", 0);
+} catch (e) {
+ TestRunner.ipcMode = true;
+}
+
/**
* Make sure the tests don't hang indefinitely.
**/
@@ -89,6 +126,10 @@ TestRunner._makeIframe = function (url, retry) {
("activeElement" in document && document.activeElement != iframe))) {
// typically calling ourselves from setTimeout is sufficient
// but we'll try focus() just in case that's needed
+
+ if (TestRunner.ipcMode) {
+ contentAsyncEvent("Focus");
+ }
window.focus();
iframe.focus();
if (retry < 3) {
diff --git a/testing/mochitest/tests/SimpleTest/quit.js b/testing/mochitest/tests/SimpleTest/quit.js
index 360ba2df56f8..ebb62ae2b9c4 100644
--- a/testing/mochitest/tests/SimpleTest/quit.js
+++ b/testing/mochitest/tests/SimpleTest/quit.js
@@ -42,6 +42,12 @@
These files did not have a license
*/
+//Simple test to see if we are running in e10s IPC
+var ipcMode = false;
+if (typeof(TestRunner) != "undefined") {
+ ipcMode = TestRunner.ipcMode;
+}
+
function quitHook()
{
var xhr = new XMLHttpRequest();
@@ -83,6 +89,11 @@ function canQuitApplication()
function goQuitApplication()
{
+ if (ipcMode) {
+ contentAsyncEvent("QuitApplication");
+ return;
+ }
+
const privs = 'UniversalXPConnect';
try
@@ -109,7 +120,6 @@ function goQuitApplication()
appService = Components.classes[kAppStartup].
getService(Components.interfaces.nsIAppStartup);
forceQuit = Components.interfaces.nsIAppStartup.eForceQuit;
-
}
else if (kAppShell in Components.classes)
{