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: "use strict"; michael@0: michael@0: const {Cc,Ci} = require("chrome"); michael@0: const timer = require("sdk/timers"); michael@0: const xulApp = require("sdk/system/xul-app"); michael@0: const { Loader } = require("sdk/test/loader"); michael@0: const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils"); michael@0: michael@0: /** michael@0: * A helper function that creates a PageMod, then opens the specified URL michael@0: * and checks the effect of the page mod on 'onload' event via testCallback. michael@0: */ michael@0: exports.testPageMod = function testPageMod(assert, done, testURL, pageModOptions, michael@0: testCallback, timeout) { michael@0: if (!xulApp.versionInRange(xulApp.platformVersion, "1.9.3a3", "*") && michael@0: !xulApp.versionInRange(xulApp.platformVersion, "1.9.2.7", "1.9.2.*")) { michael@0: assert.pass("Note: not testing PageMod, as it doesn't work on this platform version"); michael@0: return null; michael@0: } michael@0: michael@0: var wm = Cc['@mozilla.org/appshell/window-mediator;1'] michael@0: .getService(Ci.nsIWindowMediator); michael@0: var browserWindow = wm.getMostRecentWindow("navigator:browser"); michael@0: if (!browserWindow) { michael@0: assert.pass("page-mod tests: could not find the browser window, so " + michael@0: "will not run. Use -a firefox to run the pagemod tests.") michael@0: return null; michael@0: } michael@0: michael@0: let loader = Loader(module); michael@0: let pageMod = loader.require("sdk/page-mod"); michael@0: michael@0: var pageMods = [new pageMod.PageMod(opts) for each(opts in pageModOptions)]; michael@0: michael@0: let newTab = openTab(browserWindow, testURL, { michael@0: inBackground: false michael@0: }); michael@0: var b = getBrowserForTab(newTab); michael@0: michael@0: function onPageLoad() { michael@0: b.removeEventListener("load", onPageLoad, true); michael@0: // Delay callback execute as page-mod content scripts may be executed on michael@0: // load event. So page-mod actions may not be already done. michael@0: // If we delay even more contentScriptWhen:'end', we may want to modify michael@0: // this code again. michael@0: timer.setTimeout(testCallback, 0, michael@0: b.contentWindow.wrappedJSObject, michael@0: function () { michael@0: pageMods.forEach(function(mod) mod.destroy()); michael@0: // XXX leaks reported if we don't close the tab? michael@0: closeTab(newTab); michael@0: loader.unload(); michael@0: done(); michael@0: } michael@0: ); michael@0: } michael@0: b.addEventListener("load", onPageLoad, true); michael@0: michael@0: return pageMods; michael@0: } michael@0: michael@0: /** michael@0: * helper function that creates a PageMod and calls back the appropriate handler michael@0: * based on the value of document.readyState at the time contentScript is attached michael@0: */ michael@0: exports.handleReadyState = function(url, contentScriptWhen, callbacks) { michael@0: const { PageMod } = Loader(module).require('sdk/page-mod'); michael@0: michael@0: let pagemod = PageMod({ michael@0: include: url, michael@0: attachTo: ['existing', 'top'], michael@0: contentScriptWhen: contentScriptWhen, michael@0: contentScript: "self.postMessage(document.readyState)", michael@0: onAttach: worker => { michael@0: let { tab } = worker; michael@0: worker.on('message', readyState => { michael@0: pagemod.destroy(); michael@0: // generate event name from `readyState`, e.g. `"loading"` becomes `onLoading`. michael@0: let type = 'on' + readyState[0].toUpperCase() + readyState.substr(1); michael@0: michael@0: if (type in callbacks) michael@0: callbacks[type](tab); michael@0: }) michael@0: } michael@0: }); michael@0: }