/* 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 { Cc, Ci } = require("chrome");
const { setTimeout } = require("sdk/timers");
const { Loader } = require("sdk/test/loader");
const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils");
const { getMostRecentBrowserWindow } = require("sdk/window/utils");
const { merge } = require("sdk/util/object");
const httpd = require("../lib/httpd");
const { cleanUI } = require("sdk/test/utils");
const PORT = 8099;
const PATH = '/test-contentScriptWhen.html';
function createLoader () {
let options = merge({}, require('@loader/options'),
{ id: "testloader", prefixURI: require('../fixtures').url() });
return Loader(module, null, options);
}
exports.createLoader = createLoader;
function openNewTab(url) {
return openTab(getMostRecentBrowserWindow(), url, {
inBackground: false
});
}
exports.openNewTab = openNewTab;
// an evil function enables the creation of tests
// that depend on delicate event timing. do not use.
function testPageMod(assert, done, testURL, pageModOptions,
testCallback, timeout) {
let loader = createLoader();
let { PageMod } = loader.require("sdk/page-mod");
let pageMods = pageModOptions.map(opts => new PageMod(opts));
let newTab = openNewTab(testURL);
let b = getBrowserForTab(newTab);
function onPageLoad() {
b.removeEventListener("load", onPageLoad, true);
// Delay callback execute as page-mod content scripts may be executed on
// load event. So page-mod actions may not be already done.
// If we delay even more contentScriptWhen:'end', we may want to modify
// this code again.
setTimeout(testCallback, timeout,
b.contentWindow.wrappedJSObject, // TODO: remove this CPOW
function () {
pageMods.forEach(mod => mod.destroy());
// XXX leaks reported if we don't close the tab?
closeTab(newTab);
loader.unload();
done();
}
);
}
b.addEventListener("load", onPageLoad, true);
return pageMods;
}
exports.testPageMod = testPageMod;
/**
* helper function that creates a PageMod and calls back the appropriate handler
* based on the value of document.readyState at the time contentScript is attached
*/
exports.handleReadyState = function(url, contentScriptWhen, callbacks) {
const loader = Loader(module);
const { PageMod } = loader.require('sdk/page-mod');
let pagemod = PageMod({
include: url,
attachTo: ['existing', 'top'],
contentScriptWhen: contentScriptWhen,
contentScript: "self.postMessage(document.readyState)",
onAttach: worker => {
let { tab } = worker;
worker.on('message', readyState => {
// generate event name from `readyState`, e.g. `"loading"` becomes `onLoading`.
let type = 'on' + readyState[0].toUpperCase() + readyState.substr(1);
if (type in callbacks)
callbacks[type](tab);
pagemod.destroy();
loader.unload();
})
}
});
}
// serves a slow page which takes 1.5 seconds to load,
// 0.5 seconds in each readyState: uninitialized, loading, interactive.
function contentScriptWhenServer() {
const URL = 'http://localhost:' + PORT + PATH;
const HTML = `/* polyglot js
delay both the "DOMContentLoaded"
and "load" events */`;
let srv = httpd.startServerAsync(PORT);
srv.registerPathHandler(PATH, (_, response) => {
response.processAsync();
response.setHeader('Content-Type', 'text/html', false);
setTimeout(_ => response.finish(), 500);
response.write(HTML);
})
srv.URL = URL;
return srv;
}
exports.contentScriptWhenServer = contentScriptWhenServer;