caps/tests/mochitest/test_disableScript.xul

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:bdcb618951b8
1 <?xml version="1.0"?>
2 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
3 <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
4 <!--
5 https://bugzilla.mozilla.org/show_bug.cgi?id=840488
6 -->
7 <window title="Mozilla Bug 840488"
8 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
9 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
10
11 <!-- test results are displayed in the html:body -->
12 <body xmlns="http://www.w3.org/1999/xhtml">
13 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=840488"
14 target="_blank">Mozilla Bug 840488</a>
15 </body>
16
17 <iframe id="root" name="root" type="content"/>
18 <iframe id="chromeFrame" name="chromeFrame" type="content"/>
19
20 <!-- test code goes here -->
21 <script type="application/javascript">
22 <![CDATA[
23
24 /** Test for all the different ways that script can be disabled for a given global. **/
25
26 SimpleTest.waitForExplicitFinish();
27 const Cu = Components.utils;
28 const Ci = Components.interfaces;
29 Cu.import("resource://gre/modules/Promise.jsm");
30 Cu.import("resource://gre/modules/Services.jsm");
31 const ssm = Services.scriptSecurityManager;
32 function makeURI(uri) { return Services.io.newURI(uri, null, null); }
33 const path = "/tests/caps/tests/mochitest/file_disableScript.html";
34 const uri = "http://www.example.com" + path;
35 var rootFrame = document.getElementById('root');
36 var chromeFrame = document.getElementById('chromeFrame');
37 navigateFrame(rootFrame, uri + "?name=rootframe").then(function() {
38 navigateFrame(chromeFrame, "file_disableScript.html").then(go);
39 });
40
41 function navigateFrame(ifr, src) {
42 let deferred = Promise.defer();
43 function onload() {
44 ifr.removeEventListener('load', onload);
45 deferred.resolve();
46 }
47 ifr.addEventListener('load', onload, false);
48 ifr.setAttribute('src', src);
49 return deferred.promise;
50 }
51
52 function navigateBack(ifr) {
53 let deferred = Promise.defer();
54
55 // pageshow events don't fire on the iframe element, so we need to use the
56 // chrome event handler for the docshell.
57 var browser = ifr.contentWindow
58 .QueryInterface(Ci.nsIInterfaceRequestor)
59 .getInterface(Ci.nsIWebNavigation)
60 .QueryInterface(Ci.nsIDocShell)
61 .chromeEventHandler;
62 function onpageshow(evt) {
63 info("Navigated back. Persisted: " + evt.persisted);
64 browser.removeEventListener('pageshow', onpageshow);
65 deferred.resolve();
66 }
67 browser.addEventListener('pageshow', onpageshow, false);
68 ifr.contentWindow.history.back();
69 return deferred.promise;
70 }
71
72 function addFrame(parentWin, name, expectOnload) {
73 let ifr = parentWin.document.createElement('iframe');
74 parentWin.document.body.appendChild(ifr);
75 ifr.setAttribute('name', name);
76 let deferred = Promise.defer();
77 // We need to append 'name' to avoid running afoul of recursive frame detection.
78 let frameURI = uri + "?name=" + name;
79 navigateFrame(ifr, frameURI).then(function() {
80 is(ifr.contentWindow.location, frameURI, "Successful load");
81 is(!!ifr.contentWindow.wrappedJSObject.gFiredOnload, expectOnload,
82 "onload should only fire when scripts are enabled");
83 deferred.resolve();
84 });
85 return deferred.promise;
86 }
87
88 function checkScriptEnabled(win, expectEnabled) {
89 win.wrappedJSObject.gFiredOnclick = false;
90 win.document.body.dispatchEvent(new win.Event('click'));
91 is(win.wrappedJSObject.gFiredOnclick, expectEnabled, "Checking script-enabled for " + win.name + " (" + win.location + ")");
92 }
93
94 function setScriptEnabledForDocShell(win, enabled) {
95 win.QueryInterface(Ci.nsIInterfaceRequestor)
96 .getInterface(Ci.nsIDocShell)
97 .allowJavascript = enabled;
98 }
99
100 function testList(expectEnabled, win, list, idx) {
101 let idx = idx || 0;
102 let deferred = Promise.defer();
103 let target = list[idx] + path;
104 info("Testing scriptability for: " + target + ". expecting " + expectEnabled);
105 navigateFrame(win.frameElement, target).then(function() {
106 checkScriptEnabled(win, expectEnabled);
107 if (idx == list.length - 1)
108 deferred.resolve();
109 else
110 testList(expectEnabled, win, list, idx + 1).then(function() { deferred.resolve(); });
111 });
112 return deferred.promise;
113 }
114
115 function testDomainPolicy(defaultScriptability, exceptions, superExceptions,
116 exempt, notExempt, set, superSet, win) {
117 // Populate our sets.
118 for (var e of exceptions)
119 set.add(makeURI(e));
120 for (var e of superExceptions)
121 superSet.add(makeURI(e));
122
123 return testList(defaultScriptability, win, notExempt).then(function() {
124 return testList(!defaultScriptability, win, exempt);
125 });
126 }
127
128 function setScriptEnabledForBrowser(enabled) {
129 var prefname = "javascript.enabled";
130 Services.prefs.setBoolPref(prefname, enabled);
131 }
132
133 function reloadFrame(frame) {
134 let deferred = Promise.defer();
135 frame.addEventListener('load', function onload() {
136 deferred.resolve();
137 frame.removeEventListener('load', onload);
138 }, false);
139 frame.contentWindow.location.reload(true);
140 return deferred.promise;
141 }
142
143 function go() {
144 var rootWin = rootFrame.contentWindow;
145 var chromeWin = chromeFrame.contentWindow;
146
147 // Test simple docshell enable/disable.
148 checkScriptEnabled(rootWin, true);
149 setScriptEnabledForDocShell(rootWin, false);
150 checkScriptEnabled(rootWin, false);
151 setScriptEnabledForDocShell(rootWin, true);
152 checkScriptEnabled(rootWin, true);
153
154 // Privileged frames are immune to docshell flags.
155 ok(ssm.isSystemPrincipal(chromeWin.document.nodePrincipal), "Sanity check for System Principal");
156 setScriptEnabledForDocShell(chromeWin, false);
157 checkScriptEnabled(chromeWin, true);
158 setScriptEnabledForDocShell(chromeWin, true);
159
160 // Play around with the docshell tree and make sure everything works as
161 // we expect.
162 addFrame(rootWin, 'parent', true).then(function() {
163 checkScriptEnabled(rootWin[0], true);
164 return addFrame(rootWin[0], 'childA', true);
165 }).then(function() {
166 checkScriptEnabled(rootWin[0][0], true);
167 setScriptEnabledForDocShell(rootWin[0], false);
168 checkScriptEnabled(rootWin, true);
169 checkScriptEnabled(rootWin[0], false);
170 checkScriptEnabled(rootWin[0][0], false);
171 return addFrame(rootWin[0], 'childB', false);
172 }).then(function() {
173 checkScriptEnabled(rootWin[0][1], false);
174 setScriptEnabledForDocShell(rootWin[0][0], false);
175 setScriptEnabledForDocShell(rootWin[0], true);
176 checkScriptEnabled(rootWin[0], true);
177 checkScriptEnabled(rootWin[0][0], false);
178 setScriptEnabledForDocShell(rootWin[0][0], true);
179
180 // Flags are inherited from the parent docshell at attach time. Note that
181 // the flag itself is inherited, regardless of whether or not scripts are
182 // currently allowed on the parent (which could depend on the parent's
183 // parent). Check that.
184 checkScriptEnabled(rootWin[0][1], false);
185 setScriptEnabledForDocShell(rootWin[0], false);
186 setScriptEnabledForDocShell(rootWin[0][1], true);
187 return addFrame(rootWin[0][1], 'grandchild', false);
188 }).then(function() {
189 checkScriptEnabled(rootWin[0], false);
190 checkScriptEnabled(rootWin[0][1], false);
191 checkScriptEnabled(rootWin[0][1][0], false);
192 setScriptEnabledForDocShell(rootWin[0], true);
193 checkScriptEnabled(rootWin[0], true);
194 checkScriptEnabled(rootWin[0][1], true);
195 checkScriptEnabled(rootWin[0][1][0], true);
196
197 // Try navigating two frames, then munging docshell scriptability, then
198 // pulling the frames out of the bfcache to make sure that flags are
199 // properly propagated to inactive inner windows. We do this both for an
200 // 'own' docshell, as well as for an ancestor docshell.
201 return navigateFrame(rootWin[0][0].frameElement, rootWin[0][0].location + '-navigated');
202 }).then(function() { return navigateFrame(rootWin[0][1][0].frameElement, rootWin[0][1][0].location + '-navigated'); })
203 .then(function() {
204 checkScriptEnabled(rootWin[0][0], true);
205 checkScriptEnabled(rootWin[0][1][0], true);
206 setScriptEnabledForDocShell(rootWin[0][0], false);
207 setScriptEnabledForDocShell(rootWin[0][1], false);
208 checkScriptEnabled(rootWin[0][0], false);
209 checkScriptEnabled(rootWin[0][1][0], false);
210 return navigateBack(rootWin[0][0].frameElement);
211 }).then(function() { return navigateBack(rootWin[0][1][0].frameElement); })
212 .then(function() {
213 checkScriptEnabled(rootWin[0][0], false);
214 checkScriptEnabled(rootWin[0][1][0], false);
215
216 // Disable JS via the global pref pref. This is only guaranteed to have an effect
217 // for subsequent loads.
218 setScriptEnabledForBrowser(false);
219 return reloadFrame(rootFrame);
220 }).then(function() {
221 checkScriptEnabled(rootWin, false);
222 checkScriptEnabled(chromeWin, true);
223 setScriptEnabledForBrowser(true);
224 return reloadFrame(rootFrame);
225 }).then(function() {
226 checkScriptEnabled(rootWin, true);
227
228 // Play around with dynamically blocking script for a given global.
229 // This takes effect immediately.
230 Cu.blockScriptForGlobal(rootWin);
231 Cu.blockScriptForGlobal(rootWin);
232 Cu.unblockScriptForGlobal(rootWin);
233 checkScriptEnabled(rootWin, false);
234 Cu.unblockScriptForGlobal(rootWin);
235 checkScriptEnabled(rootWin, true);
236 Cu.blockScriptForGlobal(rootWin);
237 try {
238 Cu.blockScriptForGlobal(chromeWin);
239 ok(false, "Should have thrown");
240 } catch (e) {
241 ok(/may not be disabled/.test(e),
242 "Shouldn't be able to programmatically block script for system globals");
243 }
244 return reloadFrame(rootFrame);
245 }).then(function() {
246 checkScriptEnabled(rootWin, true);
247
248 // Test system-wide domain policy. This only takes effect for subsequently-
249 // loaded globals.
250
251 // Check the basic semantics of the sets.
252 is(ssm.domainPolicyActive, false, "not enabled");
253 window.policy = ssm.activateDomainPolicy();
254 ok(policy instanceof Ci.nsIDomainPolicy, "Got a policy");
255 try {
256 ssm.activateDomainPolicy();
257 ok(false, "Should have thrown");
258 } catch (e) {
259 ok(true, "can't have two live domain policies");
260 }
261 var sbRef = policy.superBlacklist;
262 isnot(sbRef, null, "superBlacklist non-null");
263 ok(!sbRef.contains(makeURI('http://www.example.com')));
264 sbRef.add(makeURI('http://www.example.com/foopy'));
265 ok(sbRef.contains(makeURI('http://www.example.com')));
266 sbRef.remove(makeURI('http://www.example.com'));
267 ok(!sbRef.contains(makeURI('http://www.example.com')));
268 sbRef.add(makeURI('http://www.example.com/foopy/this.that/'));
269 ok(sbRef.contains(makeURI('http://www.example.com/baz')));
270 ok(!sbRef.contains(makeURI('https://www.example.com')));
271 ok(!sbRef.contains(makeURI('https://www.example.com:88')));
272 ok(!sbRef.contains(makeURI('http://foo.www.example.com')));
273 ok(sbRef.containsSuperDomain(makeURI('http://foo.www.example.com')));
274 ok(sbRef.containsSuperDomain(makeURI('http://foo.bar.www.example.com')));
275 ok(!sbRef.containsSuperDomain(makeURI('http://foo.bar.www.exxample.com')));
276 ok(!sbRef.containsSuperDomain(makeURI('http://example.com')));
277 ok(!sbRef.containsSuperDomain(makeURI('http://com/this.that/')));
278 ok(!sbRef.containsSuperDomain(makeURI('https://foo.www.example.com')));
279 ok(sbRef.contains(makeURI('http://www.example.com')));
280 policy.deactivate();
281 is(ssm.domainPolicyActive, false, "back to inactive");
282 ok(!sbRef.contains(makeURI('http://www.example.com')),
283 "Disabling domain policy clears the set");
284 policy = ssm.activateDomainPolicy();
285 ok(policy.superBlacklist);
286 isnot(sbRef, policy.superBlacklist, "Mint new sets each time!");
287 policy.deactivate();
288 is(policy.blacklist, null, "blacklist nulled out");
289 policy = ssm.activateDomainPolicy();
290 isnot(policy.blacklist, null, "non-null again");
291 isnot(policy.blacklist, sbRef, "freshly minted");
292 policy.deactivate();
293
294 //
295 // Now, create and apply a mock-policy. We check the same policy both as
296 // a blacklist and as a whitelist.
297 //
298
299 window.testPolicy = {
300 // The policy.
301 exceptions: ['http://test1.example.com', 'http://example.com'],
302 superExceptions: ['http://test2.example.org', 'https://test1.example.com'],
303
304 // The testcases.
305 exempt: ['http://test1.example.com', 'http://example.com',
306 'http://test2.example.org', 'http://sub1.test2.example.org',
307 'https://sub1.test1.example.com'],
308
309 notExempt: ['http://test2.example.com', 'http://sub1.test1.example.com',
310 'http://www.example.com', 'https://test2.example.com',
311 'https://example.com', 'http://test1.example.org'],
312 };
313
314 policy = ssm.activateDomainPolicy();
315 info("Testing Blacklist-style Domain Policy");
316 return testDomainPolicy(true, testPolicy.exceptions,
317 testPolicy.superExceptions, testPolicy.exempt,
318 testPolicy.notExempt, policy.blacklist,
319 policy.superBlacklist, rootWin);
320 }).then(function() {
321 policy.deactivate();
322 policy = ssm.activateDomainPolicy();
323 info("Testing Whitelist-style Domain Policy");
324 setScriptEnabledForBrowser(false);
325 return testDomainPolicy(false, testPolicy.exceptions,
326 testPolicy.superExceptions, testPolicy.exempt,
327 testPolicy.notExempt, policy.whitelist,
328 policy.superWhitelist, rootWin);
329 }).then(function() {
330 setScriptEnabledForBrowser(true);
331 policy.deactivate();
332
333 SimpleTest.finish();
334 });
335 }
336
337 ]]>
338 </script>
339 </window>

mercurial