Bug 1407056: Part 1 - Provide more consistent principal/origin URL to content policies. r=bz,ckerschb
authorKris Maglione <maglione.k@gmail.com>
Thu, 12 Oct 2017 15:43:55 -0700
changeset 386034 197ce71943518bfb260f2b2cb3f91b55e58f9341
parent 386033 5725fbd3af70a19207b6b326db8cc1fad561503d
child 386035 41e5a4b54c93e40e92e1e697efa936e90a4c5a41
push id32673
push userarchaeopteryx@coole-files.de
push dateFri, 13 Oct 2017 09:13:17 +0000
treeherdermozilla-central@196dadb2fe50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, ckerschb
bugs1407056
milestone58.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 1407056: Part 1 - Provide more consistent principal/origin URL to content policies. r=bz,ckerschb We're currently fairly vague and inconsistent about the values we provide to content policy implementations for requestOrigin and requestPrincipal. In some cases they're the triggering principal, sometimes the loading principal, sometimes the channel principal. Our existing content policy implementations which require or expect a loading principal currently retrieve it from the context node. Since no current callers require the principal to be the loading principal, and some already expect it to be the triggering principal (which there's currently no other way to retrieve), I chose to pass the triggering principal whenever possible, but use the loading principal to determine the origin URL. As a follow-up, I'd like to change the nsIContentPolicy interface to explicitly receive loading and triggering principals, or possibly just LoadInfo instances, rather than poorly-defined request origin/principal/context args. But since that may cause trouble for comm-central, I'd rather not do it as part of this bug. MozReview-Commit-ID: LqD9GxdzMte
docshell/base/nsDocShell.cpp
dom/base/WebSocket.cpp
dom/base/nsContentPolicyUtils.h
dom/base/nsContentUtils.cpp
dom/base/nsIContentPolicy.idl
dom/base/nsObjectLoadingContent.cpp
dom/html/ImageDocument.cpp
dom/plugins/base/nsPluginStreamListenerPeer.cpp
dom/script/ScriptLoader.cpp
dom/security/nsContentSecurityManager.cpp
dom/workers/ServiceWorkerEvents.cpp
dom/workers/ServiceWorkerManager.cpp
dom/xml/nsXMLContentSink.cpp
image/imgLoader.cpp
layout/style/FontFaceSet.cpp
layout/style/Loader.cpp
layout/style/Loader.h
toolkit/modules/addons/WebRequestContent.js
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -10006,16 +10006,19 @@ nsDocShell::InternalLoad(nsIURI* aURI,
     NS_ENSURE_SUCCESS(rv, rv);
     NS_NAMED_LITERAL_STRING(msg, "conPolCheckFromDocShell");
     rv = extraStr->SetData(msg);
     NS_ENSURE_SUCCESS(rv, rv);
 
     int16_t shouldLoad = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(contentType,
                                    aURI,
+                                   // This is a top-level load, so the loading
+                                   // principal is null.
+                                   nullptr,
                                    aTriggeringPrincipal,
                                    requestingContext,
                                    EmptyCString(),  // mime guess
                                    extraStr,  // extra
                                    &shouldLoad);
 
     if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
       if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -1598,17 +1598,18 @@ WebSocketImpl::Init(JSContext* aCx,
     // Since we don't serialize the CSP within child and parent and also not
     // the context, we have to perform content policy checks here instead of
     // AsyncOpen2().
     // Please note that websockets can't follow redirects, hence there is no
     // need to perform a CSP check after redirects.
     int16_t shouldLoad = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET,
                                    uri,
-                                   aPrincipal,
+                                   aPrincipal, // loading principal
+                                   aPrincipal, // triggering principal
                                    originDoc,
                                    EmptyCString(),
                                    nullptr,
                                    &shouldLoad,
                                    nsContentUtils::GetContentPolicy());
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (NS_CP_REJECTED(shouldLoad)) {
--- a/dom/base/nsContentPolicyUtils.h
+++ b/dom/base/nsContentPolicyUtils.h
@@ -145,39 +145,43 @@ NS_CP_ContentTypeName(uint32_t contentTy
 #define CHECK_CONTENT_POLICY(action)                                          \
   PR_BEGIN_MACRO                                                              \
     nsCOMPtr<nsIContentPolicy> policy =                                       \
          do_GetService(NS_CONTENTPOLICY_CONTRACTID);                          \
     if (!policy)                                                              \
         return NS_ERROR_FAILURE;                                              \
                                                                               \
     return policy-> action (contentType, contentLocation, requestOrigin,      \
-                            context, mimeType, extra, originPrincipal,        \
+                            context, mimeType, extra, triggeringPrincipal,    \
                             decision);                                        \
   PR_END_MACRO
 
 /* Passes on parameters from its "caller"'s context. */
 #define CHECK_CONTENT_POLICY_WITH_SERVICE(action, _policy)                    \
   PR_BEGIN_MACRO                                                              \
     return _policy-> action (contentType, contentLocation, requestOrigin,     \
-                             context, mimeType, extra, originPrincipal,       \
+                             context, mimeType, extra, triggeringPrincipal,   \
                              decision);                                       \
   PR_END_MACRO
 
 /**
  * Check whether we can short-circuit this check and bail out.  If not, get the
  * origin URI to use.
  *
  * Note: requestOrigin is scoped outside the PR_BEGIN_MACRO/PR_END_MACRO on
  * purpose */
 #define CHECK_PRINCIPAL_AND_DATA(action)                                      \
   nsCOMPtr<nsIURI> requestOrigin;                                             \
   PR_BEGIN_MACRO                                                              \
-  if (originPrincipal) {                                                      \
-      bool isSystem = originPrincipal->GetIsSystemPrincipal();                \
+  if (loadingPrincipal) {                                                     \
+      /* We exempt most loads into any document with the system principal     \
+       * from content policy checks, mostly as an optimization. Which means   \
+       * that we need to apply this check to the loading principal, not the   \
+       * principal that triggered the load. */                                \
+      bool isSystem = loadingPrincipal->GetIsSystemPrincipal();               \
       if (isSystem && contentType != nsIContentPolicy::TYPE_DOCUMENT) {       \
           *decision = nsIContentPolicy::ACCEPT;                               \
           nsCOMPtr<nsINode> n = do_QueryInterface(context);                   \
           if (!n) {                                                           \
               nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(context);  \
               n = win ? win->GetExtantDoc() : nullptr;                        \
           }                                                                   \
           if (n) {                                                            \
@@ -188,66 +192,70 @@ NS_CP_ContentTypeName(uint32_t contentTy
                       do_GetService(                                          \
                               "@mozilla.org/data-document-content-policy;1"); \
                   if (dataPolicy) {                                           \
                       nsContentPolicyType externalType =                      \
                           nsContentUtils::InternalContentPolicyTypeToExternal(contentType); \
                       dataPolicy-> action (externalType, contentLocation,     \
                                            requestOrigin, context,            \
                                            mimeType, extra,                   \
-                                           originPrincipal, decision);        \
+                                           triggeringPrincipal, decision);    \
                   }                                                           \
               }                                                               \
           }                                                                   \
           return NS_OK;                                                       \
       }                                                                       \
-      nsresult rv = originPrincipal->GetURI(getter_AddRefs(requestOrigin));   \
+      nsresult rv = loadingPrincipal->GetURI(getter_AddRefs(requestOrigin));  \
       NS_ENSURE_SUCCESS(rv, rv);                                              \
   }                                                                           \
   PR_END_MACRO
 
 /**
  * Alias for calling ShouldLoad on the content policy service.  Parameters are
- * the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
- * parameter, which should be non-null if possible, and the last parameter,
+ * the same as nsIContentPolicy::shouldLoad, except for the loadingPrincipal
+ * and triggeringPrincipal parameters (which should be non-null if possible,
+ * and have the same semantics as in nsLoadInfo), and the last parameter,
  * which can be used to pass in a pointer to a useful service if the caller
  * already has it.  The origin URI to pass to shouldLoad will be the URI of
- * originPrincipal, unless originPrincipal is null (in which case a null origin
- * URI will be passed).
+ * loadingPrincipal, unless loadingPrincipal is null (in which case a null
+ * origin URI will be passed).
  */
 inline nsresult
 NS_CheckContentLoadPolicy(uint32_t          contentType,
                           nsIURI           *contentLocation,
-                          nsIPrincipal     *originPrincipal,
+                          nsIPrincipal     *loadingPrincipal,
+                          nsIPrincipal     *triggeringPrincipal,
                           nsISupports      *context,
                           const nsACString &mimeType,
                           nsISupports      *extra,
                           int16_t          *decision,
                           nsIContentPolicy *policyService = nullptr)
 {
     CHECK_PRINCIPAL_AND_DATA(ShouldLoad);
     if (policyService) {
         CHECK_CONTENT_POLICY_WITH_SERVICE(ShouldLoad, policyService);
     }
     CHECK_CONTENT_POLICY(ShouldLoad);
 }
 
 /**
  * Alias for calling ShouldProcess on the content policy service.  Parameters
- * are the same as nsIContentPolicy::shouldLoad, except for the originPrincipal
- * parameter, which should be non-null if possible, and the last parameter,
- * which can be used to pass in a pointer to a useful service if the caller
- * already has it.  The origin URI to pass to shouldLoad will be the URI of
- * originPrincipal, unless originPrincipal is null (in which case a null origin
- * URI will be passed).
+ * are the same as nsIContentPolicy::shouldLoad, except for the and
+ * triggeringPrincipal parameters (which should be non-null if possible, and
+ * have the same semantics as in nsLoadInfo), and the last parameter, which
+ * can be used to pass in a pointer to a useful service if the caller already
+ * has it.  The origin URI to pass to shouldLoad will be the URI of
+ * loadingPrincipal, unless loadingPrincipal is null (in which case a null
+ * origin URI will be passed).
  */
 inline nsresult
 NS_CheckContentProcessPolicy(uint32_t          contentType,
                              nsIURI           *contentLocation,
-                             nsIPrincipal     *originPrincipal,
+                             nsIPrincipal     *loadingPrincipal,
+                             nsIPrincipal     *triggeringPrincipal,
                              nsISupports      *context,
                              const nsACString &mimeType,
                              nsISupports      *extra,
                              int16_t          *decision,
                              nsIContentPolicy *policyService = nullptr)
 {
     CHECK_PRINCIPAL_AND_DATA(ShouldProcess);
     if (policyService) {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3622,16 +3622,17 @@ nsContentUtils::CanLoadImage(nsIURI* aUR
     }
   }
 
   int16_t decision = nsIContentPolicy::ACCEPT;
 
   rv = NS_CheckContentLoadPolicy(aContentType,
                                  aURI,
                                  aLoadingPrincipal,
+                                 aLoadingPrincipal, // triggering principal
                                  aContext,
                                  EmptyCString(), //mime guess
                                  nullptr,         //extra
                                  &decision,
                                  GetContentPolicy());
 
   if (aImageBlockingStatus) {
     *aImageBlockingStatus =
--- a/dom/base/nsIContentPolicy.idl
+++ b/dom/base/nsIContentPolicy.idl
@@ -394,18 +394,21 @@ interface nsIContentPolicy : nsISupports
    *
    * @param aContentType      the type of content being tested. This will be one
    *                          one of the TYPE_* constants.
    *
    * @param aContentLocation  the location of the content being checked; must
    *                          not be null
    *
    * @param aRequestOrigin    OPTIONAL. the location of the resource that
-   *                          initiated this load request; can be null if
-   *                          inapplicable
+   *                          that is loading the request. This will generally
+   *                          be the URI of the loading principal for the
+   *                          resulting request (as determined by its
+   *                          LoadInfo), but may vary depending on the
+   *                          caller. Can be null if inapplicable.
    *
    * @param aContext          OPTIONAL. the nsIDOMNode or nsIDOMWindow that
    *                          initiated the request, or something that can QI
    *                          to one of those; can be null if inapplicable.
    *                          Note that for navigation events (new windows and
    *                          link clicks), this is the NEW window.
    *
    * @param aMimeTypeGuess    OPTIONAL. a guess for the requested content's
@@ -415,18 +418,22 @@ interface nsIContentPolicy : nsISupports
    *                          actual MIME type of the requested content
    *
    * @param aExtra            an OPTIONAL argument, pass-through for non-Gecko
    *                          callers to pass extra data to callees.
    *
    * @param aRequestPrincipal an OPTIONAL argument, defines the principal that
    *                          caused the load. This is optional only for
    *                          non-gecko code: all gecko code should set this
-   *                          argument.  For navigation events, this is
-   *                          the principal of the page that caused this load.
+   *                          argument. This should generally be the same as
+   *                          the triggering principal for the resulting
+   *                          request (as determined by its LoadInfo), but may
+   *                          vary depending on the caller. Sometimes it will
+   *                          be the loading principal or final channel
+   *                          principal instead.
    *
    * @return ACCEPT or REJECT_*
    *
    * @note shouldLoad can be called while the DOM and layout of the document
    * involved is in an inconsistent state.  This means that implementors of
    * this method MUST NOT do any of the following:
    * 1)  Modify the DOM in any way (e.g. setting attributes is a no-no).
    * 2)  Query any DOM properties that depend on layout (e.g. offset*
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -1477,17 +1477,18 @@ nsObjectLoadingContent::CheckLoadPolicy(
 
   nsIDocument* doc = thisContent->OwnerDoc();
 
   nsContentPolicyType contentPolicyType = GetContentPolicyType();
 
   *aContentPolicy = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
                                           mURI,
-                                          doc->NodePrincipal(),
+                                          doc->NodePrincipal(), // loading principal
+                                          doc->NodePrincipal(), // triggering principal
                                           thisContent,
                                           mContentType,
                                           nullptr, //extra
                                           aContentPolicy,
                                           nsContentUtils::GetContentPolicy());
   NS_ENSURE_SUCCESS(rv, false);
   if (NS_CP_REJECTED(*aContentPolicy)) {
     LOG(("OBJLC [%p]: Content policy denied load of %s",
@@ -1530,17 +1531,18 @@ nsObjectLoadingContent::CheckProcessPoli
       NS_NOTREACHED("Calling checkProcessPolicy with a unloadable type");
       return false;
   }
 
   *aContentPolicy = nsIContentPolicy::ACCEPT;
   nsresult rv =
     NS_CheckContentProcessPolicy(objectType,
                                  mURI ? mURI : mBaseURI,
-                                 doc->NodePrincipal(),
+                                 doc->NodePrincipal(), // loading principal
+                                 doc->NodePrincipal(), // triggering principal
                                  static_cast<nsIImageLoadingContent*>(this),
                                  mContentType,
                                  nullptr, //extra
                                  aContentPolicy,
                                  nsContentUtils::GetContentPolicy());
   NS_ENSURE_SUCCESS(rv, false);
 
   if (NS_CP_REJECTED(*aContentPolicy)) {
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -97,20 +97,23 @@ ImageListener::OnStartRequest(nsIRequest
   channel->GetContentType(mimeType);
 
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   nsCOMPtr<nsIPrincipal> channelPrincipal;
   if (secMan) {
     secMan->GetChannelResultPrincipal(channel, getter_AddRefs(channelPrincipal));
   }
 
+  nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
+
   int16_t decision = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE,
                                              channelURI,
                                              channelPrincipal,
+                                             loadInfo ? loadInfo->TriggeringPrincipal() : nullptr,
                                              domWindow->GetFrameElementInternal(),
                                              mimeType,
                                              nullptr,
                                              &decision,
                                              nsContentUtils::GetContentPolicy());
 
   if (NS_FAILED(rv) || NS_CP_REJECTED(decision)) {
     request->Cancel(NS_ERROR_CONTENT_BLOCKED);
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -183,17 +183,18 @@ nsPluginStreamListenerPeer::OnStartReque
     owner->GetDOMElement(getter_AddRefs(element));
     owner->GetDocument(getter_AddRefs(doc));
   }
   nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;
 
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
                                     mURL,
-                                    principal,
+                                    principal, // loading principal
+                                    principal, // triggering principal
                                     element,
                                     contentType,
                                     nullptr,
                                     &shouldLoad);
   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
     mRequestFailed = true;
     return NS_ERROR_CONTENT_BLOCKED;
   }
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -298,17 +298,18 @@ ScriptLoader::CheckContentPolicy(nsIDocu
 {
   nsContentPolicyType contentPolicyType = aIsPreLoad
                                           ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
                                           : nsIContentPolicy::TYPE_INTERNAL_SCRIPT;
 
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
                                           aURI,
-                                          aDocument->NodePrincipal(),
+                                          aDocument->NodePrincipal(), // loading principal
+                                          aDocument->NodePrincipal(), // triggering principal
                                           aContext,
                                           NS_LossyConvertUTF16toASCII(aType),
                                           nullptr,    //extra
                                           &shouldLoad,
                                           nsContentUtils::GetContentPolicy());
   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
     if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
       return NS_ERROR_CONTENT_BLOCKED;
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -451,28 +451,21 @@ DoContentSecurityChecks(nsIChannel* aCha
       break;
     }
 
     default:
       // nsIContentPolicy::TYPE_INVALID
       MOZ_ASSERT(false, "can not perform security check without a valid contentType");
   }
 
-  // For document loads we use the triggeringPrincipal as the originPrincipal.
-  // Note the the loadingPrincipal for loads of TYPE_DOCUMENT is a nullptr.
-  nsCOMPtr<nsIPrincipal> principal =
-    (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
-     contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT)
-    ? aLoadInfo->TriggeringPrincipal()
-    : aLoadInfo->LoadingPrincipal();
-
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
                                  uri,
-                                 principal,
+                                 aLoadInfo->LoadingPrincipal(),
+                                 aLoadInfo->TriggeringPrincipal(),
                                  requestingContext,
                                  mimeTypeGuess,
                                  nullptr,        //extra,
                                  &shouldLoad,
                                  nsContentUtils::GetContentPolicy());
 
   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
     if ((NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) &&
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -262,16 +262,17 @@ public:
       // Synthetic response. The buck stops at the worker script.
       url = mScriptSpec;
     }
     rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr);
     NS_ENSURE_SUCCESS(rv, false);
     int16_t decision = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(aLoadInfo->InternalContentPolicyType(), uri,
                                    aLoadInfo->LoadingPrincipal(),
+                                   aLoadInfo->TriggeringPrincipal(),
                                    aLoadInfo->LoadingNode(), EmptyCString(),
                                    nullptr, &decision);
     NS_ENSURE_SUCCESS(rv, false);
     return decision == nsIContentPolicy::ACCEPT;
   }
 };
 
 class RespondWithHandler final : public PromiseNativeHandler
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -868,17 +868,18 @@ ServiceWorkerManager::Register(mozIDOMWi
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   // Check content policy.
   int16_t decision = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER,
                                  aScriptURI,
-                                 documentPrincipal,
+                                 documentPrincipal, // loading principal
+                                 documentPrincipal, // triggering principal
                                  doc,
                                  EmptyCString(),
                                  nullptr,
                                  &decision);
   NS_ENSURE_SUCCESS(rv, rv);
   if (NS_WARN_IF(decision != nsIContentPolicy::ACCEPT)) {
     return NS_ERROR_CONTENT_BLOCKED;
   }
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -697,17 +697,18 @@ nsXMLContentSink::ProcessStyleLink(nsICo
       CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url,
                                 nsIScriptSecurityManager::ALLOW_CHROME);
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
     // Do content policy check
     int16_t decision = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XSLT,
                                    url,
-                                   mDocument->NodePrincipal(),
+                                   mDocument->NodePrincipal(), // loading principal
+                                   mDocument->NodePrincipal(), // triggering principal
                                    aElement,
                                    type,
                                    nullptr,
                                    &decision,
                                    nsContentUtils::GetContentPolicy());
 
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -585,16 +585,17 @@ ShouldLoadCachedImage(imgRequest* aImgRe
   bool insecureRedirect = aImgRequest->HadInsecureRedirect();
   nsCOMPtr<nsIURI> contentLocation;
   aImgRequest->GetCurrentURI(getter_AddRefs(contentLocation));
   nsresult rv;
 
   int16_t decision = nsIContentPolicy::REJECT_REQUEST;
   rv = NS_CheckContentLoadPolicy(aPolicyType,
                                  contentLocation,
+                                 aTriggeringPrincipal, // loading principal
                                  aTriggeringPrincipal,
                                  aLoadingContext,
                                  EmptyCString(), //mime guess
                                  nullptr, //aExtra
                                  &decision,
                                  nsContentUtils::GetContentPolicy());
   if (NS_FAILED(rv) || !NS_CP_ACCEPTED(decision)) {
     return false;
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1386,17 +1386,18 @@ FontFaceSet::IsFontLoadAllowed(nsIURI* a
 {
   if (aViolations) {
     mDocument->StartBufferingCSPViolations();
   }
 
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_FONT,
                                           aFontLocation,
-                                          aPrincipal,
+                                          aPrincipal, // loading principal
+                                          aPrincipal, // triggering principal
                                           mDocument,
                                           EmptyCString(), // mime type
                                           nullptr, // aExtra
                                           &shouldLoad,
                                           nsContentUtils::GetContentPolicy());
 
   if (aViolations) {
     mDocument->StopBufferingCSPViolations(*aViolations);
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -882,35 +882,37 @@ Loader::ObsoleteSheet(nsIURI* aURI)
     if (NS_SUCCEEDED(rv) && areEqual) {
       iter.Remove();
     }
   }
   return NS_OK;
 }
 
 nsresult
-Loader::CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
-                          nsIURI* aTargetURI,
-                          nsISupports* aContext,
-                          bool aIsPreload)
+Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
+                           nsIPrincipal* aTriggeringPrincipal,
+                           nsIURI* aTargetURI,
+                           nsISupports* aContext,
+                           bool aIsPreload)
 {
   // When performing a system load (e.g. aUseSystemPrincipal = true)
-  // then aSourcePrincipal == null; don't consult content policies.
-  if (!aSourcePrincipal) {
+  // then aLoadingPrincipal == null; don't consult content policies.
+  if (!aLoadingPrincipal) {
     return NS_OK;
   }
 
   nsContentPolicyType contentPolicyType =
     aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
                : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
 
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
                                           aTargetURI,
-                                          aSourcePrincipal,
+                                          aLoadingPrincipal,
+                                          aTriggeringPrincipal,
                                           aContext,
                                           NS_LITERAL_CSTRING("text/css"),
                                           nullptr,  //extra param
                                           &shouldLoad,
                                           nsContentUtils::GetContentPolicy());
    if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
      return NS_ERROR_CONTENT_BLOCKED;
    }
@@ -1943,28 +1945,28 @@ Loader::LoadStyleLink(nsIContent* aEleme
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
 
-  nsIPrincipal* principal = aTriggeringPrincipal;
-  if (!principal) {
-    principal = aElement ? aElement->NodePrincipal()
-                         : mDocument->NodePrincipal();
-  }
+  nsIPrincipal* loadingPrincipal = aElement ? aElement->NodePrincipal()
+                                            : mDocument->NodePrincipal();
+
+  nsIPrincipal* principal = aTriggeringPrincipal ? aTriggeringPrincipal
+                                                 : loadingPrincipal;
 
   nsISupports* context = aElement;
   if (!context) {
     context = mDocument;
   }
 
-  nsresult rv = CheckContentPolicy(principal, aURL, context, false);
+  nsresult rv = CheckContentPolicy(loadingPrincipal, principal, aURL, context, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     // Don't fire the error event if our document is loaded as data.  We're
     // supposed to not even try to do loads in that case... Unfortunately, we
     // implement that via nsDataDocumentContentPolicy, which doesn't have a good
     // way to communicate back to us that _it_ is the thing that blocked the
     // load.
     if (aElement && !mDocument->IsLoadedAsData()) {
       // Fire an async error event on it.
@@ -2090,23 +2092,28 @@ Loader::LoadChildSheet(StyleSheet* aPare
   if (aParentSheet->GetAssociatedDocument()) {
     StyleSheet* topSheet = aParentSheet;
     while (StyleSheet* parent = topSheet->GetParentSheet()) {
       topSheet = parent;
     }
     owningNode = topSheet->GetOwnerNode();
   }
 
-  nsISupports* context = owningNode;
-  if (!context) {
+  nsISupports* context = nullptr;
+  nsIPrincipal* loadingPrincipal = nullptr;
+  if (owningNode) {
+    context = owningNode;
+    loadingPrincipal = owningNode->NodePrincipal();
+  } else if (mDocument) {
     context = mDocument;
+    loadingPrincipal = mDocument->NodePrincipal();
   }
 
   nsIPrincipal* principal = aParentSheet->Principal();
-  nsresult rv = CheckContentPolicy(principal, aURL, context, false);
+  nsresult rv = CheckContentPolicy(loadingPrincipal, 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"));
@@ -2283,17 +2290,21 @@ Loader::InternalLoadNonDocumentSheet(nsI
     *aSheet = nullptr;
   }
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsresult rv = CheckContentPolicy(aOriginPrincipal, aURL, mDocument, aIsPreload);
+  nsCOMPtr<nsIPrincipal> loadingPrincipal = (aOriginPrincipal && mDocument
+                                             ? mDocument->NodePrincipal()
+                                             : nullptr);
+  nsresult rv = CheckContentPolicy(loadingPrincipal, aOriginPrincipal,
+                                   aURL, mDocument, aIsPreload);
   NS_ENSURE_SUCCESS(rv, rv);
 
   StyleSheetState state;
   bool isAlternate;
   RefPtr<StyleSheet> sheet;
   bool syncLoad = (aObserver == nullptr);
   const nsAString& empty = EmptyString();
 
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -472,17 +472,18 @@ public:
   // Marks all the sheets at the given URI obsolete, and removes them from the
   // cache.
   nsresult ObsoleteSheet(nsIURI* aURI);
 
 private:
   friend class SheetLoadData;
   friend class StreamLoader;
 
-  nsresult CheckContentPolicy(nsIPrincipal* aSourcePrincipal,
+  nsresult CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
+                              nsIPrincipal* aTriggeringPrincipal,
                               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.
--- a/toolkit/modules/addons/WebRequestContent.js
+++ b/toolkit/modules/addons/WebRequestContent.js
@@ -182,17 +182,20 @@ var ContentPolicy = {
                 url,
                 type: WebRequestCommon.typeForPolicyType(policyType),
                 windowId,
                 parentWindowId};
     if (frameAncestors.length > 0) {
       data.frameAncestors = frameAncestors;
     }
     if (requestOrigin) {
-      data.originUrl = requestOrigin.spec;
+      data.documentUrl = requestOrigin.spec;
+    }
+    if (requestPrincipal && requestPrincipal.URI) {
+      data.originUrl = requestPrincipal.URI.spec;
     }
     mm.sendAsyncMessage("WebRequest:ShouldLoad", data);
 
     return Ci.nsIContentPolicy.ACCEPT;
   },
 
   shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) {
     return Ci.nsIContentPolicy.ACCEPT;