1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/* 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
<script src="${URL}"></script>
delay both the "DOMContentLoaded"
<script async src="${URL}"></script>
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;
|