Bug 840488 - Tests. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Tue, 12 Nov 2013 16:43:35 -0800
changeset 169382 cd0e2e0ef136b6bcfefaa695bd7909eb2504f9d3
parent 169381 9f9022aabfe9114c68879fd51660b2899ddf3c7c
child 169383 6f28e77e0a200c723b7ec0545e3a73a147ebe3e9
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs840488
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 840488 - Tests. r=bz
caps/tests/mochitest/Makefile.in
caps/tests/mochitest/chrome.ini
caps/tests/mochitest/file_disableScript.html
caps/tests/mochitest/mochitest.ini
caps/tests/mochitest/moz.build
caps/tests/mochitest/test_disableScript.xul
deleted file mode 100644
--- a/caps/tests/mochitest/Makefile.in
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# 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/.
-
-# jarPrefix test doesn't work on Windows, see bug 776296.
-ifneq ($(OS_ARCH),WINNT)
-MOCHITEST_CHROME_FILES = test_principal_jarprefix_origin_appid_appstatus.html \
-                         $(NULL)
-endif
new file mode 100644
--- /dev/null
+++ b/caps/tests/mochitest/chrome.ini
@@ -0,0 +1,4 @@
+[test_disableScript.xul]
+[test_principal_jarprefix_origin_appid_appstatus.html]
+# jarPrefix test doesn't work on Windows, see bug 776296.
+skip-if = os == "win"
new file mode 100644
--- /dev/null
+++ b/caps/tests/mochitest/file_disableScript.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+var gFiredOnload = false;
+var gFiredOnclick = false;
+</script>
+</head>
+<body onload="gFiredOnload = true;" onclick="gFiredOnclick = true;">
+</body>
+</html>
--- a/caps/tests/mochitest/mochitest.ini
+++ b/caps/tests/mochitest/mochitest.ini
@@ -1,8 +1,10 @@
 [DEFAULT]
+support-files =
+  file_disableScript.html
 
 [test_app_principal_equality.html]
 [test_bug246699.html]
 [test_bug292789.html]
 [test_bug423375.html]
 [test_bug470804.html]
 [test_disallowInheritPrincipal.html]
--- a/caps/tests/mochitest/moz.build
+++ b/caps/tests/mochitest/moz.build
@@ -1,8 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 MOCHITEST_MANIFESTS += ['mochitest.ini']
+MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
 
new file mode 100644
--- /dev/null
+++ b/caps/tests/mochitest/test_disableScript.xul
@@ -0,0 +1,321 @@
+<?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" onload="go();" 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');
+  rootFrame.setAttribute('src', uri + "?name=rootframe");
+
+  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(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) {
+    let 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() {
+    rootFrame.setAttribute('onload', null);
+
+    // Test simple docshell enable/disable.
+    var rootWin = rootFrame.contentWindow;
+    checkScriptEnabled(rootWin, true);
+    setScriptEnabledForDocShell(rootWin, false);
+    checkScriptEnabled(rootWin, false);
+    setScriptEnabledForDocShell(rootWin, true);
+    checkScriptEnabled(rootWin, 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);
+      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);
+      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>