Bug 972478 - Docshell scriptability should only affect non-immune principals. r=bz, a=lsblakk
authorBobby Holley <bobbyholley@gmail.com>
Thu, 13 Feb 2014 15:40:50 -0800
changeset 176313 7e47e1271dd5615d07ae29b7fa512bb211f5a541
parent 176312 cc9e070dd294a8b8b13f988e16821ce8668a77c9
child 176314 4a14fddfebe9da8507486d76cf48051861bbbf1a
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, lsblakk
bugs972478
milestone28.0
Bug 972478 - Docshell scriptability should only affect non-immune principals. r=bz, a=lsblakk
caps/tests/mochitest/chrome.ini
caps/tests/mochitest/test_disableScript.xul
js/xpconnect/src/XPCJSRuntime.cpp
--- a/caps/tests/mochitest/chrome.ini
+++ b/caps/tests/mochitest/chrome.ini
@@ -1,4 +1,8 @@
+[DEFAULT]
+support-files =
+  file_disableScript.html
+
 [test_disableScript.xul]
 [test_principal_jarprefix_origin_appid_appstatus.html]
 # jarPrefix test doesn't work on Windows, see bug 776296.
 skip-if = os == "win"
--- a/caps/tests/mochitest/test_disableScript.xul
+++ b/caps/tests/mochitest/test_disableScript.xul
@@ -9,17 +9,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <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"/>
+  <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();
@@ -27,17 +28,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   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");
+  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);
@@ -132,26 +136,32 @@ https://bugzilla.mozilla.org/show_bug.cg
       deferred.resolve();
       frame.removeEventListener('load', onload);
     }, false);
     frame.contentWindow.location.reload(true);
     return deferred.promise;
   }
 
   function go() {
-    rootFrame.setAttribute('onload', null);
+    var rootWin = rootFrame.contentWindow;
+    var chromeWin = chromeFrame.contentWindow;
 
     // Test simple docshell enable/disable.
-    var rootWin = rootFrame.contentWindow;
     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);
@@ -204,30 +214,38 @@ https://bugzilla.mozilla.org/show_bug.cg
       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.
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -484,17 +484,17 @@ Scriptability::Unblock()
 {
     MOZ_ASSERT(mScriptBlocks > 0);
     --mScriptBlocks;
 }
 
 void
 Scriptability::SetDocShellAllowsScript(bool aAllowed)
 {
-    mDocShellAllowsScript = aAllowed;
+    mDocShellAllowsScript = aAllowed || mImmuneToScriptPolicy;
 }
 
 /* static */
 Scriptability&
 Scriptability::Get(JSObject *aScope)
 {
     return EnsureCompartmentPrivate(aScope)->scriptability;
 }