Bug 774633 - Assert against switching origins on a compartment. r=jst
authorBobby Holley <bobbyholley@gmail.com>
Thu, 23 Aug 2012 16:44:53 -0700
changeset 105282 036eb8c2a08afd909c05101c0fccc92dee2d15bc
parent 105281 d4d36e3b948f7b8527247433c2e1effb2de71016
child 105283 4ad52e488977dd381d2bf96ede2687e9b7f86363
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersjst
bugs774633
milestone17.0a1
Bug 774633 - Assert against switching origins on a compartment. r=jst
dom/base/nsGlobalWindow.cpp
js/src/jsfriendapi.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1879,17 +1879,25 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       return NS_ERROR_FAILURE;
     }
 
     // Inner windows are only reused for same-origin principals, but the principals
     // don't necessarily match exactly. Update the principal on the compartment to
     // match the new document.
     // NB: We don't just call currentInner->RefreshCompartmentPrincipals() here
     // because we haven't yet set its mDoc to aDocument.
-    JS_SetCompartmentPrincipals(js::GetObjectCompartment(currentInner->mJSObject),
+    JSCompartment *compartment = js::GetObjectCompartment(currentInner->mJSObject);
+#ifdef DEBUG
+    bool sameOrigin = false;
+    nsIPrincipal *existing =
+      nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment));
+    aDocument->NodePrincipal()->Equals(existing, &sameOrigin);
+    MOZ_ASSERT(sameOrigin);
+#endif
+    JS_SetCompartmentPrincipals(compartment,
                                 nsJSPrincipals::get(aDocument->NodePrincipal()));
   } else {
     if (aState) {
       newInnerWindow = wsh->GetInnerWindow();
       mInnerWindowHolder = wsh->GetInnerWindowHolder();
 
       NS_ASSERTION(newInnerWindow, "Got a state without inner window");
     } else if (thisChrome) {
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -191,32 +191,40 @@ JS_GetCompartmentPrincipals(JSCompartmen
 
 JS_FRIEND_API(void)
 JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals)
 {
     // Short circuit if there's no change.
     if (principals == compartment->principals)
         return;
 
+    // Any compartment with the trusted principals -- and there can be
+    // multiple -- is a system compartment.
+    JSPrincipals *trusted = compartment->rt->trustedPrincipals();
+    bool isSystem = principals && principals == trusted;
+
     // Clear out the old principals, if any.
     if (compartment->principals) {
         JS_DropPrincipals(compartment->rt, compartment->principals);
         compartment->principals = NULL;
+        // We'd like to assert that our new principals is always same-origin
+        // with the old one, but JSPrincipals doesn't give us a way to do that.
+        // But we can at least assert that we're not switching between system
+        // and non-system.
+        JS_ASSERT(compartment->isSystemCompartment == isSystem);
     }
 
     // Set up the new principals.
     if (principals) {
         JS_HoldPrincipals(principals);
         compartment->principals = principals;
     }
 
-    // Any compartment with the trusted principals -- and there can be
-    // multiple -- is a system compartment.
-    JSPrincipals *trusted = compartment->rt->trustedPrincipals();
-    compartment->isSystemCompartment = principals && principals == trusted;
+    // Update the system flag.
+    compartment->isSystemCompartment = isSystem;
 }
 
 JS_FRIEND_API(JSBool)
 JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc)
 {
     return cx->compartment->wrap(cx, desc);
 }