|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 const {Cc,Ci} = require("chrome"); |
|
8 const timer = require("sdk/timers"); |
|
9 const xulApp = require("sdk/system/xul-app"); |
|
10 const { Loader } = require("sdk/test/loader"); |
|
11 const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils"); |
|
12 |
|
13 /** |
|
14 * A helper function that creates a PageMod, then opens the specified URL |
|
15 * and checks the effect of the page mod on 'onload' event via testCallback. |
|
16 */ |
|
17 exports.testPageMod = function testPageMod(assert, done, testURL, pageModOptions, |
|
18 testCallback, timeout) { |
|
19 if (!xulApp.versionInRange(xulApp.platformVersion, "1.9.3a3", "*") && |
|
20 !xulApp.versionInRange(xulApp.platformVersion, "1.9.2.7", "1.9.2.*")) { |
|
21 assert.pass("Note: not testing PageMod, as it doesn't work on this platform version"); |
|
22 return null; |
|
23 } |
|
24 |
|
25 var wm = Cc['@mozilla.org/appshell/window-mediator;1'] |
|
26 .getService(Ci.nsIWindowMediator); |
|
27 var browserWindow = wm.getMostRecentWindow("navigator:browser"); |
|
28 if (!browserWindow) { |
|
29 assert.pass("page-mod tests: could not find the browser window, so " + |
|
30 "will not run. Use -a firefox to run the pagemod tests.") |
|
31 return null; |
|
32 } |
|
33 |
|
34 let loader = Loader(module); |
|
35 let pageMod = loader.require("sdk/page-mod"); |
|
36 |
|
37 var pageMods = [new pageMod.PageMod(opts) for each(opts in pageModOptions)]; |
|
38 |
|
39 let newTab = openTab(browserWindow, testURL, { |
|
40 inBackground: false |
|
41 }); |
|
42 var b = getBrowserForTab(newTab); |
|
43 |
|
44 function onPageLoad() { |
|
45 b.removeEventListener("load", onPageLoad, true); |
|
46 // Delay callback execute as page-mod content scripts may be executed on |
|
47 // load event. So page-mod actions may not be already done. |
|
48 // If we delay even more contentScriptWhen:'end', we may want to modify |
|
49 // this code again. |
|
50 timer.setTimeout(testCallback, 0, |
|
51 b.contentWindow.wrappedJSObject, |
|
52 function () { |
|
53 pageMods.forEach(function(mod) mod.destroy()); |
|
54 // XXX leaks reported if we don't close the tab? |
|
55 closeTab(newTab); |
|
56 loader.unload(); |
|
57 done(); |
|
58 } |
|
59 ); |
|
60 } |
|
61 b.addEventListener("load", onPageLoad, true); |
|
62 |
|
63 return pageMods; |
|
64 } |
|
65 |
|
66 /** |
|
67 * helper function that creates a PageMod and calls back the appropriate handler |
|
68 * based on the value of document.readyState at the time contentScript is attached |
|
69 */ |
|
70 exports.handleReadyState = function(url, contentScriptWhen, callbacks) { |
|
71 const { PageMod } = Loader(module).require('sdk/page-mod'); |
|
72 |
|
73 let pagemod = PageMod({ |
|
74 include: url, |
|
75 attachTo: ['existing', 'top'], |
|
76 contentScriptWhen: contentScriptWhen, |
|
77 contentScript: "self.postMessage(document.readyState)", |
|
78 onAttach: worker => { |
|
79 let { tab } = worker; |
|
80 worker.on('message', readyState => { |
|
81 pagemod.destroy(); |
|
82 // generate event name from `readyState`, e.g. `"loading"` becomes `onLoading`. |
|
83 let type = 'on' + readyState[0].toUpperCase() + readyState.substr(1); |
|
84 |
|
85 if (type in callbacks) |
|
86 callbacks[type](tab); |
|
87 }) |
|
88 } |
|
89 }); |
|
90 } |