Bug 732209 part 6. Allow web pages to access cross-origin stylesheets if the CORS headers say so. r=dbaron,sicking
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 28 Aug 2012 13:10:09 -0400
changeset 110544 62b86f439a09333d52db9d69e2023a1b0002fbc5
parent 110543 4af1510fc1c2f8e4ac154e5d5724c9a56e2e3135
child 110545 cfd19083d2989e51e367f6ff0d9341ad3e8b2c75
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, sicking
bugs732209
milestone18.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 732209 part 6. Allow web pages to access cross-origin stylesheets if the CORS headers say so. r=dbaron,sicking When gaining such access, the web page resets the stylesheet to its principal, because it can now edit the sheet.
layout/style/nsCSSStyleSheet.cpp
layout/style/nsCSSStyleSheet.h
layout/style/test/test_bug732209.html
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -1584,17 +1584,17 @@ void
 nsCSSStyleSheet::DidDirty()
 {
   NS_ABORT_IF_FALSE(!mInner->mComplete || mDirty,
                     "caller must have called WillDirty()");
   ClearRuleCascades();
 }
 
 nsresult
-nsCSSStyleSheet::SubjectSubsumesInnerPrincipal() const
+nsCSSStyleSheet::SubjectSubsumesInnerPrincipal()
 {
   // Get the security manager and do the subsumes check
   nsIScriptSecurityManager *securityManager =
     nsContentUtils::GetSecurityManager();
 
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
   nsresult rv = securityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1607,17 +1607,36 @@ nsCSSStyleSheet::SubjectSubsumesInnerPri
   rv = subjectPrincipal->Subsumes(mInner->mPrincipal, &subsumes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (subsumes) {
     return NS_OK;
   }
   
   if (!nsContentUtils::IsCallerTrustedForWrite()) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+    // Allow access only if CORS mode is not NONE
+    if (GetCORSMode() == CORS_NONE) {
+      return NS_ERROR_DOM_SECURITY_ERR;
+    }
+
+    // Now make sure we set the principal of our inner to the
+    // subjectPrincipal.  That means we need a unique inner, of
+    // course.  But we don't want to do that if we're not complete
+    // yet.  Luckily, all the callers of this method throw anyway if
+    // not complete, so we can just do that here too.
+    if (!mInner->mComplete) {
+      return NS_ERROR_DOM_INVALID_ACCESS_ERR;
+    }
+
+    rv = WillDirty();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    mInner->mPrincipal = subjectPrincipal;
+
+    DidDirty();
   }
 
   return NS_OK;
 }
 
 nsresult
 nsCSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
 {
--- a/layout/style/nsCSSStyleSheet.h
+++ b/layout/style/nsCSSStyleSheet.h
@@ -260,18 +260,19 @@ protected:
 
   void ClearRuleCascades();
 
   nsresult WillDirty();
   void     DidDirty();
 
   // Return success if the subject principal subsumes the principal of our
   // inner, error otherwise.  This will also succeed if the subject has
-  // UniversalXPConnect.
-  nsresult SubjectSubsumesInnerPrincipal() const;
+  // UniversalXPConnect or if access is allowed by CORS.  In the latter case,
+  // it will set the principal of the inner to the subject principal.
+  nsresult SubjectSubsumesInnerPrincipal();
 
   // Add the namespace mapping from this @namespace rule to our namespace map
   nsresult RegisterNamespaceRule(mozilla::css::Rule* aRule);
 
 protected:
   nsString              mTitle;
   nsRefPtr<nsMediaList> mMedia;
   nsRefPtr<nsCSSStyleSheet> mNext;
--- a/layout/style/test/test_bug732209.html
+++ b/layout/style/test/test_bug732209.html
@@ -22,17 +22,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet"
         href="http://example.com/tests/layout/style/test/bug732209-css.sjs?five"
         crossorigin>
   <link rel="stylesheet"
         href="http://example.com/tests/layout/style/test/bug732209-css.sjs?six"
         crossorigin="use-credentials">
   <link rel="stylesheet"
         href="http://example.com/tests/layout/style/test/bug732209-css.sjs?seven&cors-anonymous">
-  <link rel="stylesheet"
+  <link rel="stylesheet" id="cross-origin-sheet"
         href="http://example.com/tests/layout/style/test/bug732209-css.sjs?eight&cors-anonymous"
         crossorigin>
   <link rel="stylesheet"
         href="http://example.com/tests/layout/style/test/bug732209-css.sjs?nine&cors-anonymous"
         crossorigin="use-credentials">
   <link rel="stylesheet"
         href="http://example.com/tests/layout/style/test/bug732209-css.sjs?ten&cors-credentials">
   <link rel="stylesheet"
@@ -66,16 +66,29 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   var spans = $("content").querySelectorAll("span");
   for (var i = 0; i < spans.length; ++i) {
     is(getComputedStyle(spans[i], "").color, "rgb(0, 128, 0)",
        "Span " + spans[i].id + " should be green");
   }
+
+  try {
+    var sheet = $("cross-origin-sheet").sheet;
+    dump('aaa');
+    is(sheet.cssRules.length, 2,
+       "Should be able to get length of list of rules");
+    is(sheet.cssRules[0].style.color, "green",
+       "Should be able to read individual rules");
+  } catch (e) {
+    ok(false,
+       "Should be allowed to access cross-origin sheet that opted in with CORS: " + e);
+  }
+
   SimpleTest.finish();
 });
 
 
 
 </script>
 </pre>
 </body>