Bug 1048048 - add preload content policy types (r=ehsan)
authorChristoph Kerschbaumer <mozilla@christophkerschbaumer.com>
Sun, 20 Sep 2015 14:55:44 -0700
changeset 263637 94c62c16128d9f4aedd1a1b776983b94bec84f80
parent 263636 56058bf8ec8c78c97429fa100213c666eca01b85
child 263638 54777c071b5d72871fa640c917adf345866bb779
push id29415
push usercbook@mozilla.com
push dateTue, 22 Sep 2015 10:41:24 +0000
treeherdermozilla-central@a1ccea59e254 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1048048
milestone43.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 1048048 - add preload content policy types (r=ehsan)
dom/base/nsContentPolicy.cpp
dom/base/nsContentPolicyUtils.h
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsIContentPolicy.idl
dom/base/nsIContentPolicyBase.idl
dom/cache/DBSchema.cpp
dom/fetch/InternalRequest.cpp
dom/fetch/InternalRequest.h
--- a/dom/base/nsContentPolicy.cpp
+++ b/dom/base/nsContentPolicy.cpp
@@ -8,16 +8,17 @@
  * Implementation of the "@mozilla.org/layout/content-policy;1" contract.
  */
 
 #include "mozilla/Logging.h"
 
 #include "nsISupports.h"
 #include "nsXPCOM.h"
 #include "nsContentPolicyUtils.h"
+#include "mozilla/dom/nsCSPService.h"
 #include "nsContentPolicy.h"
 #include "nsIURI.h"
 #include "nsIDocShell.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMWindow.h"
 #include "nsIContent.h"
 #include "nsILoadContext.h"
@@ -118,19 +119,25 @@ nsContentPolicy::CheckPolicy(CPMethod   
     }
 
     nsContentPolicyType externalType =
         nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
 
     nsContentPolicyType externalTypeOrScript =
         nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType);
 
+    nsContentPolicyType externalTypeOrPreload =
+       nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(contentType);
+
     nsCOMPtr<nsIContentPolicy> mixedContentBlocker =
         do_GetService(NS_MIXEDCONTENTBLOCKER_CONTRACTID);
 
+    nsCOMPtr<nsIContentPolicy> cspService =
+      do_GetService(CSPSERVICE_CONTRACTID);
+
     /* 
      * Enumerate mPolicies and ask each of them, taking the logical AND of
      * their permissions.
      */
     nsresult rv;
     nsCOMArray<nsIContentPolicy> entries;
     mPolicies.GetEntries(entries);
     int32_t count = entries.Count();
