123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875 |
- /* 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 } = 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 DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
- const DEFAULT_CONTENT_URL = "data:text/html;charset=utf-8,foo";
- function makeWindow(contentURL) {
- 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();
- }
- });
- }
- );
- 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) {
- let { loader } = LoaderWithHookedConsole(module, onMessage);
- // Intercept all console method calls
- let calls = [];
- function onMessage(type, msg) {
- assert.equal(type, msg,
- "console.xxx(\"xxx\"), i.e. message is equal to the " +
- "console method name we are calling");
- calls.push(msg);
- }
- // Finally, create a worker that will call all console methods
- let worker = loader.require("sdk/content/worker").Worker({
- window: browser.contentWindow,
- contentScript: "new " + function WorkerScope() {
- console.log("log");
- console.info("info");
- console.warn("warn");
- console.error("error");
- console.debug("debug");
- console.exception("exception");
- self.postMessage();
- },
- onMessage: function() {
- // Ensure that console methods are called in the same execution order
- assert.equal(JSON.stringify(calls),
- JSON.stringify(["log", "info", "warn", "error", "debug", "exception"]),
- "console has been called successfully, in the 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 (corectly) 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.postMessage("timeout restored");
- }, 0);
- });
- },
- 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 throw
- assert.throws(
- function () { worker.postMessage("data"); },
- /The page is currently hidden and can no longer be used/,
- "postMessage should throw when the page is hidden in history"
- );
- assert.throws(
- function () { worker.port.emit("event"); },
- /The page is currently hidden and can no longer be used/,
- "port.emit should throw when the page is hidden in history"
- );
- // 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("message", function (data) {
- assert.ok(data, "timeout restored");
- done();
- });
- browser.goForward();
- }, 500);
- }, false);
- });
- }
- );
- exports["test:global postMessage"] = WorkerTest(
- DEFAULT_CONTENT_URL,
- function(assert, browser, done) {
- let { loader } = LoaderWithHookedConsole(module, onMessage);
- setPref(DEPRECATE_PREF, true);
- // Intercept all console method calls
- let seenMessages = 0;
- function onMessage(type, message) {
- seenMessages++;
- assert.equal(type, "error", "Should be an error");
- assert.equal(message, "DEPRECATED: The global `postMessage()` function in " +
- "content scripts is deprecated in favor of the " +
- "`self.postMessage()` function, which works the same. " +
- "Replace calls to `postMessage()` with calls to " +
- "`self.postMessage()`." +
- "For more info on `self.on`, see " +
- "<https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/addon-development/web-content.html>.",
- "Should have seen the deprecation message")
- }
- assert.notEqual(browser.contentWindow.location.href, "about:blank",
- "window is now on the right document");
- let window = browser.contentWindow
- let worker = loader.require("sdk/content/worker").Worker({
- window: window,
- contentScript: "new " + function WorkerScope() {
- postMessage("success");
- },
- contentScriptWhen: "ready",
- onMessage: function(msg) {
- assert.equal("success", msg, "Should have seen the right postMessage call");
- assert.equal(1, seenMessages, "Should have seen the deprecation message");
- done();
- }
- });
- assert.equal(worker.url, window.location.href,
- "worker.url works");
- worker.postMessage("hi!");
- }
- );
- 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.testWorkerEvents = 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));
- });
- require("test").run(exports);
|