123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
- <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
- <!--
- https://bugzilla.mozilla.org/show_bug.cgi?id=840488
- -->
- <window title="Mozilla Bug 840488"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
- <!-- test results are displayed in the html:body -->
- <body xmlns="http://www.w3.org/1999/xhtml">
- <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=840488"
- target="_blank">Mozilla Bug 840488</a>
- </body>
- <iframe id="root" name="root" type="content"/>
- <iframe id="chromeFrame" name="chromeFrame" type="content"/>
- <!-- test code goes here -->
- <script type="application/javascript">
- <![CDATA[
- /** Test for all the different ways that script can be disabled for a given global. **/
- SimpleTest.waitForExplicitFinish();
- const Cu = Components.utils;
- const Ci = Components.interfaces;
- Cu.import("resource://gre/modules/Promise.jsm");
- Cu.import("resource://gre/modules/Services.jsm");
- const ssm = Services.scriptSecurityManager;
- function makeURI(uri) { return Services.io.newURI(uri, null, null); }
- const path = "/tests/caps/tests/mochitest/file_disableScript.html";
- const uri = "http://www.example.com" + path;
- var rootFrame = document.getElementById('root');
- var chromeFrame = document.getElementById('chromeFrame');
- navigateFrame(rootFrame, uri + "?name=rootframe").then(function() {
- navigateFrame(chromeFrame, "file_disableScript.html").then(go);
- });
- function navigateFrame(ifr, src) {
- let deferred = Promise.defer();
- function onload() {
- ifr.removeEventListener('load', onload);
- deferred.resolve();
- }
- ifr.addEventListener('load', onload, false);
- ifr.setAttribute('src', src);
- return deferred.promise;
- }
- function navigateBack(ifr) {
- let deferred = Promise.defer();
- // pageshow events don't fire on the iframe element, so we need to use the
- // chrome event handler for the docshell.
- var browser = ifr.contentWindow
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .chromeEventHandler;
- function onpageshow(evt) {
- info("Navigated back. Persisted: " + evt.persisted);
- browser.removeEventListener('pageshow', onpageshow);
- deferred.resolve();
- }
- browser.addEventListener('pageshow', onpageshow, false);
- ifr.contentWindow.history.back();
- return deferred.promise;
- }
- function addFrame(parentWin, name, expectOnload) {
- let ifr = parentWin.document.createElement('iframe');
- parentWin.document.body.appendChild(ifr);
- ifr.setAttribute('name', name);
- let deferred = Promise.defer();
- // We need to append 'name' to avoid running afoul of recursive frame detection.
- let frameURI = uri + "?name=" + name;
- navigateFrame(ifr, frameURI).then(function() {
- is(String(ifr.contentWindow.location), frameURI, "Successful load");
- is(!!ifr.contentWindow.wrappedJSObject.gFiredOnload, expectOnload,
- "onload should only fire when scripts are enabled");
- deferred.resolve();
- });
- return deferred.promise;
- }
- function checkScriptEnabled(win, expectEnabled) {
- win.wrappedJSObject.gFiredOnclick = false;
- win.document.body.dispatchEvent(new win.Event('click'));
- is(win.wrappedJSObject.gFiredOnclick, expectEnabled, "Checking script-enabled for " + win.name + " (" + win.location + ")");
- }
- function setScriptEnabledForDocShell(win, enabled) {
- win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDocShell)
- .allowJavascript = enabled;
- }
- function testList(expectEnabled, win, list, idx) {
- idx = idx || 0;
- let deferred = Promise.defer();
- let target = list[idx] + path;
- info("Testing scriptability for: " + target + ". expecting " + expectEnabled);
- navigateFrame(win.frameElement, target).then(function() {
- checkScriptEnabled(win, expectEnabled);
- if (idx == list.length - 1)
- deferred.resolve();
- else
- testList(expectEnabled, win, list, idx + 1).then(function() { deferred.resolve(); });
- });
- return deferred.promise;
- }
- function testDomainPolicy(defaultScriptability, exceptions, superExceptions,
- exempt, notExempt, set, superSet, win) {
- // Populate our sets.
- for (var e of exceptions)
- set.add(makeURI(e));
- for (var e of superExceptions)
- superSet.add(makeURI(e));
- return testList(defaultScriptability, win, notExempt).then(function() {
- return testList(!defaultScriptability, win, exempt);
- });
- }
- function setScriptEnabledForBrowser(enabled) {
- var prefname = "javascript.enabled";
- Services.prefs.setBoolPref(prefname, enabled);
- }
- function reloadFrame(frame) {
- let deferred = Promise.defer();
- frame.addEventListener('load', function onload() {
- deferred.resolve();
- frame.removeEventListener('load', onload);
- }, false);
- frame.contentWindow.location.reload(true);
- return deferred.promise;
- }
- function go() {
- var rootWin = rootFrame.contentWindow;
- var chromeWin = chromeFrame.contentWindow;
- // Test simple docshell enable/disable.
- checkScriptEnabled(rootWin, true);
- setScriptEnabledForDocShell(rootWin, false);
- checkScriptEnabled(rootWin, false);
- setScriptEnabledForDocShell(rootWin, true);
- checkScriptEnabled(rootWin, true);
- // Privileged frames are immune to docshell flags.
- ok(ssm.isSystemPrincipal(chromeWin.document.nodePrincipal), "Sanity check for System Principal");
- setScriptEnabledForDocShell(chromeWin, false);
- checkScriptEnabled(chromeWin, true);
- setScriptEnabledForDocShell(chromeWin, true);
- // Play around with the docshell tree and make sure everything works as
- // we expect.
- addFrame(rootWin, 'parent', true).then(function() {
- checkScriptEnabled(rootWin[0], true);
- return addFrame(rootWin[0], 'childA', true);
- }).then(function() {
- checkScriptEnabled(rootWin[0][0], true);
- setScriptEnabledForDocShell(rootWin[0], false);
- checkScriptEnabled(rootWin, true);
- checkScriptEnabled(rootWin[0], false);
- checkScriptEnabled(rootWin[0][0], false);
- return addFrame(rootWin[0], 'childB', false);
- }).then(function() {
- checkScriptEnabled(rootWin[0][1], false);
- setScriptEnabledForDocShell(rootWin[0][0], false);
- setScriptEnabledForDocShell(rootWin[0], true);
- checkScriptEnabled(rootWin[0], true);
- checkScriptEnabled(rootWin[0][0], false);
- setScriptEnabledForDocShell(rootWin[0][0], true);
- // Flags are inherited from the parent docshell at attach time. Note that
- // the flag itself is inherited, regardless of whether or not scripts are
- // currently allowed on the parent (which could depend on the parent's
- // parent). Check that.
- checkScriptEnabled(rootWin[0][1], false);
- setScriptEnabledForDocShell(rootWin[0], false);
- setScriptEnabledForDocShell(rootWin[0][1], true);
- return addFrame(rootWin[0][1], 'grandchild', false);
- }).then(function() {
- checkScriptEnabled(rootWin[0], false);
- checkScriptEnabled(rootWin[0][1], false);
- checkScriptEnabled(rootWin[0][1][0], false);
- setScriptEnabledForDocShell(rootWin[0], true);
- checkScriptEnabled(rootWin[0], true);
- checkScriptEnabled(rootWin[0][1], true);
- checkScriptEnabled(rootWin[0][1][0], true);
- // Try navigating two frames, then munging docshell scriptability, then
- // pulling the frames out of the bfcache to make sure that flags are
- // properly propagated to inactive inner windows. We do this both for an
- // 'own' docshell, as well as for an ancestor docshell.
- return navigateFrame(rootWin[0][0].frameElement, rootWin[0][0].location + '-navigated');
- }).then(function() { return navigateFrame(rootWin[0][1][0].frameElement, rootWin[0][1][0].location + '-navigated'); })
- .then(function() {
- checkScriptEnabled(rootWin[0][0], true);
- checkScriptEnabled(rootWin[0][1][0], true);
- setScriptEnabledForDocShell(rootWin[0][0], false);
- setScriptEnabledForDocShell(rootWin[0][1], false);
- checkScriptEnabled(rootWin[0][0], false);
- checkScriptEnabled(rootWin[0][1][0], false);
- return navigateBack(rootWin[0][0].frameElement);
- }).then(function() { return navigateBack(rootWin[0][1][0].frameElement); })
- .then(function() {
- checkScriptEnabled(rootWin[0][0], false);
- checkScriptEnabled(rootWin[0][1][0], false);
- // Disable JS via the global pref pref. This is only guaranteed to have an effect
- // for subsequent loads.
- setScriptEnabledForBrowser(false);
- return reloadFrame(rootFrame);
- }).then(function() {
- checkScriptEnabled(rootWin, false);
- checkScriptEnabled(chromeWin, true);
- setScriptEnabledForBrowser(true);
- return reloadFrame(rootFrame);
- }).then(function() {
- checkScriptEnabled(rootWin, true);
- // Play around with dynamically blocking script for a given global.
- // This takes effect immediately.
- Cu.blockScriptForGlobal(rootWin);
- Cu.blockScriptForGlobal(rootWin);
- Cu.unblockScriptForGlobal(rootWin);
- checkScriptEnabled(rootWin, false);
- Cu.unblockScriptForGlobal(rootWin);
- checkScriptEnabled(rootWin, true);
- Cu.blockScriptForGlobal(rootWin);
- try {
- Cu.blockScriptForGlobal(chromeWin);
- ok(false, "Should have thrown");
- } catch (e) {
- ok(/may not be disabled/.test(e),
- "Shouldn't be able to programmatically block script for system globals");
- }
- return reloadFrame(rootFrame);
- }).then(function() {
- checkScriptEnabled(rootWin, true);
- // Test system-wide domain policy. This only takes effect for subsequently-
- // loaded globals.
- // Check the basic semantics of the sets.
- is(ssm.domainPolicyActive, false, "not enabled");
- window.policy = ssm.activateDomainPolicy();
- ok(policy instanceof Ci.nsIDomainPolicy, "Got a policy");
- try {
- ssm.activateDomainPolicy();
- ok(false, "Should have thrown");
- } catch (e) {
- ok(true, "can't have two live domain policies");
- }
- var sbRef = policy.superBlacklist;
- isnot(sbRef, null, "superBlacklist non-null");
- ok(!sbRef.contains(makeURI('http://www.example.com')));
- sbRef.add(makeURI('http://www.example.com/foopy'));
- ok(sbRef.contains(makeURI('http://www.example.com')));
- sbRef.remove(makeURI('http://www.example.com'));
- ok(!sbRef.contains(makeURI('http://www.example.com')));
- sbRef.add(makeURI('http://www.example.com/foopy/this.that/'));
- ok(sbRef.contains(makeURI('http://www.example.com/baz')));
- ok(!sbRef.contains(makeURI('https://www.example.com')));
- ok(!sbRef.contains(makeURI('https://www.example.com:88')));
- ok(!sbRef.contains(makeURI('http://foo.www.example.com')));
- ok(sbRef.containsSuperDomain(makeURI('http://foo.www.example.com')));
- ok(sbRef.containsSuperDomain(makeURI('http://foo.bar.www.example.com')));
- ok(!sbRef.containsSuperDomain(makeURI('http://foo.bar.www.exxample.com')));
- ok(!sbRef.containsSuperDomain(makeURI('http://example.com')));
- ok(!sbRef.containsSuperDomain(makeURI('http://com/this.that/')));
- ok(!sbRef.containsSuperDomain(makeURI('https://foo.www.example.com')));
- ok(sbRef.contains(makeURI('http://www.example.com')));
- policy.deactivate();
- is(ssm.domainPolicyActive, false, "back to inactive");
- ok(!sbRef.contains(makeURI('http://www.example.com')),
- "Disabling domain policy clears the set");
- policy = ssm.activateDomainPolicy();
- ok(policy.superBlacklist);
- isnot(sbRef, policy.superBlacklist, "Mint new sets each time!");
- policy.deactivate();
- is(policy.blacklist, null, "blacklist nulled out");
- policy = ssm.activateDomainPolicy();
- isnot(policy.blacklist, null, "non-null again");
- isnot(policy.blacklist, sbRef, "freshly minted");
- policy.deactivate();
- //
- // Now, create and apply a mock-policy. We check the same policy both as
- // a blacklist and as a whitelist.
- //
- window.testPolicy = {
- // The policy.
- exceptions: ['http://test1.example.com', 'http://example.com'],
- superExceptions: ['http://test2.example.org', 'https://test1.example.com'],
- // The testcases.
- exempt: ['http://test1.example.com', 'http://example.com',
- 'http://test2.example.org', 'http://sub1.test2.example.org',
- 'https://sub1.test1.example.com'],
- notExempt: ['http://test2.example.com', 'http://sub1.test1.example.com',
- 'http://www.example.com', 'https://test2.example.com',
- 'https://example.com', 'http://test1.example.org'],
- };
- policy = ssm.activateDomainPolicy();
- info("Testing Blacklist-style Domain Policy");
- return testDomainPolicy(true, testPolicy.exceptions,
- testPolicy.superExceptions, testPolicy.exempt,
- testPolicy.notExempt, policy.blacklist,
- policy.superBlacklist, rootWin);
- }).then(function() {
- policy.deactivate();
- policy = ssm.activateDomainPolicy();
- info("Testing Whitelist-style Domain Policy");
- setScriptEnabledForBrowser(false);
- return testDomainPolicy(false, testPolicy.exceptions,
- testPolicy.superExceptions, testPolicy.exempt,
- testPolicy.notExempt, policy.whitelist,
- policy.superWhitelist, rootWin);
- }).then(function() {
- setScriptEnabledForBrowser(true);
- policy.deactivate();
- SimpleTest.finish();
- });
- }
- ]]>
- </script>
- </window>
|