@@ -139,16 +146,25 @@ nsContentPolicy::CheckPolicy(CPMethod   
         // Send the internal content policy type to the mixed content blocker
         // which needs to know about TYPE_INTERNAL_WORKER,
         // TYPE_INTERNAL_SHARED_WORKER and TYPE_INTERNAL_SERVICE_WORKER.
         bool isMixedContentBlocker = mixedContentBlocker == entries[i];
         nsContentPolicyType type = externalType;
         if (isMixedContentBlocker) {
             type = externalTypeOrScript;
         }
+        // Send the internal content policy type for CSP which needs to
+        // know about preloads, in particular:
+        // * TYPE_INTERNAL_SCRIPT_PRELOAD
+        // * TYPE_INTERNAL_IMAGE_PRELOAD
+        // * TYPE_INTERNAL_STYLESHEET_PRELOAD
+        bool isCSP = cspService == entries[i];
+        if (isCSP) {
+          type = externalTypeOrPreload;
+        }
         rv = (entries[i]->*policyMethod)(type, contentLocation,
                                          requestingLocation, requestingContext,
                                          mimeType, extra, requestPrincipal,
                                          decision);
 
         if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
             /* policy says no, no point continuing to check */
             return NS_OK;
--- a/dom/base/nsContentPolicyUtils.h
+++ b/dom/base/nsContentPolicyUtils.h
@@ -87,51 +87,56 @@ NS_CP_ResponseName(int16_t response)
  *
  * @param contentType the content type code
  * @return the name of the given content type code
  */
 inline const char *
 NS_CP_ContentTypeName(uint32_t contentType)
 {
   switch (contentType) {
-    CASE_RETURN( TYPE_OTHER                   );
-    CASE_RETURN( TYPE_SCRIPT                  );
-    CASE_RETURN( TYPE_IMAGE                   );
-    CASE_RETURN( TYPE_STYLESHEET              );
-    CASE_RETURN( TYPE_OBJECT                  );
-    CASE_RETURN( TYPE_DOCUMENT                );
-    CASE_RETURN( TYPE_SUBDOCUMENT             );
-    CASE_RETURN( TYPE_REFRESH                 );
-    CASE_RETURN( TYPE_XBL                     );
-    CASE_RETURN( TYPE_PING                    );
-    CASE_RETURN( TYPE_XMLHTTPREQUEST          );
-    CASE_RETURN( TYPE_OBJECT_SUBREQUEST       );
-    CASE_RETURN( TYPE_DTD                     );
-    CASE_RETURN( TYPE_FONT                    );
-    CASE_RETURN( TYPE_MEDIA                   );
-    CASE_RETURN( TYPE_WEBSOCKET               );
-    CASE_RETURN( TYPE_CSP_REPORT              );
-    CASE_RETURN( TYPE_XSLT                    );
-    CASE_RETURN( TYPE_BEACON                  );
-    CASE_RETURN( TYPE_FETCH                   );
-    CASE_RETURN( TYPE_IMAGESET                );
-    CASE_RETURN( TYPE_WEB_MANIFEST            );
-    CASE_RETURN( TYPE_INTERNAL_SCRIPT         );
-    CASE_RETURN( TYPE_INTERNAL_WORKER         );
-    CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER  );
-    CASE_RETURN( TYPE_INTERNAL_EMBED          );
-    CASE_RETURN( TYPE_INTERNAL_OBJECT         );
-    CASE_RETURN( TYPE_INTERNAL_FRAME          );
-    CASE_RETURN( TYPE_INTERNAL_IFRAME         );
-    CASE_RETURN( TYPE_INTERNAL_AUDIO          );
-    CASE_RETURN( TYPE_INTERNAL_VIDEO          );
-    CASE_RETURN( TYPE_INTERNAL_TRACK          );
-    CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST );
-    CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE    );
-    CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER );
+    CASE_RETURN( TYPE_OTHER                       );
+    CASE_RETURN( TYPE_SCRIPT                      );
+    CASE_RETURN( TYPE_IMAGE                       );
+    CASE_RETURN( TYPE_STYLESHEET                  );
+    CASE_RETURN( TYPE_OBJECT                      );
+    CASE_RETURN( TYPE_DOCUMENT                    );
+    CASE_RETURN( TYPE_SUBDOCUMENT                 );
+    CASE_RETURN( TYPE_REFRESH                     );
+    CASE_RETURN( TYPE_XBL                         );
+    CASE_RETURN( TYPE_PING                        );
+    CASE_RETURN( TYPE_XMLHTTPREQUEST              );
+    CASE_RETURN( TYPE_OBJECT_SUBREQUEST           );
+    CASE_RETURN( TYPE_DTD                         );
+    CASE_RETURN( TYPE_FONT                        );
+    CASE_RETURN( TYPE_MEDIA                       );
+    CASE_RETURN( TYPE_WEBSOCKET                   );
+    CASE_RETURN( TYPE_CSP_REPORT                  );
+    CASE_RETURN( TYPE_XSLT                        );
+    CASE_RETURN( TYPE_BEACON                      );
+    CASE_RETURN( TYPE_FETCH                       );
+    CASE_RETURN( TYPE_IMAGESET                    );
+    CASE_RETURN( TYPE_WEB_MANIFEST                );
+    CASE_RETURN( TYPE_INTERNAL_SCRIPT             );
+    CASE_RETURN( TYPE_INTERNAL_WORKER             );
+    CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER      );
+    CASE_RETURN( TYPE_INTERNAL_EMBED              );
+    CASE_RETURN( TYPE_INTERNAL_OBJECT             );
+    CASE_RETURN( TYPE_INTERNAL_FRAME              );
+    CASE_RETURN( TYPE_INTERNAL_IFRAME             );
+    CASE_RETURN( TYPE_INTERNAL_AUDIO              );
+    CASE_RETURN( TYPE_INTERNAL_VIDEO              );
+    CASE_RETURN( TYPE_INTERNAL_TRACK              );
+    CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST     );
+    CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE        );
+    CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER     );
+    CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD     );
+    CASE_RETURN( TYPE_INTERNAL_IMAGE              );
+    CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD      );
+    CASE_RETURN( TYPE_INTERNAL_STYLESHEET         );
+    CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD );
    default:
     return "<Unknown Type>";
   }
 }
 
 #undef CASE_RETURN
 
 /* Passes on parameters from its "caller"'s context. */
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7954,16 +7954,17 @@ nsContentUtils::GetWindowRoot(nsIDocumen
 }
 
 /* static */
 nsContentPolicyType
 nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
 {
   switch (aType) {
   case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
+  case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
   case nsIContentPolicy::TYPE_INTERNAL_WORKER:
   case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
   case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
     return nsIContentPolicy::TYPE_SCRIPT;
 
   case nsIContentPolicy::TYPE_INTERNAL_EMBED:
   case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
     return nsIContentPolicy::TYPE_OBJECT;
@@ -7976,16 +7977,24 @@ nsContentUtils::InternalContentPolicyTyp
   case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
   case nsIContentPolicy::TYPE_INTERNAL_TRACK:
     return nsIContentPolicy::TYPE_MEDIA;
 
   case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST:
   case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
     return nsIContentPolicy::TYPE_XMLHTTPREQUEST;
 
+  case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
+  case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
+    return nsIContentPolicy::TYPE_IMAGE;
+
+  case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
+  case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
+    return nsIContentPolicy::TYPE_STYLESHEET;
+
   default:
     return aType;
   }
 }
 
 /* static */
 nsContentPolicyType
 nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType)
