diff options
Diffstat (limited to 'addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js')
-rw-r--r-- | addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js | 1127 |
1 files changed, 0 insertions, 1127 deletions
diff --git a/addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js b/addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js deleted file mode 100644 index 5eddb826a..000000000 --- a/addon-sdk/source/test/addons/e10s-content/lib/test-content-worker.js +++ /dev/null @@ -1,1127 +0,0 @@ -/* 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"; - -// Skipping due to window creation being unsupported in Fennec -module.metadata = { - engines: { - 'Firefox': '*' - } -}; - -const { Cc, Ci } = require("chrome"); -const { on } = require("sdk/event/core"); -const { setTimeout } = require("sdk/timers"); -const { LoaderWithHookedConsole, Loader } = require("sdk/test/loader"); -const { Worker } = require("sdk/content/worker"); -const { close } = require("sdk/window/helpers"); -const { set: setPref } = require("sdk/preferences/service"); -const { isArray } = require("sdk/lang/type"); -const { URL } = require('sdk/url'); -const fixtures = require("./fixtures"); -const system = require("sdk/system/events"); - -const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings"; - -const DEFAULT_CONTENT_URL = "data:text/html;charset=utf-8,foo"; - -const WINDOW_SCRIPT_URL = "data:text/html;charset=utf-8," + - "<script>window.addEventListener('message', function (e) {" + - " if (e.data === 'from -> content-script')" + - " window.postMessage('from -> window', '*');" + - "});</script>"; - -function makeWindow() { - let content = - "<?xml version=\"1.0\"?>" + - "<window " + - "xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">" + - "<script>var documentValue=true;</script>" + - "</window>"; - var url = "data:application/vnd.mozilla.xul+xml;charset=utf-8," + - encodeURIComponent(content); - var features = ["chrome", "width=10", "height=10"]; - - return Cc["@mozilla.org/embedcomp/window-watcher;1"]. - getService(Ci.nsIWindowWatcher). - openWindow(null, url, null, features.join(","), null); -} - -// Listen for only first one occurence of DOM event -function listenOnce(node, eventName, callback) { - node.addEventListener(eventName, function onevent(event) { - node.removeEventListener(eventName, onevent, true); - callback(node); - }, true); -} - -// Load a given url in a given browser and fires the callback when it is loaded -function loadAndWait(browser, url, callback) { - listenOnce(browser, "load", callback); - // We have to wait before calling `loadURI` otherwise, if we call - // `loadAndWait` during browser load event, the history will be broken - setTimeout(function () { - browser.loadURI(url); - }, 0); -} - -// Returns a test function that will automatically open a new chrome window -// with a <browser> element loaded on a given content URL -// The callback receive 3 arguments: -// - test: reference to the jetpack test object -// - browser: a reference to the <browser> xul node -// - done: a callback to call when test is over -function WorkerTest(url, callback) { - return function testFunction(assert, done) { - let chromeWindow = makeWindow(); - chromeWindow.addEventListener("load", function onload() { - chromeWindow.removeEventListener("load", onload, true); - let browser = chromeWindow.document.createElement("browser"); - browser.setAttribute("type", "content"); - chromeWindow.document.documentElement.appendChild(browser); - // Wait for about:blank load event ... - listenOnce(browser, "load", function onAboutBlankLoad() { - // ... before loading the expected doc and waiting for its load event - loadAndWait(browser, url, function onDocumentLoaded() { - callback(assert, browser, function onTestDone() { - - close(chromeWindow).then(done); - }); - }); - }); - }, true); - }; -} - -exports["test:sample"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - assert.notEqual(browser.contentWindow.location.href, "about:blank", - "window is now on the right document"); - - let window = browser.contentWindow - let worker = Worker({ - window: window, - contentScript: "new " + function WorkerScope() { - // window is accessible - let myLocation = window.location.toString(); - self.on("message", function(data) { - if (data == "hi!") - self.postMessage("bye!"); - }); - }, - contentScriptWhen: "ready", - onMessage: function(msg) { - assert.equal("bye!", msg); - assert.equal(worker.url, window.location.href, - "worker.url still works"); - done(); - } - }); - - assert.equal(worker.url, window.location.href, - "worker.url works"); - assert.equal(worker.contentURL, window.location.href, - "worker.contentURL works"); - worker.postMessage("hi!"); - } -); - -exports["test:emit"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - // Validate self.on and self.emit - self.port.on("addon-to-content", function (data) { - self.port.emit("content-to-addon", data); - }); - - // Check for global pollution - //if (typeof on != "undefined") - // self.postMessage("`on` is in globals"); - if (typeof once != "undefined") - self.postMessage("`once` is in globals"); - if (typeof emit != "undefined") - self.postMessage("`emit` is in globals"); - - }, - onMessage: function(msg) { - assert.fail("Got an unexpected message : "+msg); - } - }); - - // Validate worker.port - worker.port.on("content-to-addon", function (data) { - assert.equal(data, "event data"); - done(); - }); - worker.port.emit("addon-to-content", "event data"); - } -); - -exports["test:emit hack message"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - // Validate self.port - self.port.on("message", function (data) { - self.port.emit("message", data); - }); - // We should not receive message on self, but only on self.port - self.on("message", function (data) { - self.postMessage("message", data); - }); - }, - onError: function(e) { - assert.fail("Got exception: "+e); - } - }); - - worker.port.on("message", function (data) { - assert.equal(data, "event data"); - done(); - }); - worker.on("message", function (data) { - assert.fail("Got an unexpected message : "+msg); - }); - worker.port.emit("message", "event data"); - } -); - -exports["test:n-arguments emit"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let repeat = 0; - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - // Validate self.on and self.emit - self.port.on("addon-to-content", function (a1, a2, a3) { - self.port.emit("content-to-addon", a1, a2, a3); - }); - } - }); - - // Validate worker.port - worker.port.on("content-to-addon", function (arg1, arg2, arg3) { - if (!repeat++) { - this.emit("addon-to-content", "first argument", "second", "third"); - } else { - assert.equal(arg1, "first argument"); - assert.equal(arg2, "second"); - assert.equal(arg3, "third"); - done(); - } - }); - worker.port.emit("addon-to-content", "first argument", "second", "third"); - } -); - -exports["test:post-json-values-only"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - self.on("message", function (message) { - self.postMessage([ message.fun === undefined, - typeof message.w, - message.w && "port" in message.w, - message.w._url, - Array.isArray(message.array), - JSON.stringify(message.array)]); - }); - } - }); - - // Validate worker.onMessage - let array = [1, 2, 3]; - worker.on("message", function (message) { - assert.ok(message[0], "function becomes undefined"); - assert.equal(message[1], "object", "object stays object"); - assert.ok(message[2], "object's attributes are enumerable"); - assert.equal(message[3], DEFAULT_CONTENT_URL, - "jsonable attributes are accessible"); - // See bug 714891, Arrays may be broken over compartements: - assert.ok(message[4], "Array keeps being an array"); - assert.equal(message[5], JSON.stringify(array), - "Array is correctly serialized"); - done(); - }); - // Add a new url property sa the Class function used by - // Worker doesn't set enumerables to true for non-functions - worker._url = DEFAULT_CONTENT_URL; - - worker.postMessage({ fun: function () {}, w: worker, array: array }); - } -); - -exports["test:emit-json-values-only"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - // Validate self.on and self.emit - self.port.on("addon-to-content", function (fun, w, obj, array) { - self.port.emit("content-to-addon", [ - fun === null, - typeof w, - "port" in w, - w._url, - "fun" in obj, - Object.keys(obj.dom).length, - Array.isArray(array), - JSON.stringify(array) - ]); - }); - } - }); - - // Validate worker.port - let array = [1, 2, 3]; - worker.port.on("content-to-addon", function (result) { - assert.ok(result[0], "functions become null"); - assert.equal(result[1], "object", "objects stay objects"); - assert.ok(result[2], "object's attributes are enumerable"); - assert.equal(result[3], DEFAULT_CONTENT_URL, - "json attribute is accessible"); - assert.ok(!result[4], "function as object attribute is removed"); - assert.equal(result[5], 0, "DOM nodes are converted into empty object"); - // See bug 714891, Arrays may be broken over compartments: - assert.ok(result[6], "Array keeps being an array"); - assert.equal(result[7], JSON.stringify(array), - "Array is correctly serialized"); - done(); - }); - - let obj = { - fun: function () {}, - dom: browser.contentWindow.document.createElement("div") - }; - // Add a new url property sa the Class function used by - // Worker doesn't set enumerables to true for non-functions - worker._url = DEFAULT_CONTENT_URL; - worker.port.emit("addon-to-content", function () {}, worker, obj, array); - } -); - -exports["test:content is wrapped"] = WorkerTest( - "data:text/html;charset=utf-8,<script>var documentValue=true;</script>", - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - self.postMessage(!window.documentValue); - }, - contentScriptWhen: "ready", - onMessage: function(msg) { - assert.ok(msg, - "content script has a wrapped access to content document"); - done(); - } - }); - } -); - -// ContentWorker is not for chrome -/* -exports["test:chrome is unwrapped"] = function(assert, done) { - let window = makeWindow(); - - listenOnce(window, "load", function onload() { - - let worker = Worker({ - window: window, - contentScript: "new " + function WorkerScope() { - self.postMessage(window.documentValue); - }, - contentScriptWhen: "ready", - onMessage: function(msg) { - assert.ok(msg, - "content script has an unwrapped access to chrome document"); - close(window).then(done); - } - }); - - }); -} -*/ - -exports["test:nothing is leaked to content script"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - self.postMessage([ - "ContentWorker" in window, - "UNWRAP_ACCESS_KEY" in window, - "getProxyForObject" in window - ]); - }, - contentScriptWhen: "ready", - onMessage: function(list) { - assert.ok(!list[0], "worker API contrustor isn't leaked"); - assert.ok(!list[1], "Proxy API stuff isn't leaked 1/2"); - assert.ok(!list[2], "Proxy API stuff isn't leaked 2/2"); - done(); - } - }); - } -); - -exports["test:ensure console.xxx works in cs"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - const EXPECTED = ["time", "log", "info", "warn", "error", "error", "timeEnd"]; - - let calls = []; - let levels = []; - - system.on('console-api-log-event', onMessage); - - function onMessage({ subject }) { - calls.push(subject.wrappedJSObject.arguments[0]); - levels.push(subject.wrappedJSObject.level); - } - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - console.time("time"); - console.log("log"); - console.info("info"); - console.warn("warn"); - console.error("error"); - console.debug("debug"); - console.exception("error"); - console.timeEnd("timeEnd"); - self.postMessage(); - }, - onMessage: function() { - system.off('console-api-log-event', onMessage); - - assert.equal(JSON.stringify(calls), - JSON.stringify(EXPECTED), - "console methods have been called successfully, in expected order"); - - assert.equal(JSON.stringify(levels), - JSON.stringify(EXPECTED), - "console messages have correct log levels, in expected order"); - - done(); - } - }); - } -); - -exports["test:setTimeout works with string argument"] = WorkerTest( - "data:text/html;charset=utf-8,<script>var docVal=5;</script>", - function(assert, browser, done) { - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function ContentScriptScope() { - // must use "window.scVal" instead of "var csVal" - // since we are inside ContentScriptScope function. - // i'm NOT putting code-in-string inside code-in-string </YO DAWG> - window.csVal = 13; - setTimeout("self.postMessage([" + - "csVal, " + - "window.docVal, " + - "'ContentWorker' in window, " + - "'UNWRAP_ACCESS_KEY' in window, " + - "'getProxyForObject' in window, " + - "])", 1); - }, - contentScriptWhen: "ready", - onMessage: function([csVal, docVal, chrome1, chrome2, chrome3]) { - // test timer code is executed in the correct context - assert.equal(csVal, 13, "accessing content-script values"); - assert.notEqual(docVal, 5, "can't access document values (directly)"); - assert.ok(!chrome1 && !chrome2 && !chrome3, "nothing is leaked from chrome"); - done(); - } - }); - } -); - -exports["test:setInterval works with string argument"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let count = 0; - let worker = Worker({ - window: browser.contentWindow, - contentScript: "setInterval('self.postMessage(1)', 50)", - contentScriptWhen: "ready", - onMessage: function(one) { - count++; - assert.equal(one, 1, "got " + count + " message(s) from setInterval"); - if (count >= 3) done(); - } - }); - } -); - -exports["test:setInterval async Errors passed to .onError"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let count = 0; - let worker = Worker({ - window: browser.contentWindow, - contentScript: "setInterval(() => { throw Error('ubik') }, 50)", - contentScriptWhen: "ready", - onError: function(err) { - count++; - assert.equal(err.message, "ubik", - "error (correctly) propagated " + count + " time(s)"); - if (count >= 3) done(); - } - }); - } -); - -exports["test:setTimeout throws array, passed to .onError"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let worker = Worker({ - window: browser.contentWindow, - contentScript: "setTimeout(function() { throw ['array', 42] }, 1)", - contentScriptWhen: "ready", - onError: function(arr) { - assert.ok(isArray(arr), - "the type of thrown/propagated object is array"); - assert.ok(arr.length==2, - "the propagated thrown array is the right length"); - assert.equal(arr[1], 42, - "element inside the thrown array correctly propagated"); - done(); - } - }); - } -); - -exports["test:setTimeout string arg with SyntaxError to .onError"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let worker = Worker({ - window: browser.contentWindow, - contentScript: "setTimeout('syntax 123 error', 1)", - contentScriptWhen: "ready", - onError: function(err) { - assert.equal(err.name, "SyntaxError", - "received SyntaxError thrown from bad code in string argument to setTimeout"); - assert.ok('fileName' in err, - "propagated SyntaxError contains a fileName property"); - assert.ok('stack' in err, - "propagated SyntaxError contains a stack property"); - assert.equal(err.message, "missing ; before statement", - "propagated SyntaxError has the correct (helpful) message"); - assert.equal(err.lineNumber, 1, - "propagated SyntaxError was thrown on the right lineNumber"); - done(); - } - }); - } -); - -exports["test:setTimeout can't be cancelled by content"] = WorkerTest( - "data:text/html;charset=utf-8,<script>var documentValue=true;</script>", - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - let id = setTimeout(function () { - self.postMessage("timeout"); - }, 100); - unsafeWindow.eval("clearTimeout("+id+");"); - }, - contentScriptWhen: "ready", - onMessage: function(msg) { - assert.ok(msg, - "content didn't managed to cancel our setTimeout"); - done(); - } - }); - } -); - -exports["test:clearTimeout"] = WorkerTest( - "data:text/html;charset=utf-8,clear timeout", - function(assert, browser, done) { - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - let id1 = setTimeout(function() { - self.postMessage("failed"); - }, 10); - let id2 = setTimeout(function() { - self.postMessage("done"); - }, 100); - clearTimeout(id1); - }, - contentScriptWhen: "ready", - onMessage: function(msg) { - if (msg === "failed") { - assert.fail("failed to cancel timer"); - } else { - assert.pass("timer cancelled"); - done(); - } - } - }); - } -); - -exports["test:clearInterval"] = WorkerTest( - "data:text/html;charset=utf-8,clear timeout", - function(assert, browser, done) { - let called = 0; - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - let id = setInterval(function() { - self.postMessage("intreval") - clearInterval(id) - setTimeout(function() { - self.postMessage("done") - }, 100) - }, 10); - }, - contentScriptWhen: "ready", - onMessage: function(msg) { - if (msg === "intreval") { - called = called + 1; - if (called > 1) assert.fail("failed to cancel timer"); - } else { - assert.pass("interval cancelled"); - done(); - } - } - }); - } -) - -exports["test:setTimeout are unregistered on content unload"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let originalWindow = browser.contentWindow; - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - document.title = "ok"; - let i = 0; - setInterval(function () { - document.title = i++; - }, 10); - }, - contentScriptWhen: "ready" - }); - - // Change location so that content script is destroyed, - // and all setTimeout/setInterval should be unregistered. - // Wait some cycles in order to execute some intervals. - setTimeout(function () { - // Bug 689621: Wait for the new document load so that we are sure that - // previous document cancelled its intervals - let url2 = "data:text/html;charset=utf-8,<title>final</title>"; - loadAndWait(browser, url2, function onload() { - let titleAfterLoad = originalWindow.document.title; - // Wait additional cycles to verify that intervals are really cancelled - setTimeout(function () { - assert.equal(browser.contentDocument.title, "final", - "New document has not been modified"); - assert.equal(originalWindow.document.title, titleAfterLoad, - "Nor previous one"); - - done(); - }, 100); - }); - }, 100); - } -); - -exports['test:check window attribute in iframes'] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - // Create a first iframe and wait for its loading - let contentWin = browser.contentWindow; - let contentDoc = contentWin.document; - let iframe = contentDoc.createElement("iframe"); - contentDoc.body.appendChild(iframe); - - listenOnce(iframe, "load", function onload() { - - // Create a second iframe inside the first one and wait for its loading - let iframeDoc = iframe.contentWindow.document; - let subIframe = iframeDoc.createElement("iframe"); - iframeDoc.body.appendChild(subIframe); - - listenOnce(subIframe, "load", function onload() { - subIframe.removeEventListener("load", onload, true); - - // And finally create a worker against this second iframe - let worker = Worker({ - window: subIframe.contentWindow, - contentScript: 'new ' + function WorkerScope() { - self.postMessage([ - window.top !== window, - frameElement, - window.parent !== window, - top.location.href, - parent.location.href, - ]); - }, - onMessage: function(msg) { - assert.ok(msg[0], "window.top != window"); - assert.ok(msg[1], "window.frameElement is defined"); - assert.ok(msg[2], "window.parent != window"); - assert.equal(msg[3], contentWin.location.href, - "top.location refers to the toplevel content doc"); - assert.equal(msg[4], iframe.contentWindow.location.href, - "parent.location refers to the first iframe doc"); - done(); - } - }); - - }); - subIframe.setAttribute("src", "data:text/html;charset=utf-8,bar"); - - }); - iframe.setAttribute("src", "data:text/html;charset=utf-8,foo"); - } -); - -exports['test:check window attribute in toplevel documents'] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let worker = Worker({ - window: browser.contentWindow, - contentScript: 'new ' + function WorkerScope() { - self.postMessage([ - window.top === window, - frameElement, - window.parent === window - ]); - }, - onMessage: function(msg) { - assert.ok(msg[0], "window.top == window"); - assert.ok(!msg[1], "window.frameElement is null"); - assert.ok(msg[2], "window.parent == window"); - done(); - } - }); - } -); - -exports["test:check worker API with page history"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let url2 = "data:text/html;charset=utf-8,bar"; - - loadAndWait(browser, url2, function () { - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - // Just before the content script is disable, we register a timeout - // that will be disable until the page gets visible again - self.on("pagehide", function () { - setTimeout(function () { - self.port.emit("timeout"); - }, 0); - }); - - self.on("message", function() { - self.postMessage("saw message"); - }); - - self.on("event", function() { - self.port.emit("event", "saw event"); - }); - }, - contentScriptWhen: "start" - }); - - // postMessage works correctly when the page is visible - worker.postMessage("ok"); - - // We have to wait before going back into history, - // otherwise `goBack` won't do anything. - setTimeout(function () { - browser.goBack(); - }, 0); - - // Wait for the document to be hidden - browser.addEventListener("pagehide", function onpagehide() { - browser.removeEventListener("pagehide", onpagehide, false); - // Now any event sent to this worker should be cached - - worker.postMessage("message"); - worker.port.emit("event"); - - // Display the page with attached content script back in order to resume - // its timeout and receive the expected message. - // We have to delay this in order to not break the history. - // We delay for a non-zero amount of time in order to ensure that we - // do not receive the message immediatly, so that the timeout is - // actually disabled - setTimeout(function () { - worker.on("pageshow", function() { - let promise = Promise.all([ - new Promise(resolve => { - worker.port.on("event", () => { - assert.pass("Saw event"); - resolve(); - }); - }), - new Promise(resolve => { - worker.on("message", () => { - assert.pass("Saw message"); - resolve(); - }); - }), - new Promise(resolve => { - worker.port.on("timeout", () => { - assert.pass("Timer fired"); - resolve(); - }); - }) - ]); - promise.then(done); - }); - - browser.goForward(); - }, 500); - - }, false); - }); - - } -); - -exports['test:conentScriptFile as URL instance'] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - - let url = new URL(fixtures.url("test-contentScriptFile.js")); - let worker = Worker({ - window: browser.contentWindow, - contentScriptFile: url, - onMessage: function(msg) { - assert.equal(msg, "msg from contentScriptFile", - "received a wrong message from contentScriptFile"); - done(); - } - }); - } -); - -exports["test:worker events"] = WorkerTest( - DEFAULT_CONTENT_URL, - function (assert, browser, done) { - let window = browser.contentWindow; - let events = []; - let worker = Worker({ - window: window, - contentScript: 'new ' + function WorkerScope() { - self.postMessage('start'); - }, - onAttach: win => { - events.push('attach'); - assert.pass('attach event called when attached'); - assert.equal(window, win, 'attach event passes in attached window'); - }, - onError: err => { - assert.equal(err.message, 'Custom', - 'Error passed into error event'); - worker.detach(); - }, - onMessage: msg => { - assert.pass('`onMessage` handles postMessage') - throw new Error('Custom'); - }, - onDetach: _ => { - assert.pass('`onDetach` called when worker detached'); - done(); - } - }); - // `attach` event is called synchronously during instantiation, - // so we can't listen to that, TODO FIX? - // worker.on('attach', obj => console.log('attach', obj)); - } -); - -exports["test:onDetach in contentScript on destroy"] = WorkerTest( - "data:text/html;charset=utf-8,foo#detach", - function(assert, browser, done) { - let worker = Worker({ - window: browser.contentWindow, - contentScript: 'new ' + function WorkerScope() { - self.port.on('detach', function(reason) { - window.location.hash += '!' + reason; - }) - }, - }); - browser.contentWindow.addEventListener('hashchange', _ => { - assert.equal(browser.contentWindow.location.hash, '#detach!', - "location.href is as expected"); - done(); - }) - worker.destroy(); - } -); - -exports["test:onDetach in contentScript on unload"] = WorkerTest( - "data:text/html;charset=utf-8,foo#detach", - function(assert, browser, done) { - let { loader } = LoaderWithHookedConsole(module); - let worker = loader.require("sdk/content/worker").Worker({ - window: browser.contentWindow, - contentScript: 'new ' + function WorkerScope() { - self.port.on('detach', function(reason) { - window.location.hash += '!' + reason; - }) - }, - }); - browser.contentWindow.addEventListener('hashchange', _ => { - assert.equal(browser.contentWindow.location.hash, '#detach!shutdown', - "location.href is as expected"); - done(); - }) - loader.unload('shutdown'); - } -); - -exports["test:console method log functions properly"] = WorkerTest( - DEFAULT_CONTENT_URL, - function(assert, browser, done) { - let logs = []; - - system.on('console-api-log-event', onMessage); - - function onMessage({ subject }) { - logs.push(clean(subject.wrappedJSObject.arguments[0])); - } - - let clean = message => - message.trim(). - replace(/[\r\n]/g, " "). - replace(/ +/g, " "); - - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - console.log(Function); - console.log((foo) => foo * foo); - console.log(function foo(bar) { return bar + bar }); - - self.postMessage(); - }, - onMessage: () => { - system.off('console-api-log-event', onMessage); - - assert.deepEqual(logs, [ - "function Function() { [native code] }", - "(foo) => foo * foo", - "function foo(bar) { \"use strict\"; return bar + bar }" - ]); - - done(); - } - }); - } -); - -exports["test:global postMessage"] = WorkerTest( - WINDOW_SCRIPT_URL, - function(assert, browser, done) { - let contentScript = "window.addEventListener('message', function (e) {" + - " if (e.data === 'from -> window')" + - " self.port.emit('response', e.data, e.origin);" + - "});" + - "postMessage('from -> content-script', '*');"; - let { loader } = LoaderWithHookedConsole(module); - let worker = loader.require("sdk/content/worker").Worker({ - window: browser.contentWindow, - contentScriptWhen: "ready", - contentScript: contentScript - }); - - worker.port.on("response", (data, origin) => { - assert.equal(data, "from -> window", "Communication from content-script to window completed"); - done(); - }); -}); - -exports["test:destroy unbinds listeners from port"] = WorkerTest( - "data:text/html;charset=utf-8,portdestroyer", - function(assert, browser, done) { - let destroyed = false; - let worker = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - self.port.emit("destroy"); - setInterval(self.port.emit, 10, "ping"); - }, - onDestroy: done - }); - worker.port.on("ping", () => { - if (destroyed) { - assert.fail("Should not call events on port after destroy."); - } - }); - worker.port.on("destroy", () => { - destroyed = true; - worker.destroy(); - assert.pass("Worker destroyed, waiting for no future listeners handling events."); - setTimeout(done, 500); - }); - } -); - - -exports["test:destroy kills child worker"] = WorkerTest( - "data:text/html;charset=utf-8,<html><body><p id='detail'></p></body></html>", - function(assert, browser, done) { - let worker1 = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - self.port.on("ping", detail => { - let event = document.createEvent("CustomEvent"); - event.initCustomEvent("Test:Ping", true, true, detail); - document.dispatchEvent(event); - self.port.emit("pingsent"); - }); - - let listener = function(event) { - self.port.emit("pong", event.detail); - }; - - self.port.on("detach", () => { - window.removeEventListener("Test:Pong", listener); - }); - window.addEventListener("Test:Pong", listener); - }, - onAttach: function() { - let worker2 = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - let listener = function(event) { - let newEvent = document.createEvent("CustomEvent"); - newEvent.initCustomEvent("Test:Pong", true, true, event.detail); - document.dispatchEvent(newEvent); - }; - self.port.on("detach", () => { - window.removeEventListener("Test:Ping", listener); - }) - window.addEventListener("Test:Ping", listener); - self.postMessage(); - }, - onMessage: function() { - worker1.port.emit("ping", "test1"); - worker1.port.once("pong", detail => { - assert.equal(detail, "test1", "Saw the right message"); - worker1.port.once("pingsent", () => { - assert.pass("The message was sent"); - - worker2.destroy(); - - worker1.port.emit("ping", "test2"); - worker1.port.once("pong", detail => { - assert.fail("worker2 shouldn't have responded"); - }) - worker1.port.once("pingsent", () => { - assert.pass("The message was sent"); - worker1.destroy(); - done(); - }); - }); - }) - } - }); - } - }); - } -); - -exports["test:unload kills child worker"] = WorkerTest( - "data:text/html;charset=utf-8,<html><body><p id='detail'></p></body></html>", - function(assert, browser, done) { - let loader = Loader(module); - let worker1 = Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - self.port.on("ping", detail => { - let event = document.createEvent("CustomEvent"); - event.initCustomEvent("Test:Ping", true, true, detail); - document.dispatchEvent(event); - self.port.emit("pingsent"); - }); - - let listener = function(event) { - self.port.emit("pong", event.detail); - }; - - self.port.on("detach", () => { - window.removeEventListener("Test:Pong", listener); - }); - window.addEventListener("Test:Pong", listener); - }, - onAttach: function() { - let worker2 = loader.require("sdk/content/worker").Worker({ - window: browser.contentWindow, - contentScript: "new " + function WorkerScope() { - let listener = function(event) { - let newEvent = document.createEvent("CustomEvent"); - newEvent.initCustomEvent("Test:Pong", true, true, event.detail); - document.dispatchEvent(newEvent); - }; - self.port.on("detach", () => { - window.removeEventListener("Test:Ping", listener); - }) - window.addEventListener("Test:Ping", listener); - self.postMessage(); - }, - onMessage: function() { - worker1.port.emit("ping", "test1"); - worker1.port.once("pong", detail => { - assert.equal(detail, "test1", "Saw the right message"); - worker1.port.once("pingsent", () => { - assert.pass("The message was sent"); - - loader.unload(); - - worker1.port.emit("ping", "test2"); - worker1.port.once("pong", detail => { - assert.fail("worker2 shouldn't have responded"); - }) - worker1.port.once("pingsent", () => { - assert.pass("The message was sent"); - worker1.destroy(); - done(); - }); - }); - }) - } - }); - } - }); - } -); - -// require("sdk/test").run(exports); |