Bug 1195173 - Apply CSP to preloaded styles within layout/style/Loader.cpp (r=bz)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Tue, 02 Feb 2016 20:35:30 -0800
changeset 282781 4ae3c98861568c74e586ed726c68423be2dbd680
parent 282780 a1a1dca9e27aa582bd68a170b066312fe2ffca77
child 282782 94c27b21c934f0cc178e896587532d7cc0b4c60c
push id71314
push usermozilla@christophkerschbaumer.com
push dateWed, 03 Feb 2016 04:47:37 +0000
treeherdermozilla-inbound@94c27b21c934 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1195173
milestone47.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 1195173 - Apply CSP to preloaded styles within layout/style/Loader.cpp (r=bz)
layout/style/Loader.cpp
layout/style/Loader.h
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1010,16 +1010,42 @@ Loader::ObsoleteSheet(nsIURI* aURI)
     nsresult rv = sheetURI->Equals(aURI, &areEqual);
     if (NS_SUCCEEDED(rv) && areEqual) {
       iter.Remove();
     }
   }
   return NS_OK;
 }
 
+nsresult
+Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
+                          nsIURI* aTargetURI,
+                          nsISupports* aContext,
+                          bool aIsPreload)
+{
+  nsContentPolicyType contentPolicyType =
+    aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
+               : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
+
+  int16_t shouldLoad = nsIContentPolicy::ACCEPT;
+  nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
+                                          aTargetURI,
+                                          aSourcePrincipal,
+                                          aContext,
+                                          NS_LITERAL_CSTRING("text/css"),
+                                          nullptr,  //extra param
+                                          &shouldLoad,
+                                          nsContentUtils::GetContentPolicy(),
+                                          nsContentUtils::GetSecurityManager());
+   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+     return NS_ERROR_CONTENT_BLOCKED;
+   }
+   return NS_OK;
+}
+
 /**
  * CreateSheet() creates a CSSStyleSheet object for the given URI,
  * if any.  If there is no URI given, we just create a new style sheet
  * object.  Otherwise, we check for an existing style sheet object for
  * that uri in various caches and clone it if we find it.  Cloned
  * sheets will have the title/media/enabled state of the sheet they
  * are clones off; make sure to call PrepareSheet() on the result of
  * CreateSheet().
@@ -1988,22 +2014,25 @@ Loader::LoadStyleLink(nsIContent* aEleme
   nsIPrincipal* principal =
     aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
 
   nsISupports* context = aElement;
   if (!context) {
     context = mDocument;
   }
 
+  nsresult rv = CheckContentPolicy(principal, aURL, context, false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   StyleSheetState state;
   RefPtr<CSSStyleSheet> sheet;
-  nsresult rv = CreateSheet(aURL, aElement, principal, aCORSMode,
-                            aReferrerPolicy, aIntegrity, false,
-                            aHasAlternateRel, aTitle, state, aIsAlternate,
-                            getter_AddRefs(sheet));
+  rv = CreateSheet(aURL, aElement, principal, aCORSMode,
+                   aReferrerPolicy, aIntegrity, false,
+                   aHasAlternateRel, aTitle, state, aIsAlternate,
+                   getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   LOG(("  Sheet is alternate: %d", *aIsAlternate));
 
   PrepareSheet(sheet, aTitle, aMedia, nullptr, nullptr, *aIsAlternate);
 
   rv = InsertSheetInDoc(sheet, aElement, mDocument);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -2117,16 +2146,20 @@ Loader::LoadChildSheet(CSSStyleSheet* aP
     topSheet->GetOwnerNode(getter_AddRefs(owningNode));
   }
 
   nsISupports* context = owningNode;
   if (!context) {
     context = mDocument;
   }
 
+  nsIPrincipal* principal = aParentSheet->Principal();
+  nsresult rv = CheckContentPolicy(principal, aURL, context, false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   SheetLoadData* parentData = nullptr;
   nsCOMPtr<nsICSSLoaderObserver> observer;
 
   int32_t count = mParsingDatas.Length();
   if (count > 0) {
     LOG(("  Have a parent load"));
     parentData = mParsingDatas.ElementAt(count - 1);
     // Check for cycles
@@ -2143,19 +2176,17 @@ Loader::LoadChildSheet(CSSStyleSheet* aP
     LOG(("  No parent load; must be CSSOM"));
     // No parent load data, so the sheet will need to be notified when
     // we finish, if it can be, if we do the load asynchronously.
     observer = aParentSheet;
   }
 
   // Now that we know it's safe to load this (passes security check and not a
   // loop) do so.
-  nsIPrincipal* principal = aParentSheet->Principal();
   RefPtr<CSSStyleSheet> sheet;
-  nsresult rv;
   StyleSheetState state;
   if (aReusableSheets && aReusableSheets->FindReusableStyleSheet(aURL, sheet)) {
     aParentRule->SetSheet(sheet);
     state = eSheetComplete;
   } else {
     bool isAlternate;
     const nsSubstring& empty = EmptyString();
     // For now, use CORS_NONE for child sheets
@@ -2269,22 +2300,24 @@ Loader::InternalLoadNonDocumentSheet(nsI
     *aSheet = nullptr;
   }
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  nsresult rv = CheckContentPolicy(aOriginPrincipal, aURL, mDocument, aIsPreload);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   StyleSheetState state;
   bool isAlternate;
   RefPtr<CSSStyleSheet> sheet;
   bool syncLoad = (aObserver == nullptr);
   const nsSubstring& empty = EmptyString();
-  nsresult rv;
 
   rv = CreateSheet(aURL, nullptr, aOriginPrincipal, aCORSMode,
                    aReferrerPolicy, aIntegrity, syncLoad, false,
                    empty, state, &isAlternate, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PrepareSheet(sheet, empty, empty, nullptr, nullptr, isAlternate);
 
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -436,16 +436,21 @@ public:
 
   // Marks all the sheets at the given URI obsolete, and removes them from the
   // cache.
   nsresult ObsoleteSheet(nsIURI* aURI);
 
 private:
   friend class SheetLoadData;
 
+  nsresult CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
+                              nsIURI* aTargetURI,
+                              nsISupports* aContext,
+                              bool aIsPreload);
+
   // For inline style, the aURI param is null, but the aLinkingContent
   // must be non-null then.  The loader principal must never be null
   // if aURI is not null.
   // *aIsAlternate is set based on aTitle and aHasAlternateRel.
   nsresult CreateSheet(nsIURI* aURI,
                        nsIContent* aLinkingContent,
                        nsIPrincipal* aLoaderPrincipal,
                        CORSMode aCORSMode,