Bug 972478 - Docshell scriptability should only affect non-immune principals. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Thu, 13 Feb 2014 15:40:50 -0800
changeset 168713 60e089842cb60a584a3ef4dede84e9520c20d54c
parent 168712 5d57e7e2dfe44ef35cc3b7d78f434bab4ec7adeb
child 168714 4779f288cf6e26881919c2e0ed4772479d3000cd
push id26215
push userryanvm@gmail.com
push dateFri, 14 Feb 2014 13:54:11 +0000
treeherdermozilla-central@5d7caa093f4f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs972478
milestone30.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 972478 - Docshell scriptability should only affect non-immune principals. r=bz
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
@@ -486,17 +486,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;
 }