@@ -7997,16 +8006,27 @@ nsContentUtils::InternalContentPolicyTyp
   case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
     return aType;
 
   default:
     return InternalContentPolicyTypeToExternal(aType);
   }
 }
 
+/* static */
+nsContentPolicyType
+nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType)
+{
+  if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
+      aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
+      aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) {
+    return aType;
+  }
+  return InternalContentPolicyTypeToExternal(aType);
+}
 
 nsresult
 nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal,
                                               nsIDocument* aDoc,
                                               nsIHttpChannel* aChannel)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
   NS_ENSURE_ARG_POINTER(aChannel);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -961,16 +961,26 @@ public:
    *   * TYPE_INTERNAL_SERVICE_WORKER
    *
    *
    * Note: DO NOT call this function unless you know what you're doing!
    */
   static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType);
 
   /**
+   * Map internal content policy types to external ones or preload types:
+   *   * TYPE_INTERNAL_SCRIPT_PRELOAD
+   *   * TYPE_INTERNAL_IMAGE_PRELOAD
+   *   * TYPE_INTERNAL_STYLESHEET_PRELOAD
+   *
+   * Note: DO NOT call this function unless you know what you're doing!
+   */
+  static nsContentPolicyType InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType);
+
+  /**
    * Quick helper to determine whether there are any mutation listeners
    * of a given type that apply to this content or any of its ancestors.
    * The method has the side effect to call document's MayDispatchMutationEvent
    * using aTargetForSubtreeModified as the parameter.
    *
    * @param aNode  The node to search for listeners
    * @param aType  The type of listener (NS_EVENT_BITS_MUTATION_*)
    * @param aTargetForSubtreeModified The node which is the target of the
--- a/dom/base/nsIContentPolicy.idl
+++ b/dom/base/nsIContentPolicy.idl
@@ -15,17 +15,17 @@ interface nsIPrincipal;
  * Interface for content policy mechanism.  Implementations of this
  * interface can be used to control loading of various types of out-of-line
  * content, or processing of certain types of in-line content.
  *
  * WARNING: do not block the caller from shouldLoad or shouldProcess (e.g.,
  * by launching a dialog to prompt the user for something).
  */
 
