Bug 723808: disallow inheriting of system principal in type=content docshells, r=bz, a=lsblakk
authorGavin Sharp <gavin@gavinsharp.com>
Mon, 05 Mar 2012 16:24:38 -0800
changeset 35276 855980ed722d
parent 35275 c23ed8a949b2
child 35277 f66f339fd046
push id2031
push usergsharp@mozilla.com
push date2012-03-06 00:27 +0000
reviewersbz, lsblakk
bugs723808
milestone1.9.2.28pre
Bug 723808: disallow inheriting of system principal in type=content docshells, r=bz, a=lsblakk
docshell/base/nsDocShell.cpp
docshell/test/chrome/Makefile.in
docshell/test/chrome/test_principalInherit.xul
dom/tests/mochitest/chrome/window_focus.xul
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -8082,23 +8082,25 @@ nsDocShell::InternalLoad(nsIURI * aURI,
 
     return rv;
 }
 
 nsIPrincipal*
 nsDocShell::GetInheritedPrincipal(PRBool aConsiderCurrentDocument)
 {
     nsCOMPtr<nsIDocument> document;
+    PRBool inheritedFromCurrent = PR_FALSE;
 
     if (aConsiderCurrentDocument && mContentViewer) {
         nsCOMPtr<nsIDocumentViewer>
             docViewer(do_QueryInterface(mContentViewer));
         if (!docViewer)
             return nsnull;
         docViewer->GetDocument(getter_AddRefs(document));
+        inheritedFromCurrent = PR_TRUE;
     }
 
     if (!document) {
         nsCOMPtr<nsIDocShellTreeItem> parentItem;
         GetSameTypeParent(getter_AddRefs(parentItem));
         if (parentItem) {
             nsCOMPtr<nsIDOMDocument> parentDomDoc(do_GetInterface(parentItem));
             document = do_QueryInterface(parentDomDoc);
@@ -8119,17 +8121,27 @@ nsDocShell::GetInheritedPrincipal(PRBool
             docViewer(do_QueryInterface(mContentViewer));
         if (!docViewer)
             return nsnull;
         docViewer->GetDocument(getter_AddRefs(document));
     }
 
     //-- Get the document's principal
     if (document) {
-        return document->NodePrincipal();
+        nsIPrincipal *docPrincipal = document->NodePrincipal();
+
+        // Don't allow loads in typeContent docShells to inherit the system
+        // principal from existing documents.
+        if (inheritedFromCurrent &&
+            mItemType == typeContent &&
+            nsContentUtils::IsSystemPrincipal(docPrincipal)) {
+            return nsnull;
+        }
+
+        return docPrincipal;
     }
 
     return nsnull;
 }
 
 PRBool
 nsDocShell::ShouldCheckAppCache(nsIURI *aURI)
 {
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -97,16 +97,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug428288.html \
 		test_bug449778.xul \
 		bug449778_window.xul \
 		test_bug449780.xul \
 		bug449780_window.xul \
 		test_bug454235.xul \
 		bug454235-subframe.xul \
 		test_bug456980.xul \
+		test_principalInherit.xul \
 		$(NULL)
 
 _DOCSHELL_SUBHARNESS = \
     docshell_helpers.js \
     generic.html \
     $(NULL)
 
 libs:: $(_HTTP_FILES)
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_principalInherit.xul
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+  href="chrome://mochikit/content/tests/SimpleTest/test.css"
+  type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=719994
+-->
+<window title="Test principal inheriting"
+  xmlns:html="http://www.w3.org/1999/xhtml"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <title>Test principal inheriting</title>
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 719994 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gFrame;
+
+// This test file is loaded in a type=content docshell whose principal is
+// the system principal.
+
+// Using data: URIs here instead of javascript: URIs, since javascript: URIs
+// fail to load when there's no principal to load them against. This only
+// matters when these tests fail (produces better error messages).
+var tests = [
+  function testInheritFromParent(cb) {
+    gFrame = document.createElement("iframe");
+    loadListener(gFrame, function () {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      is(window.inheritedFromParent, true, "load in type=content iframe inherited principal of same type parent");
+      cb();
+    });
+    gFrame.setAttribute("type", "content");
+    gFrame.setAttribute("src", "data:text/html,<script>parent.inheritedFromParent = true;</script>");
+    document.documentElement.appendChild(gFrame);
+  },
+  function testInheritFromCurrent_system(cb) {
+    loadListener(gFrame, function () {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      is(window.inheritedSystem, undefined, "load in type=content iframe shouldn't inherit system principal from current document");
+      cb();
+    }, true);
+    gFrame.setAttribute("src", "data:text/html,<script>parent.inheritedSystem = true;</script>");
+  }
+];
+
+addLoadEvent(function onLoad() {
+  SimpleTest.executeSoon(nextTest);
+});
+
+function loadListener(target, func) {
+  target.addEventListener("load", function lis() {
+    target.removeEventListener("load", lis, true);
+    func();
+  }, true);
+}
+
+function nextTest() {
+  if (tests.length) {
+    let test = tests.shift();
+    SimpleTest.executeSoon(function () {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+      ok(Components.stack, "this test must be run with the system principal");
+      test(nextTest);
+    });
+  } else
+    SimpleTest.executeSoon(SimpleTest.finish);
+}
+
+]]>
+</script>
+
+</window>
--- a/dom/tests/mochitest/chrome/window_focus.xul
+++ b/dom/tests/mochitest/chrome/window_focus.xul
@@ -1432,30 +1432,25 @@ function doFrameSwitchingTests()
   doFrameHistoryTests()
 }
 
 function doFrameHistoryTests()
 {
   var t20 = getById("t20");
   t20.focus();
 
-  addEventListener("message", function() { $("childframe").goBack(); }, true);
   gChildWindow.addEventListener("focus",
     function(event) {
       if (event.target == t20) {
         is(fm.focusedElement, t20, "focus restored after history back"); done();
     }
   }, true);
 
   // make sure that loading a new page and then going back maintains the focus
-  gChildWindow.location = "data:text/html,<html><body onload='window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)." +
-                          "getInterface(Components.interfaces.nsIWebNavigation)." +
-                          "QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem." +
-                          "QueryInterface(Components.interfaces.nsIInterfaceRequestor)." +
-                          "getInterface(Components.interfaces.nsIDOMWindow).postMessage(\"content loaded\", \"*\");'>Next</body></html>";
+  gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () {window.back();}, 0);}</script>";
 }
 
 function addFrameSwitchingListeners(frame)
 {
   frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false);
   frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false);
   frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false);
   frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false);