summaryrefslogtreecommitdiffstats
path: root/dom/tests/browser
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/browser')
-rw-r--r--dom/tests/browser/browser.ini46
-rw-r--r--dom/tests/browser/browser_ConsoleAPITests.js522
-rw-r--r--dom/tests/browser/browser_ConsoleAPI_originAttributes.js80
-rw-r--r--dom/tests/browser/browser_ConsoleStorageAPITests.js98
-rw-r--r--dom/tests/browser/browser_ConsoleStoragePBTest_perwindowpb.js89
-rw-r--r--dom/tests/browser/browser_allocateGigabyte.js43
-rw-r--r--dom/tests/browser/browser_autofocus_background.js37
-rw-r--r--dom/tests/browser/browser_autofocus_preference.js18
-rw-r--r--dom/tests/browser/browser_beforeunload_between_chrome_content.js144
-rw-r--r--dom/tests/browser/browser_bug1004814.js36
-rw-r--r--dom/tests/browser/browser_bug1008941_dismissGeolocationHanger.js28
-rw-r--r--dom/tests/browser/browser_bug1238427.js31
-rw-r--r--dom/tests/browser/browser_bug396843.js287
-rw-r--r--dom/tests/browser/browser_focus_steal_from_chrome.js151
-rw-r--r--dom/tests/browser/browser_focus_steal_from_chrome_during_mousedown.js45
-rw-r--r--dom/tests/browser/browser_frame_elements.html15
-rw-r--r--dom/tests/browser/browser_frame_elements.js89
-rw-r--r--dom/tests/browser/browser_largeAllocation.js214
-rw-r--r--dom/tests/browser/browser_localStorage_privatestorageevent.js76
-rw-r--r--dom/tests/browser/browser_test__content.js4
-rw-r--r--dom/tests/browser/browser_test_new_window_from_content.js202
-rw-r--r--dom/tests/browser/browser_test_toolbars_visibility.js224
-rw-r--r--dom/tests/browser/browser_xhr_sandbox.js50
-rw-r--r--dom/tests/browser/dummy.html9
-rw-r--r--dom/tests/browser/geo_leak_test.html17
-rw-r--r--dom/tests/browser/page_privatestorageevent.html5
-rw-r--r--dom/tests/browser/position.html29
-rw-r--r--dom/tests/browser/test-console-api.html75
-rw-r--r--dom/tests/browser/test_bug1004814.html14
-rw-r--r--dom/tests/browser/test_largeAllocation.html4
-rw-r--r--dom/tests/browser/test_largeAllocation.html^headers^1
-rw-r--r--dom/tests/browser/test_new_window_from_content_child.html25
-rw-r--r--dom/tests/browser/worker_bug1004814.js6
33 files changed, 2714 insertions, 0 deletions
diff --git a/dom/tests/browser/browser.ini b/dom/tests/browser/browser.ini
new file mode 100644
index 000000000..35ebd56c6
--- /dev/null
+++ b/dom/tests/browser/browser.ini
@@ -0,0 +1,46 @@
+[DEFAULT]
+support-files =
+ browser_frame_elements.html
+ page_privatestorageevent.html
+ position.html
+ test-console-api.html
+ test_bug1004814.html
+ worker_bug1004814.js
+ geo_leak_test.html
+ dummy.html
+ test_largeAllocation.html
+ test_largeAllocation.html^headers^
+ !/dom/tests/mochitest/geolocation/network_geolocation.sjs
+
+[browser_allocateGigabyte.js]
+disabled = Does not reliably pass on 32-bit systems - bug 1314098
+skip-if = !e10s
+[browser_autofocus_background.js]
+[browser_autofocus_preference.js]
+[browser_beforeunload_between_chrome_content.js]
+skip-if = !e10s
+[browser_bug396843.js]
+[browser_bug1004814.js]
+[browser_bug1008941_dismissGeolocationHanger.js]
+[browser_bug1238427.js]
+[browser_ConsoleAPI_originAttributes.js]
+[browser_ConsoleAPITests.js]
+skip-if = e10s
+[browser_ConsoleStorageAPITests.js]
+[browser_ConsoleStoragePBTest_perwindowpb.js]
+[browser_focus_steal_from_chrome.js]
+[browser_focus_steal_from_chrome_during_mousedown.js]
+[browser_frame_elements.js]
+[browser_largeAllocation.js]
+skip-if = !e10s # Large-Allocation requires e10s
+[browser_localStorage_privatestorageevent.js]
+[browser_test__content.js]
+[browser_test_new_window_from_content.js]
+tags = openwindow
+skip-if = toolkit == 'android' || (os == "linux" && debug) # see bug 1261495 for Linux debug time outs
+support-files =
+ test_new_window_from_content_child.html
+[browser_test_toolbars_visibility.js]
+support-files =
+ test_new_window_from_content_child.html
+[browser_xhr_sandbox.js]
diff --git a/dom/tests/browser/browser_ConsoleAPITests.js b/dom/tests/browser/browser_ConsoleAPITests.js
new file mode 100644
index 000000000..53615cde8
--- /dev/null
+++ b/dom/tests/browser/browser_ConsoleAPITests.js
@@ -0,0 +1,522 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/dom/tests/browser/test-console-api.html";
+
+add_task(function*() {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URI);
+ registerCleanupFunction(() => gBrowser.removeTab(tab));
+ let browser = gBrowser.selectedBrowser;
+
+ yield* consoleAPISanityTest(browser);
+ yield* observeConsoleTest(browser);
+ yield* startTraceTest(browser);
+ yield* startLocationTest(browser);
+ yield* startNativeCallbackTest(browser);
+ yield* startGroupTest(browser);
+ yield* startTimeTest(browser);
+ yield* startTimeEndTest(browser);
+ yield* startTimeStampTest(browser);
+ yield* startEmptyTimeStampTest(browser);
+ yield* startEmptyTimerTest(browser);
+});
+
+function spawnWithObserver(browser, observerFunc, func) {
+ // Build the observer generating function.
+ let source = [
+ "const TEST_URI = 'http://example.com/browser/dom/tests/browser/test-console-api.html';",
+ // Create a promise to be resolved when the text is complete. It is stored
+ // on content, such that it can be waited on by calling waitForResolve. This
+ // is done rather than returning it from this function such that the
+ // initialization can be yeilded on before yeilding on the conclusion of the
+ // test.
+ "content._promise = new Promise(_resolve => {",
+ // These are variables which are used by the test runner to communicate
+ // state to the observer.
+ " let gLevel, gArgs, gStyle;",
+ " let expect = function(level) {",
+ " gLevel = level;",
+ " gArgs = Array.slice(arguments, 1);",
+ " }",
+ // To ease the transition to the new format, content.window is avaliable as gWindow
+ // in the content.
+ " let gWindow = content.window;",
+ // This method is called rather than _resolve such that the observer is removed
+ // before exiting the test
+ " let resolve = () => {",
+ " Services.obs.removeObserver(ConsoleObserver, 'console-api-log-event');",
+ " _resolve();",
+ " };",
+ // This is the observer itself, it calls the passed-in function whenever
+ // it encounters an event
+ " let ConsoleObserver = {",
+ " QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),",
+ " observe: function(aSubject, aTopic, aData) {",
+ " try {",
+ " (" + observerFunc.toString() + ")(aSubject.wrappedJSObject);",
+ " } catch (ex) {",
+ " ok(false, 'Exception thrown in observe: ' + ex);",
+ " }",
+ " }",
+ " };",
+ " Services.obs.addObserver(ConsoleObserver, 'console-api-log-event', false);",
+ // Call the initialization function (if present)
+ func ? ("(" + func.toString() + ")();") : "",
+ "});",
+ ].join('\n');
+
+ return ContentTask.spawn(browser, null, new Function(source));
+}
+
+function waitForResolve(browser) {
+ return ContentTask.spawn(browser, null, function() {
+ return content._promise;
+ });
+}
+
+function* consoleAPISanityTest(browser) {
+ yield ContentTask.spawn(browser, null, function() {
+ let win = XPCNativeWrapper.unwrap(content.window);
+
+ ok(win.console, "we have a console attached");
+ ok(win.console, "we have a console attached, 2nd attempt");
+
+ ok(win.console.log, "console.log is here");
+ ok(win.console.info, "console.info is here");
+ ok(win.console.warn, "console.warn is here");
+ ok(win.console.error, "console.error is here");
+ ok(win.console.exception, "console.exception is here");
+ ok(win.console.trace, "console.trace is here");
+ ok(win.console.dir, "console.dir is here");
+ ok(win.console.group, "console.group is here");
+ ok(win.console.groupCollapsed, "console.groupCollapsed is here");
+ ok(win.console.groupEnd, "console.groupEnd is here");
+ ok(win.console.time, "console.time is here");
+ ok(win.console.timeEnd, "console.timeEnd is here");
+ ok(win.console.timeStamp, "console.timeStamp is here");
+ ok(win.console.assert, "console.assert is here");
+ ok(win.console.count, "console.count is here");
+ });
+}
+
+function testConsoleData(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+ ok(aMessageObject.arguments, "we have arguments");
+
+ switch (gLevel) {
+ case "trace": {
+ is(aMessageObject.arguments.length, 0, "arguments.length matches");
+ is(aMessageObject.stacktrace.toSource(), gArgs.toSource(),
+ "stack trace is correct");
+ break;
+ }
+ case "count": {
+ is(aMessageObject.counter.label, gArgs[0].label, "label matches");
+ is(aMessageObject.counter.count, gArgs[0].count, "count matches");
+ break;
+ }
+ default: {
+ is(aMessageObject.arguments.length, gArgs.length, "arguments.length matches");
+ gArgs.forEach(function (a, i) {
+ // Waive Xray so that we don't get messed up by Xray ToString.
+ //
+ // It'd be nice to just use XPCNativeWrapper.unwrap here, but there are
+ // a number of dumb reasons we can't. See bug 868675.
+ var arg = aMessageObject.arguments[i];
+ if (Components.utils.isXrayWrapper(arg))
+ arg = arg.wrappedJSObject;
+ is(arg, a, "correct arg " + i);
+ });
+
+ if (gStyle) {
+ is(aMessageObject.styles.length, gStyle.length, "styles.length matches");
+ is(aMessageObject.styles + "", gStyle + "", "styles match");
+ } else {
+ ok(!aMessageObject.styles || aMessageObject.styles.length === 0,
+ "styles match");
+ }
+ }
+ }
+}
+
+function* observeConsoleTest(browser) {
+ yield spawnWithObserver(browser, testConsoleData, function(opts) {
+ let win = XPCNativeWrapper.unwrap(content.window);
+ expect("log", "arg");
+ win.console.log("arg");
+
+ expect("info", "arg", "extra arg");
+ win.console.info("arg", "extra arg");
+
+ expect("warn", "Lesson 1: PI is approximately equal to 3");
+ win.console.warn("Lesson %d: %s is approximately equal to %1.0f",
+ 1,
+ "PI",
+ 3.14159);
+
+ expect("warn", "Lesson 1: PI is approximately equal to 3.14");
+ win.console.warn("Lesson %d: %s is approximately equal to %1.2f",
+ 1,
+ "PI",
+ 3.14159);
+
+ expect("warn", "Lesson 1: PI is approximately equal to 3.141590");
+ win.console.warn("Lesson %d: %s is approximately equal to %f",
+ 1,
+ "PI",
+ 3.14159);
+
+ expect("warn", "Lesson 1: PI is approximately equal to 3.1415900");
+ win.console.warn("Lesson %d: %s is approximately equal to %0.7f",
+ 1,
+ "PI",
+ 3.14159);
+
+ expect("log", "%d, %s, %l");
+ win.console.log("%d, %s, %l");
+
+ expect("log", "%a %b %g");
+ win.console.log("%a %b %g");
+
+ expect("log", "%a %b %g", "a", "b");
+ win.console.log("%a %b %g", "a", "b");
+
+ expect("log", "2, a, %l", 3);
+ win.console.log("%d, %s, %l", 2, "a", 3);
+
+ // Bug #692550 handle null and undefined.
+ expect("log", "null, undefined");
+ win.console.log("%s, %s", null, undefined);
+
+ // Bug #696288 handle object as first argument.
+ let obj = { a: 1 };
+ expect("log", obj, "a");
+ win.console.log(obj, "a");
+
+ expect("dir", win.toString());
+ win.console.dir(win);
+
+ expect("error", "arg");
+ win.console.error("arg");
+
+ expect("exception", "arg");
+ win.console.exception("arg");
+
+ expect("log", "foobar");
+ gStyle = ["color:red;foobar;;"];
+ win.console.log("%cfoobar", gStyle[0]);
+
+ let obj4 = { d: 4 };
+ expect("warn", "foobar", obj4, "test", "bazbazstr", "last");
+ gStyle = [null, null, null, "color:blue;", "color:red"];
+ win.console.warn("foobar%Otest%cbazbaz%s%clast", obj4, gStyle[3], "str", gStyle[4]);
+
+ let obj3 = { c: 3 };
+ expect("info", "foobar", "bazbaz", obj3, "%comg", "color:yellow");
+ gStyle = [null, "color:pink;"];
+ win.console.info("foobar%cbazbaz", gStyle[1], obj3, "%comg", "color:yellow");
+
+ gStyle = null;
+ let obj2 = { b: 2 };
+ expect("log", "omg ", obj, " foo ", 4, obj2);
+ win.console.log("omg %o foo %o", obj, 4, obj2);
+
+ expect("assert", "message");
+ win.console.assert(false, "message");
+
+ expect("count", { label: "label a", count: 1 });
+ win.console.count("label a");
+
+ expect("count", { label: "label b", count: 1 });
+ win.console.count("label b");
+
+ expect("count", { label: "label a", count: 2 });
+ win.console.count("label a");
+
+ expect("count", { label: "label b", count: 2 });
+ win.console.count("label b");
+ dump("Resolving\n");
+ resolve();
+ });
+ dump("There\n");
+}
+
+function testTraceConsoleData(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+ ok(aMessageObject.arguments, "we have arguments");
+
+ is(gLevel, "trace", "gLevel should be trace");
+ is(aMessageObject.arguments.length, 0, "arguments.length matches");
+ dump(aMessageObject.stacktrace.toSource() + "\n" + gArgs.toSource() + "\n");
+ is(aMessageObject.stacktrace.toSource(), gArgs.toSource(),
+ "stack trace is correct");
+ resolve();
+}
+
+function* startTraceTest(browser) {
+ dump("HERE\n");
+ yield spawnWithObserver(browser, testTraceConsoleData, function(opts) {
+ dump("Observer attached\n");
+ gLevel = "trace";
+ gArgs = [
+ {columnNumber: 9, filename: TEST_URI, functionName: "window.foobar585956c", language: 2, lineNumber: 6},
+ {columnNumber: 16, filename: TEST_URI, functionName: "foobar585956b", language: 2, lineNumber: 11},
+ {columnNumber: 16, filename: TEST_URI, functionName: "foobar585956a", language: 2, lineNumber: 15},
+ {columnNumber: 1, filename: TEST_URI, functionName: "onclick", language: 2, lineNumber: 1}
+ ];
+
+ });
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-trace", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testLocationData(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+ ok(aMessageObject.arguments, "we have arguments");
+
+ is(aMessageObject.filename, gArgs[0].filename, "filename matches");
+ is(aMessageObject.lineNumber, gArgs[0].lineNumber, "lineNumber matches");
+ is(aMessageObject.functionName, gArgs[0].functionName, "functionName matches");
+ is(aMessageObject.arguments.length, gArgs[0].arguments.length, "arguments.length matches");
+ gArgs[0].arguments.forEach(function (a, i) {
+ is(aMessageObject.arguments[i], a, "correct arg " + i);
+ });
+
+ resolve();
+}
+
+function* startLocationTest(browser) {
+ yield spawnWithObserver(browser, testLocationData, function(opts) {
+ gLevel = "log";
+ gArgs = [
+ {filename: TEST_URI, functionName: "foobar646025", arguments: ["omg", "o", "d"], lineNumber: 19}
+ ];
+ });
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-location", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testNativeCallback(aMessageObject) {
+ is(aMessageObject.level, "log", "expected level received");
+ is(aMessageObject.filename, "", "filename matches");
+ is(aMessageObject.lineNumber, 0, "lineNumber matches");
+ is(aMessageObject.functionName, "", "functionName matches");
+
+ resolve();
+}
+
+function* startNativeCallbackTest(browser) {
+ yield spawnWithObserver(browser, testNativeCallback);
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-nativeCallback", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testConsoleGroup(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ ok(aMessageObject.level == "group" ||
+ aMessageObject.level == "groupCollapsed" ||
+ aMessageObject.level == "groupEnd",
+ "expected level received");
+
+ is(aMessageObject.functionName, "testGroups", "functionName matches");
+ ok(aMessageObject.lineNumber >= 46 && aMessageObject.lineNumber <= 50,
+ "lineNumber matches");
+ if (aMessageObject.level == "groupCollapsed") {
+ is(aMessageObject.groupName, "a group", "groupCollapsed groupName matches");
+ is(aMessageObject.arguments[0], "a", "groupCollapsed arguments[0] matches");
+ is(aMessageObject.arguments[1], "group", "groupCollapsed arguments[0] matches");
+ }
+ else if (aMessageObject.level == "group") {
+ is(aMessageObject.groupName, "b group", "group groupName matches");
+ is(aMessageObject.arguments[0], "b", "group arguments[0] matches");
+ is(aMessageObject.arguments[1], "group", "group arguments[1] matches");
+ }
+ else if (aMessageObject.level == "groupEnd") {
+ let groupName = Array.prototype.join.call(aMessageObject.arguments, " ");
+ is(groupName,"b group", "groupEnd arguments matches");
+ is(aMessageObject.groupName, "b group", "groupEnd groupName matches");
+ }
+
+ if (aMessageObject.level == "groupEnd") {
+ resolve();
+ }
+}
+
+function* startGroupTest(browser) {
+ yield spawnWithObserver(browser, testConsoleGroup);
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-groups", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testConsoleTime(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+
+ is(aMessageObject.filename, gArgs[0].filename, "filename matches");
+ is(aMessageObject.lineNumber, gArgs[0].lineNumber, "lineNumber matches");
+ is(aMessageObject.functionName, gArgs[0].functionName, "functionName matches");
+ is(aMessageObject.timer.name, gArgs[0].timer.name, "timer.name matches");
+ ok(aMessageObject.timer.started, "timer.started exists");
+
+ gArgs[0].arguments.forEach(function (a, i) {
+ is(aMessageObject.arguments[i], a, "correct arg " + i);
+ });
+
+ resolve();
+}
+
+function* startTimeTest(browser) {
+ yield spawnWithObserver(browser, testConsoleTime, function(opts) {
+ gLevel = "time";
+ gArgs = [
+ {filename: TEST_URI, lineNumber: 23, functionName: "startTimer",
+ arguments: ["foo"],
+ timer: { name: "foo" },
+ }
+ ];
+ });
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-time", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testConsoleTimeEnd(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+ ok(aMessageObject.arguments, "we have arguments");
+
+ is(aMessageObject.filename, gArgs[0].filename, "filename matches");
+ is(aMessageObject.lineNumber, gArgs[0].lineNumber, "lineNumber matches");
+ is(aMessageObject.functionName, gArgs[0].functionName, "functionName matches");
+ is(aMessageObject.arguments.length, gArgs[0].arguments.length, "arguments.length matches");
+ is(aMessageObject.timer.name, gArgs[0].timer.name, "timer name matches");
+ is(typeof aMessageObject.timer.duration, "number", "timer duration is a number");
+ info("timer duration: " + aMessageObject.timer.duration);
+ ok(aMessageObject.timer.duration >= 0, "timer duration is positive");
+
+ gArgs[0].arguments.forEach(function (a, i) {
+ is(aMessageObject.arguments[i], a, "correct arg " + i);
+ });
+
+ resolve();
+}
+
+function* startTimeEndTest(browser) {
+ yield spawnWithObserver(browser, testConsoleTimeEnd, function(opts) {
+ gLevel = "timeEnd";
+ gArgs = [
+ {filename: TEST_URI, lineNumber: 27, functionName: "stopTimer",
+ arguments: ["foo"],
+ timer: { name: "foo" },
+ },
+ ];
+ });
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-timeEnd", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testConsoleTimeStamp(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+
+ is(aMessageObject.filename, gArgs[0].filename, "filename matches");
+ is(aMessageObject.lineNumber, gArgs[0].lineNumber, "lineNumber matches");
+ is(aMessageObject.functionName, gArgs[0].functionName, "functionName matches");
+ ok(aMessageObject.timeStamp > 0, "timeStamp is a positive value");
+
+ gArgs[0].arguments.forEach(function (a, i) {
+ is(aMessageObject.arguments[i], a, "correct arg " + i);
+ });
+
+ resolve();
+}
+
+function* startTimeStampTest(browser) {
+ yield spawnWithObserver(browser, testConsoleTimeStamp, function() {
+ gLevel = "timeStamp";
+ gArgs = [
+ {filename: TEST_URI, lineNumber: 58, functionName: "timeStamp",
+ arguments: ["!!!"]
+ }
+ ];
+ });
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-timeStamp", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testEmptyConsoleTimeStamp(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ is(aMessageObject.level, gLevel, "expected level received");
+
+ is(aMessageObject.filename, gArgs[0].filename, "filename matches");
+ is(aMessageObject.lineNumber, gArgs[0].lineNumber, "lineNumber matches");
+ is(aMessageObject.functionName, gArgs[0].functionName, "functionName matches");
+ ok(aMessageObject.timeStamp > 0, "timeStamp is a positive value");
+ is(aMessageObject.arguments.length, 0, "we don't have arguments");
+
+ resolve();
+}
+
+function* startEmptyTimeStampTest(browser) {
+ yield spawnWithObserver(browser, testEmptyConsoleTimeStamp, function() {
+ gLevel = "timeStamp";
+ gArgs = [
+ {filename: TEST_URI, lineNumber: 58, functionName: "timeStamp",
+ arguments: []
+ }
+ ];
+ });
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-emptyTimeStamp", {}, browser);
+ yield waitForResolve(browser);
+}
+
+function testEmptyTimer(aMessageObject) {
+ let messageWindow = Services.wm.getOuterWindowWithId(aMessageObject.ID);
+ is(messageWindow, gWindow, "found correct window by window ID");
+
+ ok(aMessageObject.level == "time" || aMessageObject.level == "timeEnd",
+ "expected level received");
+ is(aMessageObject.arguments.length, 0, "we don't have arguments");
+ ok(!aMessageObject.timer, "we don't have a timer");
+
+ is(aMessageObject.functionName, "namelessTimer", "functionName matches");
+ ok(aMessageObject.lineNumber == 31 || aMessageObject.lineNumber == 32,
+ "lineNumber matches");
+
+ resolve();
+}
+
+function* startEmptyTimerTest(browser) {
+ yield spawnWithObserver(browser, testEmptyTimer);
+
+ BrowserTestUtils.synthesizeMouseAtCenter("#test-namelessTimer", {}, browser);
+ yield waitForResolve(browser);
+}
diff --git a/dom/tests/browser/browser_ConsoleAPI_originAttributes.js b/dom/tests/browser/browser_ConsoleAPI_originAttributes.js
new file mode 100644
index 000000000..e24640bbd
--- /dev/null
+++ b/dom/tests/browser/browser_ConsoleAPI_originAttributes.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
+ .getService(Ci.nsIConsoleAPIStorage);
+
+const FAKE_ADDON_ID = "test-webext-addon@mozilla.org";
+const EXPECTED_CONSOLE_ID = `addon/${FAKE_ADDON_ID}`;
+const EXPECTED_CONSOLE_MESSAGE_CONTENT = "fake-webext-addon-test-log-message";
+const ConsoleObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ init() {
+ Services.obs.addObserver(this, "console-api-log-event", false);
+ },
+
+ uninit() {
+ Services.obs.removeObserver(this, "console-api-log-event", false);
+ },
+
+ observe(aSubject, aTopic, aData) {
+ if (aTopic == "console-api-log-event") {
+ let consoleAPIMessage = aSubject.wrappedJSObject;
+
+ is(consoleAPIMessage.arguments[0], EXPECTED_CONSOLE_MESSAGE_CONTENT,
+ "the consoleAPIMessage contains the expected message");
+
+ ok(consoleAPIMessage.originAttributes, "the consoleAPImessage contains originattributes");
+ is(consoleAPIMessage.originAttributes.addonId, FAKE_ADDON_ID,
+ "the consoleAPImessage's originAttributes contains the expected addonId");
+
+ let cachedMessages = ConsoleAPIStorage.getEvents().filter((msg) => {
+ return msg.originAttributes && msg.originAttributes.addonId == FAKE_ADDON_ID;
+ });
+
+ is(cachedMessages.length, 1, "found the expected cached console messages from the addon");
+ is(cachedMessages[0] && cachedMessages[0].originAttributes.addonId, FAKE_ADDON_ID,
+ "the cached message's originAttributes contains the expected addonId");
+
+ finish();
+ }
+ }
+};
+
+function test()
+{
+ ConsoleObserver.init();
+
+ waitForExplicitFinish();
+
+ let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+ let uuid = uuidGenerator.generateUUID().number;
+ uuid = uuid.slice(1, -1); // Strip { and } off the UUID.
+ let baseURI = Services.io.newURI("about:blank", null, null);
+ let originAttributes = {addonId: FAKE_ADDON_ID};
+ let principal = Services.scriptSecurityManager
+ .createCodebasePrincipal(baseURI, originAttributes);
+
+ let chromeWebNav = Services.appShell.createWindowlessBrowser(true);
+ let interfaceRequestor = chromeWebNav.QueryInterface(Ci.nsIInterfaceRequestor);
+ let docShell = interfaceRequestor.getInterface(Ci.nsIDocShell);
+ docShell.createAboutBlankContentViewer(principal);
+
+ info("fake webextension docShell created");
+
+ registerCleanupFunction(function() {
+ if (chromeWebNav) {
+ chromeWebNav.close();
+ chromeWebNav = null;
+ }
+ ConsoleObserver.uninit();
+ });
+
+ let window = docShell.contentViewer.DOMDocument.defaultView;
+ window.eval(`console.log("${EXPECTED_CONSOLE_MESSAGE_CONTENT}");`);
+ chromeWebNav.close();
+ chromeWebNav = null;
+
+ info("fake webextension page logged a console api message");
+}
diff --git a/dom/tests/browser/browser_ConsoleStorageAPITests.js b/dom/tests/browser/browser_ConsoleStorageAPITests.js
new file mode 100644
index 000000000..742f6f877
--- /dev/null
+++ b/dom/tests/browser/browser_ConsoleStorageAPITests.js
@@ -0,0 +1,98 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI_NAV = "http://example.com/browser/dom/tests/browser/";
+
+function tearDown()
+{
+ while (gBrowser.tabs.length > 1)
+ gBrowser.removeCurrentTab();
+}
+
+add_task(function*()
+{
+ // Don't cache removed tabs, so "clear console cache on tab close" triggers.
+ yield SpecialPowers.pushPrefEnv({ set: [[ "browser.tabs.max_tabs_undo", 0 ]] });
+
+ registerCleanupFunction(tearDown);
+
+ // Open a keepalive tab in the background to make sure we don't accidentally
+ // kill the content process
+ var keepaliveTab = gBrowser.addTab("about:blank");
+
+ // Open the main tab to run the test in
+ var tab = gBrowser.addTab("about:blank");
+ gBrowser.selectedTab = tab;
+ var browser = gBrowser.selectedBrowser;
+
+ let observerPromise = ContentTask.spawn(browser, null, function* (opt) {
+ const TEST_URI = "http://example.com/browser/dom/tests/browser/test-console-api.html";
+ let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
+ .getService(Ci.nsIConsoleAPIStorage);
+
+ let observerPromise = new Promise(resolve => {
+ let apiCallCount = 0;
+ let ConsoleObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function(aSubject, aTopic, aData) {
+ if (aTopic == "console-storage-cache-event") {
+ apiCallCount++;
+ if (apiCallCount == 4) {
+ let windowId = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
+
+ Services.obs.removeObserver(this, "console-storage-cache-event");
+ ok(ConsoleAPIStorage.getEvents(windowId).length >= 4, "Some messages found in the storage service");
+ ConsoleAPIStorage.clearEvents();
+ is(ConsoleAPIStorage.getEvents(windowId).length, 0, "Cleared Storage");
+
+ resolve(windowId);
+ }
+ }
+ }
+ };
+
+ Services.obs.addObserver(ConsoleObserver, "console-storage-cache-event", false);
+
+ // Redirect the browser to the test URI
+ content.window.location = TEST_URI;
+ });
+
+ yield ContentTaskUtils.waitForEvent(this, "DOMContentLoaded");
+
+ content.console.log("this", "is", "a", "log message");
+ content.console.info("this", "is", "a", "info message");
+ content.console.warn("this", "is", "a", "warn message");
+ content.console.error("this", "is", "a", "error message");
+ return observerPromise;
+ });
+
+ let windowId = yield observerPromise;
+
+ yield ContentTask.spawn(browser, null, function() {
+ // make sure a closed window's events are in fact removed from
+ // the storage cache
+ content.console.log("adding a new event");
+ });
+
+ // Close the window.
+ gBrowser.removeTab(tab, {animate: false});
+ // Ensure actual window destruction is not delayed (too long).
+ SpecialPowers.DOMWindowUtils.garbageCollect();
+
+ // Spawn the check in the keepaliveTab, so that we can read the ConsoleAPIStorage correctly
+ gBrowser.selectedTab = keepaliveTab;
+ browser = gBrowser.selectedBrowser;
+
+ // Spin the event loop to make sure everything is cleared.
+ yield ContentTask.spawn(browser, null, function () {
+ return Promise.resolve();
+ });
+
+ yield ContentTask.spawn(browser, windowId, function(windowId) {
+ var ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
+ .getService(Ci.nsIConsoleAPIStorage);
+ is(ConsoleAPIStorage.getEvents(windowId).length, 0, "tab close is clearing the cache");
+ });
+});
diff --git a/dom/tests/browser/browser_ConsoleStoragePBTest_perwindowpb.js b/dom/tests/browser/browser_ConsoleStoragePBTest_perwindowpb.js
new file mode 100644
index 000000000..1efa01730
--- /dev/null
+++ b/dom/tests/browser/browser_ConsoleStoragePBTest_perwindowpb.js
@@ -0,0 +1,89 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+function test() {
+ // initialization
+ waitForExplicitFinish();
+ let windowsToClose = [];
+ let innerID;
+ let beforeEvents;
+ let afterEvents;
+ let storageShouldOccur;
+ let consoleObserver;
+ let testURI =
+ "http://example.com/browser/dom/tests/browser/test-console-api.html";
+ let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
+ .getService(Ci.nsIConsoleAPIStorage);
+
+ function getInnerWindowId(aWindow) {
+ return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .currentInnerWindowID;
+ }
+
+ function whenNewWindowLoaded(aOptions, aCallback) {
+ let win = OpenBrowserWindow(aOptions);
+ win.addEventListener("load", function onLoad() {
+ win.removeEventListener("load", onLoad, false);
+ aCallback(win);
+ }, false);
+ }
+
+ function doTest(aIsPrivateMode, aWindow, aCallback) {
+ aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+
+ consoleObserver = {
+ observe: function(aSubject, aTopic, aData) {
+ if (aTopic == "console-api-log-event") {
+ afterEvents = ConsoleAPIStorage.getEvents(innerID);
+ is(beforeEvents.length == afterEvents.length - 1, storageShouldOccur,
+ "storage should" + (storageShouldOccur ? "" : " not") + " occur");
+
+ executeSoon(function() {
+ Services.obs.removeObserver(consoleObserver, "console-api-log-event");
+ aCallback();
+ });
+ }
+ }
+ };
+
+ aWindow.Services.obs.addObserver(
+ consoleObserver, "console-api-log-event", false);
+ aWindow.nativeConsole.log("foo bar baz (private: " + aIsPrivateMode + ")");
+ }, true);
+
+ // We expect that console API messages are always stored.
+ storageShouldOccur = true;
+ innerID = getInnerWindowId(aWindow);
+ beforeEvents = ConsoleAPIStorage.getEvents(innerID);
+ aWindow.gBrowser.selectedBrowser.loadURI(testURI);
+ }
+
+ function testOnWindow(aOptions, aCallback) {
+ whenNewWindowLoaded(aOptions, function(aWin) {
+ windowsToClose.push(aWin);
+ // execute should only be called when need, like when you are opening
+ // web pages on the test. If calling executeSoon() is not necesary, then
+ // call whenNewWindowLoaded() instead of testOnWindow() on your test.
+ executeSoon(() => aCallback(aWin));
+ });
+ };
+
+ // this function is called after calling finish() on the test.
+ registerCleanupFunction(function() {
+ windowsToClose.forEach(function(aWin) {
+ aWin.close();
+ });
+ });
+
+ // test first when not on private mode
+ testOnWindow({}, function(aWin) {
+ doTest(false, aWin, function() {
+ // then test when on private mode
+ testOnWindow({private: true}, function(aWin) {
+ doTest(true, aWin, finish);
+ });
+ });
+ });
+}
diff --git a/dom/tests/browser/browser_allocateGigabyte.js b/dom/tests/browser/browser_allocateGigabyte.js
new file mode 100644
index 000000000..b291afe49
--- /dev/null
+++ b/dom/tests/browser/browser_allocateGigabyte.js
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/dom/tests/browser/test_largeAllocation.html";
+
+function expectProcessCreated() {
+ let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ return new Promise(resolve => {
+ let topic = "ipc:content-created";
+ function observer() {
+ os.removeObserver(observer, topic);
+ ok(true, "Expect process created");
+ resolve();
+ }
+ os.addObserver(observer, topic, /* weak = */ false);
+ });
+}
+
+add_task(function*() {
+ yield SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.largeAllocationHeader.enabled", true],
+ ]
+ });
+
+ // A toplevel tab should be able to navigate cross process!
+ yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
+ let epc = expectProcessCreated();
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.location = TEST_URI;
+ });
+
+ // Wait for the new process to be created by the Large-Allocation header
+ yield epc;
+
+ // Allocate a gigabyte of memory in the content process
+ yield ContentTask.spawn(aBrowser, null, () => {
+ let arrayBuffer = new ArrayBuffer(1024*1024*1024);
+ ok(arrayBuffer, "Successfully allocated a gigabyte of memory in content process");
+ });
+ });
+});
diff --git a/dom/tests/browser/browser_autofocus_background.js b/dom/tests/browser/browser_autofocus_background.js
new file mode 100644
index 000000000..8523ec047
--- /dev/null
+++ b/dom/tests/browser/browser_autofocus_background.js
@@ -0,0 +1,37 @@
+add_task(function* () {
+ let tabs = [ gBrowser.selectedTab, gBrowser.addTab() ];
+
+ // The first tab has an autofocused element.
+ // The second tab is exactly like the first one without the autofocus.
+ let testingList = [
+ { uri: "data:text/html,<!DOCTYPE html><html><body><input autofocus id='target'></body></html>",
+ tagName: "INPUT"},
+ ];
+
+ // Set the focus to the first tab.
+ tabs[0].linkedBrowser.focus();
+
+ // Load the second tab in the background.
+ let loadedPromise = BrowserTestUtils.browserLoaded(tabs[1].linkedBrowser);
+ tabs[1].linkedBrowser.loadURI(testingList[0].uri);
+ yield loadedPromise;
+
+ for (var i = 0; i < testingList.length; ++i) {
+ // Get active element in the tab.
+ let tagName = yield ContentTask.spawn(tabs[i + 1].linkedBrowser, null, function* () {
+ return content.document.activeElement.tagName;
+ });
+
+ is(tagName, testingList[i].tagName,
+ "The background tab's focused element should be " + testingList[i].tagName);
+ }
+
+ is(document.activeElement, tabs[0].linkedBrowser,
+ "The background tab's focused element should not cause the tab to be focused");
+
+ // Cleaning up.
+ for (let i = 1; i < tabs.length; i++) {
+ yield BrowserTestUtils.removeTab(tabs[i]);
+ }
+});
+
diff --git a/dom/tests/browser/browser_autofocus_preference.js b/dom/tests/browser/browser_autofocus_preference.js
new file mode 100644
index 000000000..213f6164e
--- /dev/null
+++ b/dom/tests/browser/browser_autofocus_preference.js
@@ -0,0 +1,18 @@
+add_task(function* () {
+ yield new Promise(resolve => {
+ SpecialPowers.pushPrefEnv({"set": [["browser.autofocus", false]]}, resolve);
+ });
+
+ const url = "data:text/html,<!DOCTYPE html><html><body><input autofocus><button autofocus></button><textarea autofocus></textarea><select autofocus></select></body></html>";
+
+ let loadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+ gBrowser.selectedBrowser.loadURI(url);
+ yield loadedPromise;
+
+ yield new Promise(resolve => executeSoon(resolve));
+
+ yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
+ is(content.document.activeElement, content.document.body, "body focused");
+ });
+});
+
diff --git a/dom/tests/browser/browser_beforeunload_between_chrome_content.js b/dom/tests/browser/browser_beforeunload_between_chrome_content.js
new file mode 100644
index 000000000..e8bf45d06
--- /dev/null
+++ b/dom/tests/browser/browser_beforeunload_between_chrome_content.js
@@ -0,0 +1,144 @@
+const TEST_URL = "http://www.example.com/browser/dom/tests/browser/dummy.html";
+
+function pageScript() {
+ window.addEventListener("beforeunload", function (event) {
+ var str = "Leaving?";
+ event.returnValue = str;
+ return str;
+ }, true);
+}
+
+function frameScript() {
+ content.window.addEventListener("beforeunload", function (event) {
+ sendAsyncMessage("Test:OnBeforeUnloadReceived");
+ var str = "Leaving?";
+ event.returnValue = str;
+ return str;
+ }, true);
+}
+
+// Wait for onbeforeunload dialog, and dismiss it immediately.
+function awaitAndCloseBeforeUnloadDialog(doStayOnPage) {
+ return new Promise(resolve => {
+ function onDialogShown(node) {
+ Services.obs.removeObserver(onDialogShown, "tabmodal-dialog-loaded");
+ let button = doStayOnPage ? node.ui.button1 : node.ui.button0;
+ button.click();
+ resolve();
+ }
+
+ Services.obs.addObserver(onDialogShown, "tabmodal-dialog-loaded");
+ });
+}
+
+SpecialPowers.pushPrefEnv(
+ {"set": [["dom.require_user_interaction_for_beforeunload", false]]});
+
+/**
+ * Test navigation from a content page to a chrome page. Also check that only
+ * one beforeunload event is fired.
+ */
+add_task(function* () {
+ let beforeUnloadCount = 0;
+ messageManager.addMessageListener("Test:OnBeforeUnloadReceived", function() {
+ beforeUnloadCount++;
+ });
+
+ // Open a content page.
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+ let browser = tab.linkedBrowser;
+
+ ok(browser.isRemoteBrowser, "Browser should be remote.");
+ browser.messageManager.loadFrameScript(
+ "data:,(" + frameScript.toString() + ")();", true);
+
+ // Navigate to a chrome page.
+ let dialogShown1 = awaitAndCloseBeforeUnloadDialog(false);
+ yield BrowserTestUtils.loadURI(browser, "about:support");
+ yield Promise.all([
+ dialogShown1,
+ BrowserTestUtils.browserLoaded(browser)
+ ]);
+ is(beforeUnloadCount, 1, "Should have received one beforeunload event.");
+ ok(!browser.isRemoteBrowser, "Browser should not be remote.");
+
+ // Go back to content page.
+ ok(gBrowser.webNavigation.canGoBack, "Should be able to go back.");
+ gBrowser.goBack();
+ yield BrowserTestUtils.browserLoaded(browser);
+ browser.messageManager.loadFrameScript(
+ "data:,(" + frameScript.toString() + ")();", true);
+
+ // Test that going forward triggers beforeunload prompt as well.
+ ok(gBrowser.webNavigation.canGoForward, "Should be able to go forward.");
+ let dialogShown2 = awaitAndCloseBeforeUnloadDialog(false);
+ gBrowser.goForward();
+ yield Promise.all([
+ dialogShown2,
+ BrowserTestUtils.browserLoaded(browser)
+ ]);
+ is(beforeUnloadCount, 2, "Should have received two beforeunload events.");
+
+ yield BrowserTestUtils.removeTab(tab);
+});
+
+/**
+ * Test navigation from a chrome page to a content page. Also check that only
+ * one beforeunload event is fired.
+ */
+add_task(function* () {
+ let beforeUnloadCount = 0;
+ messageManager.addMessageListener("Test:OnBeforeUnloadReceived", function() {
+ beforeUnloadCount++;
+ });
+
+ // Open a chrome page.
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
+ "about:support");
+ let browser = tab.linkedBrowser;
+
+ ok(!browser.isRemoteBrowser, "Browser should not be remote.");
+ yield ContentTask.spawn(browser, null, function* () {
+ content.window.addEventListener("beforeunload", function (event) {
+ sendAsyncMessage("Test:OnBeforeUnloadReceived");
+ var str = "Leaving?";
+ event.returnValue = str;
+ return str;
+ }, true);
+ });
+
+ // Navigate to a content page.
+ let dialogShown1 = awaitAndCloseBeforeUnloadDialog(false);
+ yield BrowserTestUtils.loadURI(browser, TEST_URL);
+ yield Promise.all([
+ dialogShown1,
+ BrowserTestUtils.browserLoaded(browser)
+ ]);
+ is(beforeUnloadCount, 1, "Should have received one beforeunload event.");
+ ok(browser.isRemoteBrowser, "Browser should be remote.");
+
+ // Go back to chrome page.
+ ok(gBrowser.webNavigation.canGoBack, "Should be able to go back.");
+ gBrowser.goBack();
+ yield BrowserTestUtils.browserLoaded(browser);
+ yield ContentTask.spawn(browser, null, function* () {
+ content.window.addEventListener("beforeunload", function (event) {
+ sendAsyncMessage("Test:OnBeforeUnloadReceived");
+ var str = "Leaving?";
+ event.returnValue = str;
+ return str;
+ }, true);
+ });
+
+ // Test that going forward triggers beforeunload prompt as well.
+ ok(gBrowser.webNavigation.canGoForward, "Should be able to go forward.");
+ let dialogShown2 = awaitAndCloseBeforeUnloadDialog(false);
+ gBrowser.goForward();
+ yield Promise.all([
+ dialogShown2,
+ BrowserTestUtils.browserLoaded(browser)
+ ]);
+ is(beforeUnloadCount, 2, "Should have received two beforeunload events.");
+
+ yield BrowserTestUtils.removeTab(tab);
+});
diff --git a/dom/tests/browser/browser_bug1004814.js b/dom/tests/browser/browser_bug1004814.js
new file mode 100644
index 000000000..d69d86dea
--- /dev/null
+++ b/dom/tests/browser/browser_bug1004814.js
@@ -0,0 +1,36 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+add_task(function*() {
+ yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
+ let duration = yield ContentTask.spawn(aBrowser, null, function (opts) {
+ const TEST_URI = "http://example.com/browser/dom/tests/browser/test_bug1004814.html";
+
+ return new Promise(resolve => {
+ let ConsoleObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+
+ observe: function(aSubject, aTopic, aData) {
+ var obj = aSubject.wrappedJSObject;
+ if (obj.arguments.length != 1 || obj.arguments[0] != 'bug1004814' ||
+ obj.level != 'timeEnd') {
+ return;
+ }
+
+ Services.obs.removeObserver(this, "console-api-log-event");
+ resolve(obj.timer.duration);
+ }
+ };
+
+ Services.obs.addObserver(ConsoleObserver, "console-api-log-event", false);
+
+ // Redirect the browser to the correct document to start the test
+ content.document.location = TEST_URI;
+ });
+ });
+
+ ok(duration > 0, "ConsoleEvent.timer.duration > 0: " + duration + " ~ 200ms");
+ });
+});
diff --git a/dom/tests/browser/browser_bug1008941_dismissGeolocationHanger.js b/dom/tests/browser/browser_bug1008941_dismissGeolocationHanger.js
new file mode 100644
index 000000000..93b2124ef
--- /dev/null
+++ b/dom/tests/browser/browser_bug1008941_dismissGeolocationHanger.js
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+const TEST_URI = "http://example.com/" +
+ "browser/dom/tests/browser/position.html";
+
+add_task(function testDismissHanger() {
+ info("Check that location is not shared when dismissing the geolocation hanger");
+
+ let promisePanelShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown", true);
+ yield BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URI);
+ yield promisePanelShown;
+
+ // click outside the Geolocation hanger to dismiss it
+ window.document.getElementById("nav-bar").click();
+ info("Clicked outside the Geolocation panel to dismiss it");
+
+ let hasLocation = yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() {
+ return content.document.body.innerHTML.includes("location...");
+ });
+
+ ok(hasLocation, "Location is not shared");
+
+ yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
diff --git a/dom/tests/browser/browser_bug1238427.js b/dom/tests/browser/browser_bug1238427.js
new file mode 100644
index 000000000..18e39ad95
--- /dev/null
+++ b/dom/tests/browser/browser_bug1238427.js
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const TEST_URI = "http://example.com/" +
+ "browser/dom/tests/browser/geo_leak_test.html";
+
+const BASE_GEO_URL = "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs";
+
+add_task(function* () {
+ Services.prefs.setBoolPref("geo.prompt.testing", true);
+ Services.prefs.setBoolPref("geo.prompt.testing.allow", true);
+
+ // Make the geolocation provider responder very slowly to ensure that
+ // it does not reply before we close the tab.
+ Services.prefs.setCharPref("geo.wifi.uri", BASE_GEO_URL + "?delay=100000");
+
+ // Open the test URI and close it. The test harness will make sure that the
+ // page is cleaned up after some GCs. If geolocation is not shut down properly,
+ // it will show up as a non-shutdown leak.
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: TEST_URI
+ }, function* (browser) { /* ... */ });
+
+ ok(true, "Need to do something in this test");
+});
+
diff --git a/dom/tests/browser/browser_bug396843.js b/dom/tests/browser/browser_bug396843.js
new file mode 100644
index 000000000..84d7e3b83
--- /dev/null
+++ b/dom/tests/browser/browser_bug396843.js
@@ -0,0 +1,287 @@
+/** Test for Bug 396843 **/
+
+function testInDocument(doc, documentID) {
+
+ var allNodes = [];
+ var XMLNodes = [];
+
+ // HTML
+ function HTML_TAG(name) {
+ allNodes.push(doc.createElement(name));
+ }
+
+ /* List copy/pasted from nsHTMLTagList.h */
+ HTML_TAG("a", "Anchor")
+ HTML_TAG("abbr", "Span")
+ HTML_TAG("acronym", "Span")
+ HTML_TAG("address", "Span")
+ HTML_TAG("applet", "SharedObject")
+ HTML_TAG("area", "Area")
+ HTML_TAG("b", "Span")
+ HTML_TAG("base", "Shared")
+ HTML_TAG("basefont", "Span")
+ HTML_TAG("bdo", "Span")
+ HTML_TAG("bgsound", "Span")
+ HTML_TAG("big", "Span")
+ HTML_TAG("blockquote", "Shared")
+ HTML_TAG("body", "Body")
+ HTML_TAG("br", "BR")
+ HTML_TAG("button", "Button")
+ HTML_TAG("canvas", "Canvas")
+ HTML_TAG("caption", "TableCaption")
+ HTML_TAG("center", "Span")
+ HTML_TAG("cite", "Span")
+ HTML_TAG("code", "Span")
+ HTML_TAG("col", "TableCol")
+ HTML_TAG("colgroup", "TableCol")
+ HTML_TAG("dd", "Span")
+ HTML_TAG("del", "Mod")
+ HTML_TAG("dfn", "Span")
+ HTML_TAG("dir", "Shared")
+ HTML_TAG("div", "Div")
+ HTML_TAG("dl", "SharedList")
+ HTML_TAG("dt", "Span")
+ HTML_TAG("em", "Span")
+ HTML_TAG("embed", "SharedObject")
+ HTML_TAG("fieldset", "FieldSet")
+ HTML_TAG("font", "Font")
+ HTML_TAG("form", "Form")
+ HTML_TAG("frame", "Frame")
+ HTML_TAG("frameset", "FrameSet")
+ HTML_TAG("h1", "Heading")
+ HTML_TAG("h2", "Heading")
+ HTML_TAG("h3", "Heading")
+ HTML_TAG("h4", "Heading")
+ HTML_TAG("h5", "Heading")
+ HTML_TAG("h6", "Heading")
+ HTML_TAG("head", "Head")
+ HTML_TAG("hr", "HR")
+ HTML_TAG("html", "Html")
+ HTML_TAG("i", "Span")
+ HTML_TAG("iframe", "IFrame")
+ HTML_TAG("image", "")
+ HTML_TAG("img", "Image")
+ HTML_TAG("input", "Input")
+ HTML_TAG("ins", "Mod")
+ HTML_TAG("isindex", "Unknown")
+ HTML_TAG("kbd", "Span")
+ HTML_TAG("keygen", "Span")
+ HTML_TAG("label", "Label")
+ HTML_TAG("legend", "Legend")
+ HTML_TAG("li", "LI")
+ HTML_TAG("link", "Link")
+ HTML_TAG("listing", "Span")
+ HTML_TAG("map", "Map")
+ HTML_TAG("marquee", "Div")
+ HTML_TAG("menu", "Shared")
+ HTML_TAG("meta", "Meta")
+ HTML_TAG("multicol", "Unknown")
+ HTML_TAG("nobr", "Span")
+ HTML_TAG("noembed", "Div")
+ HTML_TAG("noframes", "Div")
+ HTML_TAG("noscript", "Div")
+ HTML_TAG("object", "Object")
+ HTML_TAG("ol", "SharedList")
+ HTML_TAG("optgroup", "OptGroup")
+ HTML_TAG("option", "Option")
+ HTML_TAG("p", "Paragraph")
+ HTML_TAG("param", "Shared")
+ HTML_TAG("plaintext", "Span")
+ HTML_TAG("pre", "Pre")
+ HTML_TAG("q", "Shared")
+ HTML_TAG("s", "Span")
+ HTML_TAG("samp", "Span")
+ HTML_TAG("script", "Script")
+ HTML_TAG("select", "Select")
+ HTML_TAG("small", "Span")
+ HTML_TAG("spacer", "Unknown")
+ HTML_TAG("span", "Span")
+ HTML_TAG("strike", "Span")
+ HTML_TAG("strong", "Span")
+ HTML_TAG("style", "Style")
+ HTML_TAG("sub", "Span")
+ HTML_TAG("sup", "Span")
+ HTML_TAG("table", "Table")
+ HTML_TAG("tbody", "TableSection")
+ HTML_TAG("td", "TableCell")
+ HTML_TAG("textarea", "TextArea")
+ HTML_TAG("tfoot", "TableSection")
+ HTML_TAG("th", "TableCell")
+ HTML_TAG("thead", "TableSection")
+ HTML_TAG("template", "Template")
+ HTML_TAG("title", "Title")
+ HTML_TAG("tr", "TableRow")
+ HTML_TAG("tt", "Span")
+ HTML_TAG("u", "Span")
+ HTML_TAG("ul", "SharedList")
+ HTML_TAG("var", "Span")
+ HTML_TAG("wbr", "Shared")
+ HTML_TAG("xmp", "Span")
+
+ function SVG_TAG(name) {
+ allNodes.push(doc.createElementNS("http://www.w3.org/2000/svg", name));
+ }
+
+ // List sorta stolen from SVG element factory.
+ SVG_TAG("a")
+ SVG_TAG("polyline")
+ SVG_TAG("polygon")
+ SVG_TAG("circle")
+ SVG_TAG("ellipse")
+ SVG_TAG("line")
+ SVG_TAG("rect")
+ SVG_TAG("svg")
+ SVG_TAG("g")
+ SVG_TAG("foreignObject")
+ SVG_TAG("path")
+ SVG_TAG("text")
+ SVG_TAG("tspan")
+ SVG_TAG("image")
+ SVG_TAG("style")
+ SVG_TAG("linearGradient")
+ SVG_TAG("metadata")
+ SVG_TAG("radialGradient")
+ SVG_TAG("stop")
+ SVG_TAG("defs")
+ SVG_TAG("desc")
+ SVG_TAG("script")
+ SVG_TAG("use")
+ SVG_TAG("symbol")
+ SVG_TAG("marker")
+ SVG_TAG("title")
+ SVG_TAG("clipPath")
+ SVG_TAG("textPath")
+ SVG_TAG("filter")
+ SVG_TAG("feBlend")
+ SVG_TAG("feColorMatrix")
+ SVG_TAG("feComponentTransfer")
+ SVG_TAG("feComposite")
+ SVG_TAG("feFuncR")
+ SVG_TAG("feFuncG")
+ SVG_TAG("feFuncB")
+ SVG_TAG("feFuncA")
+ SVG_TAG("feGaussianBlur")
+ SVG_TAG("feMerge")
+ SVG_TAG("feMergeNode")
+ SVG_TAG("feMorphology")
+ SVG_TAG("feOffset")
+ SVG_TAG("feFlood")
+ SVG_TAG("feTile")
+ SVG_TAG("feTurbulence")
+ SVG_TAG("feConvolveMatrix")
+ SVG_TAG("feDistantLight")
+ SVG_TAG("fePointLight")
+ SVG_TAG("feSpotLight")
+ SVG_TAG("feDiffuseLighting")
+ SVG_TAG("feSpecularLighting")
+ SVG_TAG("feDisplacementMap")
+ SVG_TAG("feImage")
+ SVG_TAG("pattern")
+ SVG_TAG("mask")
+ SVG_TAG("svgSwitch")
+
+ // Toss in some other namespaced stuff too, for good measure
+ // XUL stuff might not be creatable in content documents
+ try {
+ allNodes.push(doc.createElementNS(
+ "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+ "window"));
+ } catch (e) {}
+ allNodes.push(doc.createElementNS("http://www.w3.org/1998/Math/MathML",
+ "math"));
+ allNodes.push(doc.createElementNS("http://www.w3.org/2001/xml-events",
+ "testname"));
+ allNodes.push(doc.createElementNS("bogus.namespace", "testname"));
+
+ var XMLDoc = doc.implementation.createDocument("", "", null);
+
+ // And non-elements
+ allNodes.push(doc.createTextNode("some text"));
+ allNodes.push(doc.createComment("some text"));
+ allNodes.push(doc.createDocumentFragment());
+ XMLNodes.push(XMLDoc.createCDATASection("some text"));
+ XMLNodes.push(XMLDoc.createProcessingInstruction("PI", "data"));
+
+ function runTestUnwrapped() {
+ if (!("wrappedJSObject" in doc)) {
+ return;
+ }
+ ok(doc.wrappedJSObject.nodePrincipal === undefined,
+ "Must not have document principal for " + documentID);
+ ok(doc.wrappedJSObject.baseURIObject === undefined,
+ "Must not have document base URI for " + documentID);
+ ok(doc.wrappedJSObject.documentURIObject === undefined,
+ "Must not have document URI for " + documentID);
+
+ for (var i = 0; i < allNodes.length; ++i) {
+ ok(allNodes[i].wrappedJSObject.nodePrincipal === undefined,
+ "Unexpected principal appears for " + allNodes[i].nodeName +
+ " in " + documentID);
+ ok(allNodes[i].wrappedJSObject.baseURIObject === undefined,
+ "Unexpected base URI appears for " + allNodes[i].nodeName +
+ " in " + documentID);
+ }
+ }
+
+ function runTestProps() {
+ isnot(doc.nodePrincipal, null,
+ "Must have document principal in " + documentID);
+ is(doc.nodePrincipal instanceof Components.interfaces.nsIPrincipal,
+ true, "document principal must be a principal in " + documentID);
+ isnot(doc.baseURIObject, null,
+ "Must have document base URI in" + documentID);
+ is(doc.baseURIObject instanceof Components.interfaces.nsIURI,
+ true, "document base URI must be a URI in " + documentID);
+ isnot(doc.documentURIObject, null,
+ "Must have document URI " + documentID);
+ is(doc.documentURIObject instanceof Components.interfaces.nsIURI,
+ true, "document URI must be a URI in " + documentID);
+ is(doc.documentURIObject.spec, doc.documentURI,
+ "document URI must be the right URI in " + documentID);
+
+ for (var i = 0; i < allNodes.length; ++i) {
+ is(allNodes[i].nodePrincipal, doc.nodePrincipal,
+ "Unexpected principal for " + allNodes[i].nodeName +
+ " in " + documentID);
+ is(allNodes[i].baseURIObject, doc.baseURIObject,
+ "Unexpected base URI for " + allNodes[i].nodeName +
+ " in " + documentID);
+ }
+
+ for (i = 0; i < XMLNodes.length; ++i) {
+ is(XMLNodes[i].nodePrincipal, doc.nodePrincipal,
+ "Unexpected principal for " + XMLNodes[i].nodeName +
+ " in " + documentID);
+ is(XMLNodes[i].baseURIObject.spec, "about:blank",
+ "Unexpected base URI for " + XMLNodes[i].nodeName +
+ " in " + documentID);
+ }
+ }
+
+ runTestUnwrapped();
+ runTestProps();
+ runTestUnwrapped();
+}
+
+add_task(function* test1() {
+ testInDocument(document, "browser window");
+});
+
+function* newTabTest(location) {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: location },
+ function* (browser) {
+ yield ContentTask.spawn(browser, { location, testInDocument_: testInDocument.toSource() },
+ function* ({ location, testInDocument_ }) {
+ let testInDocument = eval(`(() => (${testInDocument_}))()`);
+ testInDocument(content.document, location);
+ });
+ });
+}
+
+add_task(function* test2() {
+ yield newTabTest("about:blank");
+});
+
+add_task(function* test3() {
+ yield newTabTest("about:config");
+});
diff --git a/dom/tests/browser/browser_focus_steal_from_chrome.js b/dom/tests/browser/browser_focus_steal_from_chrome.js
new file mode 100644
index 000000000..37c2e1028
--- /dev/null
+++ b/dom/tests/browser/browser_focus_steal_from_chrome.js
@@ -0,0 +1,151 @@
+add_task(function* () {
+ requestLongerTimeout(2);
+
+ let testingList = [
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><input id='target'></body>",
+ tagName: "INPUT", methodName: "focus" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').select(); }, 10);\"><input id='target'></body>",
+ tagName: "INPUT", methodName: "select" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><a href='about:blank' id='target'>anchor</a></body>",
+ tagName: "A", methodName: "focus" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><button id='target'>button</button></body>",
+ tagName: "BUTTON", methodName: "focus" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><select id='target'><option>item1</option></select></body>",
+ tagName: "SELECT", methodName: "focus" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><textarea id='target'>textarea</textarea></body>",
+ tagName: "TEXTAREA", methodName: "focus" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').select(); }, 10);\"><textarea id='target'>textarea</textarea></body>",
+ tagName: "TEXTAREA", methodName: "select" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><label id='target'><input></label></body>",
+ tagName: "INPUT", methodName: "focus of label element" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><fieldset><legend id='target'>legend</legend><input></fieldset></body>",
+ tagName: "INPUT", methodName: "focus of legend element" },
+ { uri: "data:text/html,<body onload=\"setTimeout(function () {" +
+ " var element = document.getElementById('target');" +
+ " var event = document.createEvent('MouseEvent');" +
+ " event.initMouseEvent('click', true, true, window," +
+ " 1, 0, 0, 0, 0, false, false, false, false, 0, element);" +
+ " element.dispatchEvent(event); }, 10);\">" +
+ "<label id='target'><input></label></body>",
+ tagName: "INPUT", methodName: "click event on the label element" },
+ ];
+
+ yield BrowserTestUtils.withNewTab("about:blank", function*(bg) {
+ yield BrowserTestUtils.withNewTab("about:blank", function*(fg) {
+ for (let test of testingList) {
+ // Focus the foreground tab's content
+ fg.focus();
+
+ // Load the URIs.
+ yield BrowserTestUtils.loadURI(bg, test.uri);
+ yield BrowserTestUtils.browserLoaded(bg);
+ yield BrowserTestUtils.loadURI(fg, test.uri);
+ yield BrowserTestUtils.browserLoaded(fg);
+
+ ok(true, "Test1: Both of the tabs are loaded");
+
+ // Confirm that the contents should be able to steal focus from content.
+ yield ContentTask.spawn(fg, test, test => {
+ return new Promise(res => {
+ function f() {
+ let e = content.document.activeElement;
+ if (e.tagName != test.tagName) {
+ setTimeout(f, 10);
+ } else {
+ is(Services.focus.focusedElement, e,
+ "the foreground tab's " + test.tagName +
+ " element isn't focused by the " + test.methodName +
+ " (Test1: content can steal focus)");
+ res();
+ }
+ }
+ f();
+ });
+ });
+
+ yield ContentTask.spawn(bg, test, test => {
+ return new Promise(res => {
+ function f() {
+ let e = content.document.activeElement;
+ if (e.tagName != test.tagName) {
+ setTimeout(f, 10);
+ } else {
+ isnot(Services.focus.focusedElement, e,
+ "the background tab's " + test.tagName +
+ " element is focused by the " + test.methodName +
+ " (Test1: content can steal focus)");
+ res();
+ }
+ }
+ f();
+ });
+ });
+
+ if (fg.isRemoteBrowser) {
+ is(Services.focus.focusedElement, fg,
+ "Focus should be on the content in the parent process");
+ }
+
+ // Focus chrome
+ document.getElementById("urlbar").focus();
+ let originalFocus = Services.focus.focusedElement;
+
+ // Load about:blank just to make sure that everything works nicely
+ yield BrowserTestUtils.loadURI(bg, "about:blank");
+ yield BrowserTestUtils.browserLoaded(bg);
+ yield BrowserTestUtils.loadURI(fg, "about:blank");
+ yield BrowserTestUtils.browserLoaded(fg);
+
+ // Load the URIs.
+ yield BrowserTestUtils.loadURI(bg, test.uri);
+ yield BrowserTestUtils.browserLoaded(bg);
+ yield BrowserTestUtils.loadURI(fg, test.uri);
+ yield BrowserTestUtils.browserLoaded(fg);
+
+ ok(true, "Test2: Both of the tabs are loaded");
+
+ // Confirm that the contents should be able to steal focus from content.
+ yield ContentTask.spawn(fg, test, test => {
+ return new Promise(res => {
+ function f() {
+ let e = content.document.activeElement;
+ if (e.tagName != test.tagName) {
+ setTimeout(f, 10);
+ } else {
+ isnot(Services.focus.focusedElement, e,
+ "the foreground tab's " + test.tagName +
+ " element is focused by the " + test.methodName +
+ " (Test2: content can NOT steal focus)");
+ res();
+ }
+ }
+ f();
+ });
+ });
+
+ yield ContentTask.spawn(bg, test, test => {
+ return new Promise(res => {
+ function f() {
+ let e = content.document.activeElement;
+ if (e.tagName != test.tagName) {
+ setTimeout(f, 10);
+ } else {
+ isnot(Services.focus.focusedElement, e,
+ "the background tab's " + test.tagName +
+ " element is focused by the " + test.methodName +
+ " (Test2: content can NOT steal focus)");
+ res();
+ }
+ }
+ f();
+ });
+ });
+
+ is(Services.focus.focusedElement, originalFocus,
+ "The parent process's focus has shifted " +
+ "(methodName = " + test.methodName + ")" +
+ " (Test2: content can NOT steal focus)");
+ }
+ });
+ });
+});
diff --git a/dom/tests/browser/browser_focus_steal_from_chrome_during_mousedown.js b/dom/tests/browser/browser_focus_steal_from_chrome_during_mousedown.js
new file mode 100644
index 000000000..a21240872
--- /dev/null
+++ b/dom/tests/browser/browser_focus_steal_from_chrome_during_mousedown.js
@@ -0,0 +1,45 @@
+add_task(function* test() {
+ const kTestURI =
+ "data:text/html," +
+ "<script type=\"text/javascript\">" +
+ " function onMouseDown(aEvent) {" +
+ " document.getElementById('willBeFocused').focus();" +
+ " aEvent.preventDefault();" +
+ " }" +
+ "</script>" +
+ "<body id=\"body\">" +
+ "<button onmousedown=\"onMouseDown(event);\" style=\"width: 100px; height: 100px;\">click here</button>" +
+ "<input id=\"willBeFocused\"></body>";
+
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, kTestURI);
+
+ let fm = Components.classes["@mozilla.org/focus-manager;1"].
+ getService(Components.interfaces.nsIFocusManager);
+
+ for (var button = 0; button < 3; button++) {
+ // Set focus to a chrome element before synthesizing a mouse down event.
+ document.getElementById("urlbar").focus();
+
+ is(fm.focusedElement, document.getElementById("urlbar").inputField,
+ "Failed to move focus to search bar: button=" + button);
+
+ // Synthesize mouse down event on browser object over the button, such that
+ // the event propagates through both processes.
+ EventUtils.synthesizeMouse(tab.linkedBrowser, 20, 20, { "button": button }, null);
+
+ isnot(fm.focusedElement, document.getElementById("urlbar").inputField,
+ "Failed to move focus away from search bar: button=" + button);
+
+ yield ContentTask.spawn(tab.linkedBrowser, button, function (button) {
+ let fm = Components.classes["@mozilla.org/focus-manager;1"].
+ getService(Components.interfaces.nsIFocusManager);
+
+ Assert.equal(content.document.activeElement.id, "willBeFocused",
+ "The input element isn't active element: button=" + button);
+ Assert.equal(fm.focusedElement, content.document.activeElement,
+ "The active element isn't focused element in App level: button=" + button);
+ });
+ }
+
+ gBrowser.removeTab(tab);
+});
diff --git a/dom/tests/browser/browser_frame_elements.html b/dom/tests/browser/browser_frame_elements.html
new file mode 100644
index 000000000..4843173f5
--- /dev/null
+++ b/dom/tests/browser/browser_frame_elements.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>Frame Element Tests</title>
+</head>
+<body>
+ <h1>Frame Element Tests</h1>
+
+ <iframe id="iframe-blank" src="about:blank"></iframe>
+
+ <iframe id="iframe-data-url" src="data:text/html;charset=utf-8,%3Chtml%3E%3Cbody%3Eiframe%3C/body%3E%3C/html%3E"></iframe>
+
+ <object id="object-data-url" type="text/html" data="data:text/html;charset=utf-8,%3Chtml%3E%3Cbody%3Eobject%3C/body%3E%3C/html%3E"></object>
+
+</body>
diff --git a/dom/tests/browser/browser_frame_elements.js b/dom/tests/browser/browser_frame_elements.js
new file mode 100644
index 000000000..e26fe95ec
--- /dev/null
+++ b/dom/tests/browser/browser_frame_elements.js
@@ -0,0 +1,89 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/dom/tests/browser/browser_frame_elements.html";
+
+function getWindowUtils(window) {
+ return window.
+ QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+}
+
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: TEST_URI }, function* (browser) {
+ if (!browser.isRemoteBrowser) {
+ // Non-e10s, access contentWindow and confirm its container is the browser:
+ let windowUtils = getWindowUtils(browser.contentWindow);
+ is (windowUtils.containerElement, browser,
+ "Container element for main window is xul:browser");
+
+ }
+
+ yield ContentTask.spawn(browser, null, startTests);
+ yield Task.spawn(mozBrowserTests(browser));
+ });
+});
+
+function startTests() {
+ function getWindowUtils(window) {
+ return window.
+ QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+ getInterface(Components.interfaces.nsIDOMWindowUtils);
+ }
+ info("Frame tests started");
+
+ info("Checking top window");
+ let gWindow = content;
+ Assert.equal(gWindow.top, gWindow, "gWindow is top");
+ Assert.equal(gWindow.parent, gWindow, "gWindow is parent");
+
+ info("Checking about:blank iframe");
+ let iframeBlank = gWindow.document.querySelector("#iframe-blank");
+ Assert.ok(iframeBlank, "Iframe exists on page");
+ let iframeBlankUtils = getWindowUtils(iframeBlank.contentWindow);
+ Assert.equal(iframeBlankUtils.containerElement, iframeBlank, "Container element for iframe window is iframe");
+ Assert.equal(iframeBlank.contentWindow.top, gWindow, "gWindow is top");
+ Assert.equal(iframeBlank.contentWindow.parent, gWindow, "gWindow is parent");
+
+ info("Checking iframe with data url src");
+ let iframeDataUrl = gWindow.document.querySelector("#iframe-data-url");
+ Assert.ok(iframeDataUrl, "Iframe exists on page");
+ let iframeDataUrlUtils = getWindowUtils(iframeDataUrl.contentWindow);
+ Assert.equal(iframeDataUrlUtils.containerElement, iframeDataUrl, "Container element for iframe window is iframe");
+ Assert.equal(iframeDataUrl.contentWindow.top, gWindow, "gWindow is top");
+ Assert.equal(iframeDataUrl.contentWindow.parent, gWindow, "gWindow is parent");
+
+ info("Checking object with data url data attribute");
+ let objectDataUrl = gWindow.document.querySelector("#object-data-url");
+ Assert.ok(objectDataUrl, "Object exists on page");
+ let objectDataUrlUtils = getWindowUtils(objectDataUrl.contentWindow);
+ Assert.equal(objectDataUrlUtils.containerElement, objectDataUrl, "Container element for object window is the object");
+ Assert.equal(objectDataUrl.contentWindow.top, gWindow, "gWindow is top");
+ Assert.equal(objectDataUrl.contentWindow.parent, gWindow, "gWindow is parent");
+}
+
+function* mozBrowserTests(browser) {
+ info("Granting special powers for mozbrowser");
+ SpecialPowers.addPermission("browser", true, TEST_URI);
+ SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
+ SpecialPowers.setBoolPref('network.disable.ipc.security', true);
+
+ yield ContentTask.spawn(browser, null, function() {
+ info("Checking mozbrowser iframe");
+ let mozBrowserFrame = content.document.createElement("iframe");
+ mozBrowserFrame.setAttribute("mozbrowser", "");
+ content.document.body.appendChild(mozBrowserFrame);
+ Assert.equal(mozBrowserFrame.contentWindow.top, mozBrowserFrame.contentWindow,
+ "Mozbrowser top == iframe window");
+ Assert.equal(mozBrowserFrame.contentWindow.parent, mozBrowserFrame.contentWindow,
+ "Mozbrowser parent == iframe window");
+ });
+
+ info("Revoking special powers for mozbrowser");
+ SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
+ SpecialPowers.clearUserPref('network.disable.ipc.security');
+ SpecialPowers.removePermission("browser", TEST_URI);
+}
diff --git a/dom/tests/browser/browser_largeAllocation.js b/dom/tests/browser/browser_largeAllocation.js
new file mode 100644
index 000000000..54079718d
--- /dev/null
+++ b/dom/tests/browser/browser_largeAllocation.js
@@ -0,0 +1,214 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TEST_URI = "http://example.com/browser/dom/tests/browser/test_largeAllocation.html";
+
+function expectProcessCreated() {
+ let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ return new Promise(resolve => {
+ let topic = "ipc:content-created";
+ function observer() {
+ os.removeObserver(observer, topic);
+ ok(true, "Expect process created");
+ resolve();
+ }
+ os.addObserver(observer, topic, /* weak = */ false);
+ });
+}
+
+function expectNoProcess() {
+ let os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ let topic = "ipc:content-created";
+ function observer() {
+ ok(false, "A process was created!");
+ os.removeObserver(observer, topic);
+ }
+ os.addObserver(observer, topic, /* weak = */ false);
+
+ return () => os.removeObserver(observer, topic);
+}
+
+function getPID(aBrowser) {
+ return ContentTask.spawn(aBrowser, null, () => {
+ const appinfo = Components.classes["@mozilla.org/xre/app-info;1"]
+ .getService(Components.interfaces.nsIXULRuntime);
+ return appinfo.processID;
+ });
+}
+
+add_task(function*() {
+ // I'm terrible and put this set of tests into a single file, so I need a longer timeout
+ requestLongerTimeout(2);
+
+ yield SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.largeAllocationHeader.enabled", true],
+ ]
+ });
+
+ // A toplevel tab should be able to navigate cross process!
+ yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
+ ok(true, "Starting test 0");
+ let pid1 = yield getPID(aBrowser);
+
+ let epc = expectProcessCreated();
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.location = TEST_URI;
+ });
+
+ // Wait for the new process to be created
+ yield epc;
+
+ let pid2 = yield getPID(aBrowser);
+
+ isnot(pid1, pid2, "The pids should be different between the initial load and the new load");
+ });
+
+ // When a Large-Allocation document is loaded in an iframe, the header should
+ // be ignored, and the tab should stay in the current process.
+ yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
+ ok(true, "Starting test 1");
+ let pid1 = yield getPID(aBrowser);
+
+ // Fail the test if we create a process
+ let stopExpectNoProcess = expectNoProcess();
+
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.body.innerHTML = `<iframe src='${TEST_URI}'></iframe>`;
+
+ return new Promise(resolve => {
+ content.document.body.querySelector('iframe').onload = () => {
+ ok(true, "Iframe finished loading");
+ resolve();
+ };
+ });
+ });
+
+ let pid2 = yield getPID(aBrowser);
+
+ is(pid1, pid2, "The PID should not have changed");
+
+ stopExpectNoProcess();
+ });
+
+ // If you have an opener cross process navigation shouldn't work
+ yield BrowserTestUtils.withNewTab("http://example.com", function*(aBrowser) {
+ ok(true, "Starting test 2");
+ let pid1 = yield getPID(aBrowser);
+
+ // Fail the test if we create a process
+ let stopExpectNoProcess = expectNoProcess();
+
+ let loaded = ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.body.innerHTML = '<button>CLICK ME</button>';
+
+ return new Promise(resolve => {
+ content.document.querySelector('button').onclick = e => {
+ let w = content.window.open(TEST_URI, '_blank');
+ w.onload = () => {
+ ok(true, "Window finished loading");
+ w.close();
+ resolve();
+ };
+ };
+ });
+ });
+
+ yield BrowserTestUtils.synthesizeMouseAtCenter("button", {}, aBrowser);
+
+ yield loaded;
+
+ let pid2 = yield getPID(aBrowser);
+
+ is(pid1, pid2, "The PID should not have changed");
+
+ stopExpectNoProcess();
+ });
+
+ // Load Large-Allocation twice with about:blank load in between
+ yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
+ ok(true, "Starting test 3");
+ let pid1 = yield getPID(aBrowser);
+
+ let epc = expectProcessCreated();
+
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.location = TEST_URI;
+ });
+
+ yield epc;
+
+ let pid2 = yield getPID(aBrowser);
+
+ isnot(pid1, pid2);
+
+ epc = expectProcessCreated();
+
+ yield BrowserTestUtils.browserLoaded(aBrowser);
+
+ yield ContentTask.spawn(aBrowser, null, () => content.document.location = "about:blank");
+
+ yield BrowserTestUtils.browserLoaded(aBrowser);
+
+ let pid3 = yield getPID(aBrowser);
+
+ is(pid2, pid3);
+
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.location = TEST_URI;
+ });
+
+ yield epc;
+
+ let pid4 = yield getPID(aBrowser);
+
+ isnot(pid1, pid4);
+ isnot(pid2, pid4);
+ });
+
+ // Load Large-Allocation then about:blank load, then back button press should load from bfcache.
+ yield BrowserTestUtils.withNewTab("about:blank", function*(aBrowser) {
+ ok(true, "Starting test 4");
+ let pid1 = yield getPID(aBrowser);
+
+ let epc = expectProcessCreated();
+
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.document.location = TEST_URI;
+ });
+
+ yield epc;
+
+ let pid2 = yield getPID(aBrowser);
+
+ isnot(pid1, pid2, "PIDs 1 and 2 should not match");
+
+ let stopExpectNoProcess = expectNoProcess();
+
+ yield BrowserTestUtils.browserLoaded(aBrowser);
+
+ // Switch to about:blank, so we can navigate back
+ yield ContentTask.spawn(aBrowser, null, () => {
+ content.document.location = "about:blank";
+ });
+
+ yield BrowserTestUtils.browserLoaded(aBrowser);
+
+ let pid3 = yield getPID(aBrowser);
+
+ is(pid2, pid3, "PIDs 2 and 3 should match");
+
+ // Navigate back to the previous page, loading it from bfcache
+ yield ContentTask.spawn(aBrowser, TEST_URI, TEST_URI => {
+ content.window.history.back();
+ });
+
+ let pid4 = yield getPID(aBrowser);
+
+ isnot(pid1, pid4, "PID 4 shouldn't match PID 1");
+ is(pid2, pid4, "PID 4 should match PID 2");
+
+ stopExpectNoProcess();
+ });
+});
diff --git a/dom/tests/browser/browser_localStorage_privatestorageevent.js b/dom/tests/browser/browser_localStorage_privatestorageevent.js
new file mode 100644
index 000000000..83458a399
--- /dev/null
+++ b/dom/tests/browser/browser_localStorage_privatestorageevent.js
@@ -0,0 +1,76 @@
+add_task(function *() {
+ var privWin = OpenBrowserWindow({private: true});
+ yield new privWin.Promise(resolve => {
+ privWin.addEventListener('load', function onLoad() {
+ privWin.removeEventListener('load', onLoad, false);
+ resolve();
+ });
+ });
+
+ var pubWin = OpenBrowserWindow({private: false});
+ yield new pubWin.Promise(resolve => {
+ pubWin.addEventListener('load', function onLoad() {
+ pubWin.removeEventListener('load', onLoad, false);
+ resolve();
+ });
+ });
+
+ var URL = "http://mochi.test:8888/browser/dom/tests/browser/page_privatestorageevent.html";
+
+ var privTab = privWin.gBrowser.addTab(URL);
+ yield BrowserTestUtils.browserLoaded(privWin.gBrowser.getBrowserForTab(privTab));
+ var privBrowser = gBrowser.getBrowserForTab(privTab);
+
+ var pubTab = pubWin.gBrowser.addTab(URL);
+ yield BrowserTestUtils.browserLoaded(pubWin.gBrowser.getBrowserForTab(pubTab));
+ var pubBrowser = gBrowser.getBrowserForTab(pubTab);
+
+ // Check if pubWin can see privWin's storage events
+ yield ContentTask.spawn(pubBrowser, null, function(opts) {
+ content.window.gotStorageEvent = false;
+ content.window.addEventListener('storage', ev => {
+ content.window.gotStorageEvent = true;
+ });
+ });
+
+ yield ContentTask.spawn(privBrowser, null, function(opts) {
+ content.window.localStorage['key'] = 'ablooabloo';
+ });
+
+ let pubSaw = yield ContentTask.spawn(pubBrowser, null, function(opts) {
+ return content.window.gotStorageEvent;
+ });
+
+ ok(!pubSaw, "pubWin shouldn't be able to see privWin's storage events");
+
+ yield ContentTask.spawn(privBrowser, null, function(opts) {
+ content.window.gotStorageEvent = false;
+ content.window.addEventListener('storage', ev => {
+ content.window.gotStorageEvent = true;
+ });
+ });
+
+ // Check if privWin can see pubWin's storage events
+ yield ContentTask.spawn(privBrowser, null, function(opts) {
+ content.window.gotStorageEvent = false;
+ content.window.addEventListener('storage', ev => {
+ content.window.gotStorageEvent = true;
+ });
+ });
+
+ yield ContentTask.spawn(pubBrowser, null, function(opts) {
+ content.window.localStorage['key'] = 'ablooabloo';
+ });
+
+ let privSaw = yield ContentTask.spawn(privBrowser, null, function(opts) {
+ return content.window.gotStorageEvent;
+ });
+
+ ok(!privSaw, "privWin shouldn't be able to see pubWin's storage events");
+
+ yield BrowserTestUtils.removeTab(privTab);
+ yield BrowserTestUtils.closeWindow(privWin);
+
+ yield BrowserTestUtils.removeTab(pubTab);
+ yield BrowserTestUtils.closeWindow(pubWin);
+});
diff --git a/dom/tests/browser/browser_test__content.js b/dom/tests/browser/browser_test__content.js
new file mode 100644
index 000000000..b06233527
--- /dev/null
+++ b/dom/tests/browser/browser_test__content.js
@@ -0,0 +1,4 @@
+function test() {
+ is(window._content, window.content,
+ "_content needs to work, since extensions use it");
+}
diff --git a/dom/tests/browser/browser_test_new_window_from_content.js b/dom/tests/browser/browser_test_new_window_from_content.js
new file mode 100644
index 000000000..8b190287c
--- /dev/null
+++ b/dom/tests/browser/browser_test_new_window_from_content.js
@@ -0,0 +1,202 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/*
+ We have three ways for content to open new windows:
+ 1) window.open (with the default features)
+ 2) window.open (with non-default features)
+ 3) target="_blank" in <a> tags
+
+ We also have two prefs that modify our window opening behaviours:
+
+ 1) browser.link.open_newwindow
+
+ This has a numeric value that allows us to set our window-opening behaviours from
+ content in three ways:
+ 1) Open links that would normally open a new window in the current tab
+ 2) Open links that would normally open a new window in a new window
+ 3) Open links that would normally open a new window in a new tab (default)
+
+ 2) browser.link.open_newwindow.restriction
+
+ This has a numeric value that allows us to fine tune the browser.link.open_newwindow
+ pref so that it can discriminate between different techniques for opening windows.
+
+ 0) All things that open windows should behave according to browser.link.open_newwindow.
+ 1) No things that open windows should behave according to browser.link.open_newwindow
+ (essentially rendering browser.link.open_newwindow inert).
+ 2) Most things that open windows should behave according to browser.link.open_newwindow,
+ _except_ for window.open calls with the "feature" parameter. This will open in a new
+ window regardless of what browser.link.open_newwindow is set at. (default)
+
+ This file attempts to test each window opening technique against all possible settings for
+ each preference.
+*/
+
+Cu.import("resource://gre/modules/Task.jsm");
+
+const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+const kContentDoc = "http://www.example.com/browser/dom/tests/browser/test_new_window_from_content_child.html";
+const kNewWindowPrefKey = "browser.link.open_newwindow";
+const kNewWindowRestrictionPrefKey = "browser.link.open_newwindow.restriction";
+const kSameTab = "same tab";
+const kNewWin = "new window";
+const kNewTab = "new tab";
+
+SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
+
+requestLongerTimeout(3);
+
+// The following "matrices" represent the result of content attempting to
+// open a window with window.open with the default feature set. The key of
+// the kWinOpenDefault object represents the value of browser.link.open_newwindow.
+// The value for each key is an array that represents the result (either opening
+// the link in the same tab, a new window, or a new tab), where the index of each
+// result maps to the browser.link.open_newwindow.restriction pref. I've tried
+// to illustrate this more clearly in the kWinOpenDefault object.
+const kWinOpenDefault = {
+// open_newwindow.restriction
+// 0 1 2
+// open_newwindow
+ 1: [kSameTab, kNewWin, kSameTab],
+ 2: [kNewWin, kNewWin, kNewWin],
+ 3: [kNewTab, kNewWin, kNewTab],
+};
+
+const kWinOpenNonDefault = {
+ 1: [kSameTab, kNewWin, kNewWin],
+ 2: [kNewWin, kNewWin, kNewWin],
+ 3: [kNewTab, kNewWin, kNewWin],
+};
+
+const kTargetBlank = {
+ 1: [kSameTab, kSameTab, kSameTab],
+ 2: [kNewWin, kNewWin, kNewWin],
+ 3: [kNewTab, kNewTab, kNewTab],
+};
+
+// We'll be changing these preferences a lot, so we'll stash their original
+// values and make sure we restore them at the end of the test.
+var originalNewWindowPref = Services.prefs.getIntPref(kNewWindowPrefKey);
+var originalNewWindowRestrictionPref =
+ Services.prefs.getIntPref(kNewWindowRestrictionPrefKey);
+
+registerCleanupFunction(function() {
+ Services.prefs.setIntPref(kNewWindowPrefKey, originalNewWindowPref);
+ Services.prefs.setIntPref(kNewWindowRestrictionPrefKey,
+ originalNewWindowRestrictionPref);
+});
+
+/**
+ * For some expectation when a link is clicked, creates and
+ * returns a Promise that resolves when that expectation is
+ * fulfilled. For example, aExpectation might be kSameTab, which
+ * will cause this function to return a Promise that resolves when
+ * the current tab attempts to browse to about:blank.
+ *
+ * This function also takes care of cleaning up once the result has
+ * occurred - for example, if a new window was opened, this function
+ * closes it before resolving.
+ *
+ * @param aBrowser the <xul:browser> with the test document
+ * @param aExpectation one of kSameTab, kNewWin, or kNewTab.
+ * @return a Promise that resolves when the expectation is fulfilled,
+ * and cleaned up after.
+ */
+function prepareForResult(aBrowser, aExpectation) {
+ let expectedSpec = kContentDoc.replace(/[^\/]*$/, "dummy.html");
+ switch(aExpectation) {
+ case kSameTab:
+ return Task.spawn(function*() {
+ yield BrowserTestUtils.browserLoaded(aBrowser);
+ is(aBrowser.currentURI.spec, expectedSpec, "Should be at dummy.html");
+ // Now put the browser back where it came from
+ yield BrowserTestUtils.loadURI(aBrowser, kContentDoc);
+ yield BrowserTestUtils.browserLoaded(aBrowser);
+ });
+ break;
+ case kNewWin:
+ return Task.spawn(function*() {
+ let newWin = yield BrowserTestUtils.waitForNewWindow();
+ let newBrowser = newWin.gBrowser.selectedBrowser;
+ yield BrowserTestUtils.browserLoaded(newBrowser);
+ is(newBrowser.currentURI.spec, expectedSpec, "Should be at dummy.html");
+ yield BrowserTestUtils.closeWindow(newWin);
+ });
+ break;
+ case kNewTab:
+ return Task.spawn(function*() {
+ let newTab = yield BrowserTestUtils.waitForNewTab(gBrowser);
+ is(newTab.linkedBrowser.currentURI.spec, expectedSpec,
+ "Should be at dummy.html");
+ yield BrowserTestUtils.removeTab(newTab);
+ });
+ break;
+ default:
+ ok(false, "prepareForResult can't handle an expectation of " + aExpectation)
+ return;
+ }
+
+ return deferred.promise;
+}
+
+/**
+ * Ensure that clicks on a link with ID aLinkID cause us to
+ * perform as specified in the supplied aMatrix (kWinOpenDefault,
+ * for example).
+ *
+ * @param aLinkSelector a selector for the link within the testing page to click.
+ * @param aMatrix a testing matrix for the
+ * browser.link.open_newwindow and browser.link.open_newwindow.restriction
+ * prefs to test against. See kWinOpenDefault for an example.
+ */
+function testLinkWithMatrix(aLinkSelector, aMatrix) {
+ return BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: kContentDoc,
+ }, function*(browser) {
+ // This nested for-loop is unravelling the matrix const
+ // we set up, and gives us three things through each tick
+ // of the inner loop:
+ // 1) newWindowPref: a browser.link.open_newwindow pref to try
+ // 2) newWindowRestPref: a browser.link.open_newwindow.restriction pref to try
+ // 3) expectation: what we expect the click outcome on this link to be,
+ // which will either be kSameTab, kNewWin or kNewTab.
+ for (let newWindowPref in aMatrix) {
+ let expectations = aMatrix[newWindowPref];
+ for (let i = 0; i < expectations.length; ++i) {
+ let newWindowRestPref = i;
+ let expectation = expectations[i];
+
+ Services.prefs.setIntPref("browser.link.open_newwindow", newWindowPref);
+ Services.prefs.setIntPref("browser.link.open_newwindow.restriction", newWindowRestPref);
+ info("Clicking on " + aLinkSelector);
+ info("Testing with browser.link.open_newwindow = " + newWindowPref + " and " +
+ "browser.link.open_newwindow.restriction = " + newWindowRestPref);
+ info("Expecting: " + expectation);
+ let resultPromise = prepareForResult(browser, expectation);
+ BrowserTestUtils.synthesizeMouseAtCenter(aLinkSelector, {}, browser);
+ yield resultPromise;
+ info("Got expectation: " + expectation);
+ }
+ }
+ });
+}
+
+add_task(function* test_window_open_with_defaults() {
+ yield testLinkWithMatrix("#winOpenDefault", kWinOpenDefault);
+});
+
+add_task(function* test_window_open_with_non_defaults() {
+ yield testLinkWithMatrix("#winOpenNonDefault", kWinOpenNonDefault);
+});
+
+add_task(function* test_window_open_dialog() {
+ yield testLinkWithMatrix("#winOpenDialog", kWinOpenNonDefault);
+});
+
+add_task(function* test_target__blank() {
+ yield testLinkWithMatrix("#targetBlank", kTargetBlank);
+});
diff --git a/dom/tests/browser/browser_test_toolbars_visibility.js b/dom/tests/browser/browser_test_toolbars_visibility.js
new file mode 100644
index 000000000..d7649793c
--- /dev/null
+++ b/dom/tests/browser/browser_test_toolbars_visibility.js
@@ -0,0 +1,224 @@
+// Tests that toolbars have proper visibility when opening a new window
+// in either content or chrome context.
+
+const ROOT = "http://www.example.com/browser/dom/tests/browser/";
+const CONTENT_PAGE = ROOT + "test_new_window_from_content_child.html";
+const TARGET_PAGE = ROOT + "dummy.html";
+
+/**
+ * This function retrieves the visibility state of the toolbars of a
+ * window within the content context.
+ *
+ * @param aBrowser (<xul:browser>)
+ * The browser to query for toolbar visibility states
+ * @returns Promise
+ * A promise that resolves when the toolbar state is retrieved
+ * within the content context, which value is an object that holds
+ * the visibility state of the toolbars
+ */
+function getToolbarsFromBrowserContent(aBrowser) {
+ return ContentTask.spawn(aBrowser, {}, function*() {
+ return {
+ toolbar: content.toolbar.visible,
+ menubar: content.menubar.visible,
+ personalbar: content.personalbar.visible,
+ statusbar: content.statusbar.visible,
+ locationbar: content.locationbar.visible,
+ };
+ });
+}
+
+/**
+ * This function retrieves the visibility state of the toolbars of a
+ * window within the chrome context.
+ *
+ * @param win
+ * the chrome privileged window
+ * @returns object
+ * an object that holds the visibility state of the toolbars
+ */
+function getToolbarsFromWindowChrome(win) {
+ return {
+ toolbar: win.toolbar.visible,
+ menubar: win.menubar.visible,
+ personalbar: win.personalbar.visible,
+ statusbar: win.statusbar.visible,
+ locationbar: win.locationbar.visible,
+ }
+}
+
+/**
+ * Tests toolbar visibility when opening a window with default parameters.
+ *
+ * @param toolbars
+ * the visibility state of the toolbar elements
+ */
+function testDefaultToolbars(toolbars) {
+ ok(toolbars.locationbar,
+ "locationbar should be visible on default window.open()");
+ ok(toolbars.menubar,
+ "menubar be visible on default window.open()");
+ ok(toolbars.personalbar,
+ "personalbar should be visible on default window.open()");
+ ok(toolbars.statusbar,
+ "statusbar should be visible on default window.open()");
+ ok(toolbars.toolbar,
+ "toolbar should be visible on default window.open()");
+}
+
+/**
+ * Tests toolbar visibility when opening a window with non default parameters
+ * on the content context.
+ *
+ * Ensure that locationbar can't be hidden in the content context, see bug#337344.
+ *
+ * @param toolbars
+ * the visibility state of the toolbar elements
+ */
+function testNonDefaultContentToolbars(toolbars) {
+ // Locationbar should always be visible on content context
+ ok(toolbars.locationbar,
+ "locationbar should be visible even with location=no");
+ ok(!toolbars.menubar,
+ "menubar shouldn't be visible when menubar=no");
+ ok(!toolbars.personalbar,
+ "personalbar shouldn't be visible when personalbar=no");
+ // statusbar will report visible=true even when it's hidden because of bug#55820
+ todo(!toolbars.statusbar,
+ "statusbar shouldn't be visible when status=no");
+ ok(!toolbars.toolbar,
+ "toolbar shouldn't be visible when toolbar=no");
+}
+
+/**
+ * Tests toolbar visibility when opening a window with non default parameters
+ * on the chrome context.
+ *
+ * @param toolbars
+ * the visibility state of the toolbar elements
+ */
+function testNonDefaultChromeToolbars(toolbars) {
+ // None of the toolbars should be visible if hidden with chrome privileges
+ ok(!toolbars.locationbar,
+ "locationbar should not be visible with location=no");
+ ok(!toolbars.menubar,
+ "menubar should not be visible with menubar=no");
+ ok(!toolbars.personalbar,
+ "personalbar should not be visible with personalbar=no");
+ ok(!toolbars.statusbar,
+ "statusbar should not be visible with status=no");
+ ok(!toolbars.toolbar,
+ "toolbar should not be visible with toolbar=no");
+}
+
+/**
+ * Ensure that toolbars of a window opened in the content context have the
+ * correct visibility.
+ *
+ * A window opened with default parameters should have all toolbars visible.
+ *
+ * A window opened with "location=no, personalbar=no, toolbar=no, scrollbars=no,
+ * menubar=no, status=no", should only have location visible.
+ */
+add_task(function*() {
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: CONTENT_PAGE,
+ }, function*(browser) {
+ // First, call the default window.open() which will open a new tab
+ let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#winOpenDefault", {}, browser);
+ let tab = yield newTabPromise;
+
+ // Check that all toolbars are visible
+ let toolbars = yield getToolbarsFromBrowserContent(gBrowser.selectedBrowser);
+ testDefaultToolbars(toolbars);
+
+ // Cleanup
+ yield BrowserTestUtils.removeTab(tab);
+
+ // Now let's open a window with toolbars hidden
+ let winPromise = BrowserTestUtils.waitForNewWindow();
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#winOpenNonDefault", {}, browser);
+ let popupWindow = yield winPromise;
+
+ let popupBrowser = popupWindow.gBrowser.selectedBrowser;
+ yield BrowserTestUtils.browserLoaded(popupBrowser);
+
+ // Test toolbars visibility
+ let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser);
+ testNonDefaultContentToolbars(popupToolbars);
+
+ // Ensure that chrome toolbars agree with content
+ let chromeToolbars = getToolbarsFromWindowChrome(popupWindow);
+ testNonDefaultContentToolbars(chromeToolbars);
+
+ // Close the new window
+ yield BrowserTestUtils.closeWindow(popupWindow);
+ });
+});
+
+/**
+ * Ensure that toolbars of a window opened to about:blank in the content context
+ * have the correct visibility.
+ *
+ * A window opened with "location=no, personalbar=no, toolbar=no, scrollbars=no,
+ * menubar=no, status=no", should only have location visible.
+ */
+add_task(function*() {
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: CONTENT_PAGE,
+ }, function*(browser) {
+ // Open a blank window with toolbars hidden
+ let winPromise = BrowserTestUtils.waitForNewWindow();
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#winOpenNoURLNonDefault", {}, browser);
+ let popupWindow = yield winPromise;
+
+ // No need to wait for this window to load, since it's loading about:blank
+ let popupBrowser = popupWindow.gBrowser.selectedBrowser;
+ let popupToolbars = yield getToolbarsFromBrowserContent(popupBrowser);
+ testNonDefaultContentToolbars(popupToolbars);
+
+ // Ensure that chrome toolbars agree with content
+ let chromeToolbars = getToolbarsFromWindowChrome(popupWindow);
+ testNonDefaultContentToolbars(chromeToolbars);
+
+ // Close the new window
+ yield BrowserTestUtils.closeWindow(popupWindow);
+ });
+});
+
+/**
+ * Ensure that toolbars of a window opened in the chrome context have the
+ * correct visibility.
+ *
+ * A window opened with default parameters should have all toolbars visible.
+ *
+ * A window opened with "location=no, personalbar=no, toolbar=no, scrollbars=no,
+ * menubar=no, status=no", should not have any toolbar visible.
+ */
+add_task(function* () {
+ // First open a default window from this chrome context
+ let defaultWindowPromise = BrowserTestUtils.waitForNewWindow();
+ window.open(TARGET_PAGE, "_blank");
+ let defaultWindow = yield defaultWindowPromise;
+
+ // Check that all toolbars are visible
+ let toolbars = getToolbarsFromWindowChrome(defaultWindow);
+ testDefaultToolbars(toolbars);
+
+ // Now lets open a window with toolbars hidden from this chrome context
+ let features = "location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no";
+ let popupWindowPromise = BrowserTestUtils.waitForNewWindow();
+ window.open(TARGET_PAGE, "_blank", features);
+ let popupWindow = yield popupWindowPromise;
+
+ // Test none of the tooolbars are visible
+ let hiddenToolbars = getToolbarsFromWindowChrome(popupWindow);
+ testNonDefaultChromeToolbars(hiddenToolbars);
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(defaultWindow);
+ yield BrowserTestUtils.closeWindow(popupWindow);
+});
diff --git a/dom/tests/browser/browser_xhr_sandbox.js b/dom/tests/browser/browser_xhr_sandbox.js
new file mode 100644
index 000000000..d80fee9f8
--- /dev/null
+++ b/dom/tests/browser/browser_xhr_sandbox.js
@@ -0,0 +1,50 @@
+// This code is evaluated in a sandbox courtesy of toSource();
+var sandboxCode = (function() {
+ let req = new XMLHttpRequest();
+ req.open("GET", "http://mochi.test:8888/browser/dom/tests/browser/", true);
+ req.onreadystatechange = function() {
+ if (req.readyState === 4) {
+ // If we get past the problem above, we end up with a req.status of zero
+ // (ie, blocked due to CORS) even though we are fetching from the same
+ // origin as the window itself.
+ let result;
+ if (req.status != 200) {
+ result = "ERROR: got request status of " + req.status;
+ } else if (req.responseText.length == 0) {
+ result = "ERROR: got zero byte response text";
+ } else {
+ result = "ok";
+ }
+ postMessage({result: result}, "*");
+ }
+ };
+ req.send(null);
+}).toSource() + "();";
+
+function test() {
+ waitForExplicitFinish();
+ let appShell = Cc["@mozilla.org/appshell/appShellService;1"]
+ .getService(Ci.nsIAppShellService);
+ let doc = appShell.hiddenDOMWindow.document;
+ let frame = doc.createElement("iframe");
+ frame.setAttribute("type", "content");
+ frame.setAttribute("src", "http://mochi.test:8888/browser/dom/tests/browser/browser_xhr_sandbox.js");
+
+ frame.addEventListener("load", function () {
+ let workerWindow = frame.contentWindow;
+ workerWindow.addEventListener("message", function(evt) {
+ is(evt.data.result, "ok", "check the sandbox code was happy");
+ frame.remove();
+ finish();
+ }, true);
+ let sandbox = new Cu.Sandbox(workerWindow);
+ // inject some functions from the window into the sandbox.
+ // postMessage so the async code in the sandbox can report a result.
+ sandbox.importFunction(workerWindow.postMessage.bind(workerWindow), "postMessage");
+ sandbox.importFunction(workerWindow.XMLHttpRequest, "XMLHttpRequest");
+ Cu.evalInSandbox(sandboxCode, sandbox, "1.8");
+ }, true);
+
+ let container = doc.body ? doc.body : doc.documentElement;
+ container.appendChild(frame);
+}
diff --git a/dom/tests/browser/dummy.html b/dom/tests/browser/dummy.html
new file mode 100644
index 000000000..1a87e2840
--- /dev/null
+++ b/dom/tests/browser/dummy.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Dummy test page</title>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
+</head>
+<body>
+<p>Dummy test page</p>
+</body>
+</html>
diff --git a/dom/tests/browser/geo_leak_test.html b/dom/tests/browser/geo_leak_test.html
new file mode 100644
index 000000000..fb3fabac4
--- /dev/null
+++ b/dom/tests/browser/geo_leak_test.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<title>Geolocation incomplete position leak test</title>
+<script type="text/javascript">
+
+function successCallback(position) {}
+function errorCallback() {}
+
+function init() {
+ navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
+}
+</script>
+</head>
+<body onload="init()">
+</body>
+</html>
diff --git a/dom/tests/browser/page_privatestorageevent.html b/dom/tests/browser/page_privatestorageevent.html
new file mode 100644
index 000000000..90c2184ae
--- /dev/null
+++ b/dom/tests/browser/page_privatestorageevent.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+la la la la
+</body>
+</html>
diff --git a/dom/tests/browser/position.html b/dom/tests/browser/position.html
new file mode 100644
index 000000000..d5b665d8e
--- /dev/null
+++ b/dom/tests/browser/position.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+<head>
+ <script type="text/javascript">
+ var result = null;
+
+ function handlePosition(position) {
+ result.innerHTML = position.coords.latitude + " " + position.coords.longitude;
+ }
+
+ function handleError(error) {
+ result.innerHTML = error.message;
+ }
+
+ function init() {
+ result = document.getElementById("result");
+
+ if (navigator.geolocation)
+ navigator.geolocation.getCurrentPosition(handlePosition, handleError);
+ else
+ result.innerHTML = "not available";
+ }
+
+ </script>
+</head>
+<body onload="init()">
+ <p id="result">location...</p>
+</body>
+</html>
diff --git a/dom/tests/browser/test-console-api.html b/dom/tests/browser/test-console-api.html
new file mode 100644
index 000000000..4e7d75708
--- /dev/null
+++ b/dom/tests/browser/test-console-api.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+ <title>Console API test page</title>
+ <script type="text/javascript">
+ window.foobar585956c = function(a) {
+ console.trace();
+ return a+"c";
+ };
+
+ function foobar585956b(a) {
+ return foobar585956c(a+"b");
+ }
+
+ function foobar585956a(omg) {
+ return foobar585956b(omg + "a");
+ }
+
+ function foobar646025(omg) {
+ console.log(omg, "o", "d");
+ }
+
+ function startTimer(timer) {
+ console.time(timer);
+ }
+
+ function stopTimer(timer) {
+ console.timeEnd(timer);
+ }
+
+ function namelessTimer() {
+ console.time();
+ console.timeEnd();
+ }
+
+ function test() {
+ var str = "Test Message."
+ console.foobar(str); // if this throws, we don't execute following funcs
+ console.log(str);
+ console.info(str);
+ console.warn(str);
+ console.error(str);
+ console.exception(str);
+ console.assert(false, str);
+ console.count(str);
+ }
+
+ function testGroups() {
+ console.groupCollapsed("a", "group");
+ console.group("b", "group");
+ console.groupEnd("b", "group");
+ }
+
+ function nativeCallback() {
+ new Promise(function(resolve, reject) { resolve(42); }).then(console.log.bind(console));
+ }
+
+ function timeStamp(val) {
+ console.timeStamp(val);
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Console API Test Page</h1>
+ <button onclick="test();">Log stuff</button>
+ <button id="test-trace" onclick="foobar585956a('omg');">Test trace</button>
+ <button id="test-location" onclick="foobar646025('omg');">Test location</button>
+ <button id="test-nativeCallback" onclick="nativeCallback();">Test nativeCallback</button>
+ <button id="test-groups" onclick="testGroups();">Test groups</button>
+ <button id="test-time" onclick="startTimer('foo');">Test time</button>
+ <button id="test-timeEnd" onclick="stopTimer('foo');">Test timeEnd</button>
+ <button id="test-namelessTimer" onclick="namelessTimer();">Test namelessTimer</button>
+ <button id="test-timeStamp" onclick="timeStamp('!!!')">Test timeStamp</button>
+ <button id="test-emptyTimeStamp" onclick="timeStamp();">Test emptyTimeStamp</button>
+ </body>
+</html>
diff --git a/dom/tests/browser/test_bug1004814.html b/dom/tests/browser/test_bug1004814.html
new file mode 100644
index 000000000..64d056ecf
--- /dev/null
+++ b/dom/tests/browser/test_bug1004814.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Console API test bug 1004814</title>
+ </head>
+ <body>
+ <script>
+
+var w = new Worker('worker_bug1004814.js');
+w.postMessage(true);
+
+ </script>
+ </body>
+</html>
diff --git a/dom/tests/browser/test_largeAllocation.html b/dom/tests/browser/test_largeAllocation.html
new file mode 100644
index 000000000..3a117af81
--- /dev/null
+++ b/dom/tests/browser/test_largeAllocation.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<html>
+ <body>Loaded in a new process!</body>
+</html>
diff --git a/dom/tests/browser/test_largeAllocation.html^headers^ b/dom/tests/browser/test_largeAllocation.html^headers^
new file mode 100644
index 000000000..672836b61
--- /dev/null
+++ b/dom/tests/browser/test_largeAllocation.html^headers^
@@ -0,0 +1 @@
+Large-Allocation: 0 \ No newline at end of file
diff --git a/dom/tests/browser/test_new_window_from_content_child.html b/dom/tests/browser/test_new_window_from_content_child.html
new file mode 100644
index 000000000..0d6f8eb80
--- /dev/null
+++ b/dom/tests/browser/test_new_window_from_content_child.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>Test popup window opening behaviour</title>
+</head>
+<body>
+ <p><a id="winOpenDefault" href="#" onclick="return openWindow();">Open a new window via window.open with default features.</a></p>
+ <p><a id="winOpenNonDefault" href="#" onclick="return openWindow('resizable=no, location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no, directories=no, height=100, width=500');">Open a new window via window.open with non-default features.</a></p>
+ <p><a id="winOpenDialog" href="#" onclick="return openWindow('dialog=yes');">Open a new window via window.open with dialog=1.</a></p>
+ <p><a id="winOpenNoURLNonDefault" href="#" onclick="return openBlankWindow('location=no, toolbar=no, height=100, width=100');">Open a blank new window via window.open with non-default features.</a></p>
+ <p><a id="targetBlank" href="dummy.html" target="_blank">Open a new window via target="_blank".</a></p>
+</body>
+</html>
+
+<script>
+function openWindow(aFeatures="") {
+ window.open("dummy.html", "_blank", aFeatures);
+ return false;
+}
+
+function openBlankWindow(aFeatures="") {
+ window.open("", "_blank", aFeatures);
+ return false;
+}
+</script>
diff --git a/dom/tests/browser/worker_bug1004814.js b/dom/tests/browser/worker_bug1004814.js
new file mode 100644
index 000000000..f49fe8dc8
--- /dev/null
+++ b/dom/tests/browser/worker_bug1004814.js
@@ -0,0 +1,6 @@
+onmessage = function(evt) {
+ console.time('bug1004814');
+ setTimeout(function() {
+ console.timeEnd('bug1004814');
+ }, 200);
+}