-[scriptable,uuid(ce321216-c404-40a7-a711-d80454ec6b76)]
+[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)]
 interface nsIContentPolicy : nsIContentPolicyBase
 {
   /**
    * Should the resource at this location be loaded?
    * ShouldLoad will be called before loading the resource at aContentLocation
    * to determine whether to start the load at all.
    *
    * @param aContentType      the type of content being tested. This will be one
--- a/dom/base/nsIContentPolicyBase.idl
+++ b/dom/base/nsIContentPolicyBase.idl
@@ -19,17 +19,17 @@ typedef unsigned long nsContentPolicyTyp
  * Interface for content policy mechanism.  Implementations of this
  * interface can be used to control loading of various types of out-of-line
  * content, or processing of certain types of in-line content.
  *
  * WARNING: do not block the caller from shouldLoad or shouldProcess (e.g.,
  * by launching a dialog to prompt the user for something).
  */
 
-[scriptable,uuid(8527ae0d-0c43-4413-bc46-85c0bcb66876)]
+[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)]
 interface nsIContentPolicyBase : nsISupports
 {
   /**
    * Indicates a unset or bogus policy type.
    */
   const nsContentPolicyType TYPE_INVALID = 0;
 
   /**
@@ -275,16 +275,57 @@ interface nsIContentPolicyBase : nsISupp
    * Indicates an internal constant for scripts loaded through a service
    * worker.
    *
    * This will be mapped to TYPE_SCRIPT before being passed to content policy
    * implementations.
    */
   const nsContentPolicyType TYPE_INTERNAL_SERVICE_WORKER = 35;
 
+  /**
+   * Indicates an internal constant for *preloaded* scripts
+   * loaded through script elements.
+   *
+   * This will be mapped to TYPE_SCRIPT before being passed
+   * to content policy implementations.
+   */
+  const nsContentPolicyType TYPE_INTERNAL_SCRIPT_PRELOAD = 36;
+
+  /**
+   * Indicates an internal constant for normal images.
+   *
+   * This will be mapped to TYPE_IMAGE before being passed
+   * to content policy implementations.
+   */
+  const nsContentPolicyType TYPE_INTERNAL_IMAGE = 37;
+
+  /**
+   * Indicates an internal constant for *preloaded* images.
+   *
+   * This will be mapped to TYPE_IMAGE before being passed
+   * to content policy implementations.
+   */
+  const nsContentPolicyType TYPE_INTERNAL_IMAGE_PRELOAD = 38;
+
+  /**
+   * Indicates an internal constant for normal stylesheets.
+   *
+   * This will be mapped to TYPE_STYLESHEET before being passed
+   * to content policy implementations.
+   */
+  const nsContentPolicyType TYPE_INTERNAL_STYLESHEET = 39;
+
+  /**
+   * Indicates an internal constant for *preloaded* stylesheets.
+   *
+   * This will be mapped to TYPE_STYLESHEET before being passed
+   * to content policy implementations.
+   */
+  const nsContentPolicyType TYPE_INTERNAL_STYLESHEET_PRELOAD = 40;
+
   /* When adding new content types, please update nsContentBlocker,
    * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
    * implementations, the static_assert in dom/cache/DBSchema.cpp,
    * and other things that are not listed here that are related to
    * nsIContentPolicy. */
 
   //////////////////////////////////////////////////////////////////////
 
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -270,17 +270,22 @@ static_assert(nsIContentPolicy::TYPE_INV
               nsIContentPolicy::TYPE_INTERNAL_OBJECT == 27 &&
               nsIContentPolicy::TYPE_INTERNAL_FRAME == 28 &&
               nsIContentPolicy::TYPE_INTERNAL_IFRAME == 29 &&
               nsIContentPolicy::TYPE_INTERNAL_AUDIO == 30 &&
               nsIContentPolicy::TYPE_INTERNAL_VIDEO == 31 &&
               nsIContentPolicy::TYPE_INTERNAL_TRACK == 32 &&
               nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST == 33 &&
               nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 &&
-              nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35,
+              nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35 &&
+              nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD == 36 &&
+              nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 &&
+              nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 &&
+              nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 &&
+              nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40,
               "nsContentPolicyType values are as expected");
 
 namespace {
 
 typedef int32_t EntryId;
 
 struct IdCount
 {
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -111,29 +111,32 @@ RequestContext
 InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType)
 {
   RequestContext context = RequestContext::Internal;
   switch (aContentPolicyType) {
   case nsIContentPolicy::TYPE_OTHER:
     context = RequestContext::Internal;
     break;
   case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
+  case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
   case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
     context = RequestContext::Script;
     break;
   case nsIContentPolicy::TYPE_INTERNAL_WORKER:
     context = RequestContext::Worker;
     break;
   case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
     context = RequestContext::Sharedworker;
     break;
-  case nsIContentPolicy::TYPE_IMAGE:
+  case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
+  case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
     context = RequestContext::Image;
     break;
-  case nsIContentPolicy::TYPE_STYLESHEET:
+  case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
+  case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
     context = RequestContext::Style;
     break;
   case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
     context = RequestContext::Object;
     break;
   case nsIContentPolicy::TYPE_INTERNAL_EMBED:
     context = RequestContext::Embed;
     break;
--- a/dom/fetch/InternalRequest.h
+++ b/dom/fetch/InternalRequest.h
@@ -38,30 +38,30 @@ namespace dom {
  * eventsource       |
  * favicon           |
  * fetch             | TYPE_FETCH
  * font              | TYPE_FONT
  * form              |
  * frame             | TYPE_INTERNAL_FRAME
  * hyperlink         |
  * iframe            | TYPE_INTERNAL_IFRAME
- * image             | TYPE_IMAGE
+ * image             | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD
  * imageset          | TYPE_IMAGESET
  * import            | Not supported by Gecko
  * internal          | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
  * location          |
  * manifest          | TYPE_WEB_MANIFEST
  * object            | TYPE_INTERNAL_OBJECT
  * ping              | TYPE_PING
  * plugin            | TYPE_OBJECT_SUBREQUEST
  * prefetch          |
- * script            | TYPE_INTERNAL_SCRIPT
+ * script            | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD
  * sharedworker      | TYPE_INTERNAL_SHARED_WORKER
  * subresource       | Not supported by Gecko
- * style             | TYPE_STYLESHEET
+ * style             | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD
  * track             | TYPE_INTERNAL_TRACK
  * video             | TYPE_INTERNAL_VIDEO
  * worker            | TYPE_INTERNAL_WORKER
  * xmlhttprequest    | TYPE_INTERNAL_XMLHTTPREQUEST
  * eventsource       | TYPE_INTERNAL_EVENTSOURCE
  * xslt              | TYPE_XSLT
  *
  * TODO: Figure out if TYPE_REFRESH maps to anything useful