diff options
Diffstat (limited to 'dom/tests/browser')
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); +} |