michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const hiddenFrames = require("sdk/frame/hidden-frame"); michael@0: const { create: makeFrame } = require("sdk/frame/utils"); michael@0: const { window } = require("sdk/addon/window"); michael@0: const { Loader } = require('sdk/test/loader'); michael@0: const { URL } = require("sdk/url"); michael@0: const testURI = require("./fixtures").url("test.html"); michael@0: const testHost = URL(testURI).scheme + '://' + URL(testURI).host; michael@0: michael@0: /* michael@0: * Utility function that allow to easily run a proxy test with a clean michael@0: * new HTML document. See first unit test for usage. michael@0: */ michael@0: function createProxyTest(html, callback) { michael@0: return function (assert, done) { michael@0: let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(html); michael@0: let principalLoaded = false; michael@0: michael@0: let element = makeFrame(window.document, { michael@0: nodeName: "iframe", michael@0: type: "content", michael@0: allowJavascript: true, michael@0: allowPlugins: true, michael@0: allowAuth: true, michael@0: uri: testURI michael@0: }); michael@0: michael@0: element.addEventListener("DOMContentLoaded", onDOMReady, false); michael@0: michael@0: function onDOMReady() { michael@0: // Reload frame after getting principal from `testURI` michael@0: if (!principalLoaded) { michael@0: element.setAttribute("src", url); michael@0: principalLoaded = true; michael@0: return; michael@0: } michael@0: michael@0: assert.equal(element.getAttribute("src"), url, "correct URL loaded"); michael@0: element.removeEventListener("DOMContentLoaded", onDOMReady, michael@0: false); michael@0: let xrayWindow = element.contentWindow; michael@0: let rawWindow = xrayWindow.wrappedJSObject; michael@0: michael@0: let isDone = false; michael@0: let helper = { michael@0: xrayWindow: xrayWindow, michael@0: rawWindow: rawWindow, michael@0: createWorker: function (contentScript) { michael@0: return createWorker(assert, xrayWindow, contentScript, helper.done); michael@0: }, michael@0: done: function () { michael@0: if (isDone) michael@0: return; michael@0: isDone = true; michael@0: element.parentNode.removeChild(element); michael@0: done(); michael@0: } michael@0: }; michael@0: callback(helper, assert); michael@0: } michael@0: }; michael@0: } michael@0: michael@0: function createWorker(assert, xrayWindow, contentScript, done) { michael@0: let loader = Loader(module); michael@0: let Worker = loader.require("sdk/content/worker").Worker; michael@0: let worker = Worker({ michael@0: window: xrayWindow, michael@0: contentScript: [ michael@0: 'new ' + function () { michael@0: assert = function assert(v, msg) { michael@0: self.port.emit("assert", {assertion:v, msg:msg}); michael@0: } michael@0: done = function done() { michael@0: self.port.emit("done"); michael@0: } michael@0: }, michael@0: contentScript michael@0: ] michael@0: }); michael@0: michael@0: worker.port.on("done", done); michael@0: worker.port.on("assert", function (data) { michael@0: assert.ok(data.assertion, data.msg); michael@0: }); michael@0: michael@0: return worker; michael@0: } michael@0: michael@0: /* Examples for the `createProxyTest` uses */ michael@0: michael@0: let html = ""; michael@0: michael@0: exports["test Create Proxy Test"] = createProxyTest(html, function (helper, assert) { michael@0: // You can get access to regular `test` object in second argument of michael@0: // `createProxyTest` method: michael@0: assert.ok(helper.rawWindow.documentGlobal, michael@0: "You have access to a raw window reference via `helper.rawWindow`"); michael@0: assert.ok(!("documentGlobal" in helper.xrayWindow), michael@0: "You have access to an XrayWrapper reference via `helper.xrayWindow`"); michael@0: michael@0: // If you do not create a Worker, you have to call helper.done(), michael@0: // in order to say when your test is finished michael@0: helper.done(); michael@0: }); michael@0: michael@0: exports["test Create Proxy Test With Worker"] = createProxyTest("", function (helper) { michael@0: michael@0: helper.createWorker( michael@0: "new " + function WorkerScope() { michael@0: assert(true, "You can do assertions in your content script"); michael@0: // And if you create a worker, you either have to call `done` michael@0: // from content script or helper.done() michael@0: done(); michael@0: } michael@0: ); michael@0: michael@0: }); michael@0: michael@0: exports["test Create Proxy Test With Events"] = createProxyTest("", function (helper, assert) { michael@0: michael@0: let worker = helper.createWorker( michael@0: "new " + function WorkerScope() { michael@0: self.port.emit("foo"); michael@0: } michael@0: ); michael@0: michael@0: worker.port.on("foo", function () { michael@0: assert.pass("You can use events"); michael@0: // And terminate your test with helper.done: michael@0: helper.done(); michael@0: }); michael@0: michael@0: }); michael@0: michael@0: // Bug 714778: There was some issue around `toString` functions michael@0: // that ended up being shared between content scripts michael@0: exports["test Shared To String Proxies"] = createProxyTest("", function(helper) { michael@0: michael@0: let worker = helper.createWorker( michael@0: 'new ' + function ContentScriptScope() { michael@0: // We ensure that `toString` can't be modified so that nothing could michael@0: // leak to/from the document and between content scripts michael@0: // It only applies to JS proxies, there isn't any such issue with xrays. michael@0: //document.location.toString = function foo() {}; michael@0: document.location.toString.foo = "bar"; michael@0: assert("foo" in document.location.toString, "document.location.toString can be modified"); michael@0: assert(document.location.toString() == "data:text/html;charset=utf-8,", michael@0: "First document.location.toString()"); michael@0: self.postMessage("next"); michael@0: } michael@0: ); michael@0: worker.on("message", function () { michael@0: helper.createWorker( michael@0: 'new ' + function ContentScriptScope2() { michael@0: assert(!("foo" in document.location.toString), michael@0: "document.location.toString is different for each content script"); michael@0: assert(document.location.toString() == "data:text/html;charset=utf-8,", michael@0: "Second document.location.toString()"); michael@0: done(); michael@0: } michael@0: ); michael@0: }); michael@0: }); michael@0: michael@0: michael@0: // Ensure that postMessage is working correctly across documents with an iframe michael@0: let html = '