Bug 1187335 - P2 - Modify the way to report to console for worker and use LoadTainting to decide CORS or not. r=bkelly. r=francois.
authorTom Tung <ttung@mozilla.com>
Thu, 08 Sep 2016 09:59:40 +0800
changeset 354513 89c1c3294bee9930d4421f0f033f9d9ed0a69be3
parent 354512 8510e1c0f42a29d15b442c9c44c700add93e955c
child 354514 c586b098334477f680e9eff7e65e904805f7d7ee
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly, francois
bugs1187335
milestone51.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 1187335 - P2 - Modify the way to report to console for worker and use LoadTainting to decide CORS or not. r=bkelly. r=francois.
dom/base/nsScriptLoader.cpp
dom/base/nsScriptLoader.h
dom/security/SRICheck.cpp
dom/security/SRICheck.h
layout/style/Loader.cpp
layout/style/Loader.h
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -46,16 +46,17 @@
 #include "nsCRT.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsProxyRelease.h"
 #include "nsSandboxFlags.h"
 #include "nsContentTypeParser.h"
 #include "nsINetworkPredictor.h"
 #include "ImportManager.h"
 #include "mozilla/dom/EncodingUtils.h"
+#include "mozilla/ConsoleReportCollector.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Unused.h"
 #include "nsIScriptError.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -509,17 +510,18 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScrip
 nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
   : mDocument(aDocument),
     mParserBlockingBlockerCount(0),
     mBlockerCount(0),
     mNumberOfProcessors(0),
     mEnabled(true),
     mDeferEnabled(false),
     mDocumentParsingDone(false),
-    mBlockingDOMContentLoaded(false)
+    mBlockingDOMContentLoaded(false),
+    mReporter(new ConsoleReportCollector())
 {
 }
 
 nsScriptLoader::~nsScriptLoader()
 {
   mObservers.Clear();
 
   if (mParserBlockingRequest) {
@@ -1274,17 +1276,22 @@ nsScriptLoader::StartLoad(nsScriptLoadRe
   // Set the initiator type
   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
   if (timedChannel) {
     timedChannel->SetInitiatorType(NS_LITERAL_STRING("script"));
   }
 
   nsAutoPtr<mozilla::dom::SRICheckDataVerifier> sriDataVerifier;
   if (!aRequest->mIntegrity.IsEmpty()) {
-    sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, mDocument);
+    nsAutoCString sourceUri;
+    if (mDocument && mDocument->GetDocumentURI()) {
+      mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
+    }
+    sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, sourceUri,
+                                               mReporter);
   }
 
   RefPtr<nsScriptLoadHandler> handler =
       new nsScriptLoadHandler(this, aRequest, sriDataVerifier.forget());
 
   nsCOMPtr<nsIIncrementalStreamLoader> loader;
   rv = NS_NewIncrementalStreamLoader(getter_AddRefs(loader), handler);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1500,17 +1507,22 @@ nsScriptLoader::ProcessScriptElement(nsI
       {
         nsAutoString integrity;
         scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity,
                                integrity);
         if (!integrity.IsEmpty()) {
           MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
                  ("nsScriptLoader::ProcessScriptElement, integrity=%s",
                   NS_ConvertUTF16toUTF8(integrity).get()));
-          SRICheck::IntegrityMetadata(integrity, mDocument, &sriMetadata);
+          nsAutoCString sourceUri;
+          if (mDocument && mDocument->GetDocumentURI()) {
+            mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
+          }
+          SRICheck::IntegrityMetadata(integrity, sourceUri, mReporter,
+                                      &sriMetadata);
         }
       }
 
       request = CreateLoadRequest(scriptKind, aElement, version, ourCORSMode,
                                   sriMetadata);
       request->mURI = scriptURI;
       request->mIsInline = false;
       request->mReferrerPolicy = ourRefPolicy;
@@ -2446,18 +2458,26 @@ nsScriptLoader::OnStreamComplete(nsIIncr
   aLoader->GetRequest(getter_AddRefs(channelRequest));
   nsCOMPtr<nsIChannel> channel;
   channel = do_QueryInterface(channelRequest);
 
   nsresult rv = NS_OK;
   if (!request->mIntegrity.IsEmpty() &&
       NS_SUCCEEDED((rv = aSRIStatus))) {
     MOZ_ASSERT(aSRIDataVerifier);
-    if (NS_FAILED(aSRIDataVerifier->Verify(request->mIntegrity, channel,
-                                           request->mCORSMode, mDocument))) {
+    MOZ_ASSERT(mReporter);
+
+    nsAutoCString sourceUri;
+    if (mDocument && mDocument->GetDocumentURI()) {
+      mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
+    }
+    rv = aSRIDataVerifier->Verify(request->mIntegrity, channel, sourceUri,
+                                  mReporter);
+    mReporter->FlushConsoleReports(mDocument);
+    if (NS_FAILED(rv)) {
       rv = NS_ERROR_SRI_CORRUPT;
     }
   } else {
     nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
 
     if (loadInfo->GetEnforceSRI()) {
       MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
              ("nsScriptLoader::OnStreamComplete, required SRI not found"));
@@ -2752,17 +2772,21 @@ nsScriptLoader::PreloadURI(nsIURI *aURI,
     return;
   }
 
   SRIMetadata sriMetadata;
   if (!aIntegrity.IsEmpty()) {
     MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
            ("nsScriptLoader::PreloadURI, integrity=%s",
             NS_ConvertUTF16toUTF8(aIntegrity).get()));
-    SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata);
+    nsAutoCString sourceUri;
+    if (mDocument && mDocument->GetDocumentURI()) {
+      mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
+    }
+    SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
   }
 
   RefPtr<nsScriptLoadRequest> request =
     CreateLoadRequest(nsScriptKind::Classic, nullptr, 0,
                       Element::StringToCORSMode(aCrossOrigin), sriMetadata);
   request->mURI = aURI;
   request->mIsInline = false;
   request->mReferrerPolicy = aReferrerPolicy;
--- a/dom/base/nsScriptLoader.h
+++ b/dom/base/nsScriptLoader.h
@@ -633,16 +633,18 @@ private:
   bool mEnabled;
   bool mDeferEnabled;
   bool mDocumentParsingDone;
   bool mBlockingDOMContentLoaded;
 
   // Module map
   nsRefPtrHashtable<nsURIHashKey, mozilla::GenericPromise::Private> mFetchingModules;
   nsRefPtrHashtable<nsURIHashKey, nsModuleScript> mFetchedModules;
+
+  nsCOMPtr<nsIConsoleReportCollector> mReporter;
 };
 
 class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
 {
 public:
   explicit nsScriptLoadHandler(nsScriptLoader* aScriptLoader,
                                nsScriptLoadRequest *aRequest,
                                mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier);
--- a/dom/security/SRICheck.cpp
+++ b/dom/security/SRICheck.cpp
@@ -2,25 +2,25 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SRICheck.h"
 
 #include "mozilla/Base64.h"
+#include "mozilla/LoadTainting.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/SRILogHelper.h"
 #include "nsContentUtils.h"
 #include "nsIChannel.h"
-#include "nsIDocument.h"
+#include "nsIConsoleReportCollector.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptError.h"
-#include "nsIScriptSecurityManager.h"
 #include "nsIIncrementalStreamLoader.h"
 #include "nsIUnicharStreamLoader.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsWhitespaceTokenizer.h"
 
 #define SRILOG(args)                                                           \
   MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug, args)
@@ -31,77 +31,76 @@ namespace mozilla {
 namespace dom {
 
 /**
  * Returns whether or not the sub-resource about to be loaded is eligible
  * for integrity checks. If it's not, the checks will be skipped and the
  * sub-resource will be loaded.
  */
 static nsresult
-IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode,
-           const nsIDocument* aDocument)
+IsEligible(nsIChannel* aChannel, mozilla::LoadTainting aTainting,
+           const nsACString& aSourceFileURI,
+           nsIConsoleReportCollector* aReporter)
 {
-  NS_ENSURE_ARG_POINTER(aDocument);
+  NS_ENSURE_ARG_POINTER(aReporter);
 
   if (!aChannel) {
     SRILOG(("SRICheck::IsEligible, null channel"));
     return NS_ERROR_SRI_NOT_ELIGIBLE;
   }
 
   // Was the sub-resource loaded via CORS?
-  if (aCORSMode != CORS_NONE) {
+  if (aTainting == LoadTainting::CORS) {
     SRILOG(("SRICheck::IsEligible, CORS mode"));
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> finalURI;
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalURI));
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIURI> originalURI;
   rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
   NS_ENSURE_SUCCESS(rv, rv);
   nsAutoCString requestSpec;
   rv = originalURI->GetSpec(requestSpec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
-    nsAutoCString documentSpec;
-    aDocument->GetDocumentURI()->GetAsciiSpec(documentSpec);
-    SRILOG(("SRICheck::IsEligible, documentURI=%s; requestURI=%s; finalURI=%s",
-            documentSpec.get(), requestSpec.get(),
+    SRILOG(("SRICheck::IsEligible, requestURI=%s; finalURI=%s",
+            requestSpec.get(),
             finalURI ? finalURI->GetSpecOrDefault().get() : ""));
   }
 
   // Is the sub-resource same-origin?
-  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  if (NS_SUCCEEDED(ssm->CheckSameOriginURI(aDocument->GetDocumentURI(),
-                                           finalURI, false))) {
+  if (aTainting == LoadTainting::Basic) {
     SRILOG(("SRICheck::IsEligible, same-origin"));
     return NS_OK;
   }
   SRILOG(("SRICheck::IsEligible, NOT same origin"));
 
   NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec);
-  const char16_t* params[] = { requestSpecUTF16.get() };
-  nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                  NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                  aDocument,
-                                  nsContentUtils::eSECURITY_PROPERTIES,
-                                  "IneligibleResource",
-                                  params, ArrayLength(params));
+  nsTArray<nsString> params;
+  params.AppendElement(requestSpecUTF16);
+  aReporter->AddConsoleReport(nsIScriptError::errorFlag,
+                              NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                              nsContentUtils::eSECURITY_PROPERTIES,
+                              aSourceFileURI, 0, 0,
+                              NS_LITERAL_CSTRING("IneligibleResource"),
+                              const_cast<const nsTArray<nsString>&>(params));
   return NS_ERROR_SRI_NOT_ELIGIBLE;
 }
 
 /* static */ nsresult
 SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
-                            const nsIDocument* aDocument,
+                            const nsACString& aSourceFileURI,
+                            nsIConsoleReportCollector* aReporter,
                             SRIMetadata* outMetadata)
 {
   NS_ENSURE_ARG_POINTER(outMetadata);
-  NS_ENSURE_ARG_POINTER(aDocument);
+  NS_ENSURE_ARG_POINTER(aReporter);
   MOZ_ASSERT(outMetadata->IsEmpty()); // caller must pass empty metadata
 
   if (!Preferences::GetBool("security.sri.enable", false)) {
     SRILOG(("SRICheck::IntegrityMetadata, sri is disabled (pref)"));
     return NS_ERROR_SRI_DISABLED;
   }
 
   // put a reasonable bound on the length of the metadata
@@ -118,34 +117,36 @@ SRICheck::IntegrityMetadata(const nsAStr
   nsAutoCString token;
   for (uint32_t i=0; tokenizer.hasMoreTokens() &&
          i < SRICheck::MAX_METADATA_TOKENS; ++i) {
     token = tokenizer.nextToken();
 
     SRIMetadata metadata(token);
     if (metadata.IsMalformed()) {
       NS_ConvertUTF8toUTF16 tokenUTF16(token);
-      const char16_t* params[] = { tokenUTF16.get() };
-      nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
-                                      NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                      aDocument,
-                                      nsContentUtils::eSECURITY_PROPERTIES,
-                                      "MalformedIntegrityHash",
-                                      params, ArrayLength(params));
+      nsTArray<nsString> params;
+      params.AppendElement(tokenUTF16);
+      aReporter->AddConsoleReport(nsIScriptError::warningFlag,
+                                  NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                                  nsContentUtils::eSECURITY_PROPERTIES,
+                                  aSourceFileURI, 0, 0,
+                                  NS_LITERAL_CSTRING("MalformedIntegrityHash"),
+                                  const_cast<const nsTArray<nsString>&>(params));
     } else if (!metadata.IsAlgorithmSupported()) {
       nsAutoCString alg;
       metadata.GetAlgorithm(&alg);
       NS_ConvertUTF8toUTF16 algUTF16(alg);
-      const char16_t* params[] = { algUTF16.get() };
-      nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
-                                      NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                      aDocument,
-                                      nsContentUtils::eSECURITY_PROPERTIES,
-                                      "UnsupportedHashAlg",
-                                      params, ArrayLength(params));
+      nsTArray<nsString> params;
+      params.AppendElement(algUTF16);
+      aReporter->AddConsoleReport(nsIScriptError::warningFlag,
+                                  NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                                  nsContentUtils::eSECURITY_PROPERTIES,
+                                  aSourceFileURI, 0, 0,
+                                  NS_LITERAL_CSTRING("UnsupportedHashAlg"),
+                                  const_cast<const nsTArray<nsString>&>(params));
     }
 
     nsAutoCString alg1, alg2;
     if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
       outMetadata->GetAlgorithm(&alg1);
       metadata.GetAlgorithm(&alg2);
     }
     if (*outMetadata == metadata) {
@@ -171,67 +172,72 @@ SRICheck::IntegrityMetadata(const nsAStr
     }
   }
   return NS_OK;
 }
 
 /* static */ nsresult
 SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata,
                           nsIUnicharStreamLoader* aLoader,
-                          const CORSMode aCORSMode,
                           const nsAString& aString,
-                          const nsIDocument* aDocument)
+                          const nsACString& aSourceFileURI,
+                          nsIConsoleReportCollector* aReporter)
 {
   NS_ENSURE_ARG_POINTER(aLoader);
+  NS_ENSURE_ARG_POINTER(aReporter);
 
   NS_ConvertUTF16toUTF8 utf8Hash(aString);
   nsCOMPtr<nsIChannel> channel;
   aLoader->GetChannel(getter_AddRefs(channel));
 
   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     nsAutoCString requestURL;
     nsCOMPtr<nsIURI> originalURI;
     if (channel &&
         NS_SUCCEEDED(channel->GetOriginalURI(getter_AddRefs(originalURI))) &&
         originalURI) {
       originalURI->GetAsciiSpec(requestURL);
     }
     SRILOG(("SRICheck::VerifyIntegrity (unichar stream)"));
   }
 
-  SRICheckDataVerifier verifier(aMetadata, aDocument);
+  SRICheckDataVerifier verifier(aMetadata, aSourceFileURI, aReporter);
   nsresult rv;
   rv = verifier.Update(utf8Hash.Length(), (uint8_t*)utf8Hash.get());
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return verifier.Verify(aMetadata, channel, aCORSMode, aDocument);
+  return verifier.Verify(aMetadata, channel, aSourceFileURI, aReporter);
 }
 
 //////////////////////////////////////////////////////////////
 //
 //////////////////////////////////////////////////////////////
 SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata,
-                                           const nsIDocument* aDocument)
+                                           const nsACString& aSourceFileURI,
+                                           nsIConsoleReportCollector* aReporter)
   : mCryptoHash(nullptr),
     mBytesHashed(0),
     mInvalidMetadata(false),
     mComplete(false)
 {
   MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller
 
   // IntegrityMetadata() checks this and returns "no metadata" if
   // it's disabled so we should never make it this far
   MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
+  MOZ_ASSERT(aReporter);
 
   if (!aMetadata.IsValid()) {
-    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
-                                    NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                    aDocument,
-                                    nsContentUtils::eSECURITY_PROPERTIES,
-                                    "NoValidMetadata");
+    nsTArray<nsString> params;
+    aReporter->AddConsoleReport(nsIScriptError::warningFlag,
+                                NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                                nsContentUtils::eSECURITY_PROPERTIES,
+                                aSourceFileURI, 0, 0,
+                                NS_LITERAL_CSTRING("NoValidMetadata"),
+                                const_cast<const nsTArray<nsString>&>(params));
     mInvalidMetadata = true;
     return; // ignore invalid metadata for forward-compatibility
   }
 
   uint32_t hashLength;
   aMetadata.GetHashType(&mHashType, &hashLength);
 }
 
@@ -287,43 +293,48 @@ SRICheckDataVerifier::Finish()
   mCryptoHash = nullptr;
   mComplete = true;
   return rv;
 }
 
 nsresult
 SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata,
                                  uint32_t aHashIndex,
-                                 const nsIDocument* aDocument)
+                                 const nsACString& aSourceFileURI,
+                                 nsIConsoleReportCollector* aReporter)
 {
-  NS_ENSURE_ARG_POINTER(aDocument);
+  NS_ENSURE_ARG_POINTER(aReporter);
 
   nsAutoCString base64Hash;
   aMetadata.GetHash(aHashIndex, &base64Hash);
   SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u]=%s", aHashIndex, base64Hash.get()));
 
   nsAutoCString binaryHash;
   if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) {
-    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                    NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                    aDocument,
-                                    nsContentUtils::eSECURITY_PROPERTIES,
-                                    "InvalidIntegrityBase64");
+    nsTArray<nsString> params;
+    aReporter->AddConsoleReport(nsIScriptError::errorFlag,
+                                NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                                nsContentUtils::eSECURITY_PROPERTIES,
+                                aSourceFileURI, 0, 0,
+                                NS_LITERAL_CSTRING("InvalidIntegrityBase64"),
+                                const_cast<const nsTArray<nsString>&>(params));
     return NS_ERROR_SRI_CORRUPT;
   }
 
   uint32_t hashLength;
   int8_t hashType;
   aMetadata.GetHashType(&hashType, &hashLength);
   if (binaryHash.Length() != hashLength) {
-    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                    NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                    aDocument,
-                                    nsContentUtils::eSECURITY_PROPERTIES,
-                                    "InvalidIntegrityLength");
+    nsTArray<nsString> params;
+    aReporter->AddConsoleReport(nsIScriptError::errorFlag,
+                                NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                                nsContentUtils::eSECURITY_PROPERTIES,
+                                aSourceFileURI, 0, 0,
+                                NS_LITERAL_CSTRING("InvalidIntegrityLength"),
+                                const_cast<const nsTArray<nsString>&>(params));
     return NS_ERROR_SRI_CORRUPT;
   }
 
   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     nsAutoCString encodedHash;
     nsresult rv = Base64Encode(mComputedHash, encodedHash);
     if (NS_SUCCEEDED(rv)) {
       SRILOG(("SRICheckDataVerifier::VerifyHash, mComputedHash=%s",
@@ -338,54 +349,59 @@ SRICheckDataVerifier::VerifyHash(const S
 
   SRILOG(("SRICheckDataVerifier::VerifyHash, hash[%u] verified successfully", aHashIndex));
   return NS_OK;
 }
 
 nsresult
 SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata,
                              nsIChannel* aChannel,
-                             const CORSMode aCORSMode,
-                             const nsIDocument* aDocument)
+                             const nsACString& aSourceFileURI,
+                             nsIConsoleReportCollector* aReporter)
 {
-  NS_ENSURE_ARG_POINTER(aDocument);
+  NS_ENSURE_ARG_POINTER(aReporter);
 
   if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
     nsAutoCString requestURL;
     nsCOMPtr<nsIRequest> request;
     request = do_QueryInterface(aChannel);
     request->GetName(requestURL);
     SRILOG(("SRICheckDataVerifier::Verify, url=%s (length=%lu)",
             requestURL.get(), mBytesHashed));
   }
 
   nsresult rv = Finish();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (NS_FAILED(IsEligible(aChannel, aCORSMode, aDocument))) {
+  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
+  NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
+  LoadTainting tainting = loadInfo->GetTainting();
+
+  if (NS_FAILED(IsEligible(aChannel, tainting, aSourceFileURI, aReporter))) {
     return NS_ERROR_SRI_NOT_ELIGIBLE;
   }
 
   if (mInvalidMetadata) {
     return NS_OK; // ignore invalid metadata for forward-compatibility
   }
 
   for (uint32_t i = 0; i < aMetadata.HashCount(); i++) {
-    if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aDocument))) {
+    if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aSourceFileURI, aReporter))) {
       return NS_OK; // stop at the first valid hash
     }
   }
 
   nsAutoCString alg;
   aMetadata.GetAlgorithm(&alg);
   NS_ConvertUTF8toUTF16 algUTF16(alg);
-  const char16_t* params[] = { algUTF16.get() };
-  nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                  NS_LITERAL_CSTRING("Sub-resource Integrity"),
-                                  aDocument,
-                                  nsContentUtils::eSECURITY_PROPERTIES,
-                                  "IntegrityMismatch",
-                                  params, ArrayLength(params));
+  nsTArray<nsString> params;
+  params.AppendElement(algUTF16);
+  aReporter->AddConsoleReport(nsIScriptError::errorFlag,
+                              NS_LITERAL_CSTRING("Sub-resource Integrity"),
+                              nsContentUtils::eSECURITY_PROPERTIES,
+                              aSourceFileURI, 0, 0,
+                              NS_LITERAL_CSTRING("IntegrityMismatch"),
+                              const_cast<const nsTArray<nsString>&>(params));
   return NS_ERROR_SRI_CORRUPT;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/security/SRICheck.h
+++ b/dom/security/SRICheck.h
@@ -2,73 +2,76 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SRICheck_h
 #define mozilla_dom_SRICheck_h
 
-#include "mozilla/CORSMode.h"
 #include "nsCOMPtr.h"
 #include "nsICryptoHash.h"
 #include "SRIMetadata.h"
 
 class nsIChannel;
-class nsIDocument;
 class nsIUnicharStreamLoader;
+class nsIConsoleReportCollector;
 
 namespace mozilla {
 namespace dom {
 
 class SRICheck final
 {
 public:
   static const uint32_t MAX_METADATA_LENGTH = 24*1024;
   static const uint32_t MAX_METADATA_TOKENS = 512;
 
   /**
    * Parse the multiple hashes specified in the integrity attribute and
    * return the strongest supported hash.
    */
   static nsresult IntegrityMetadata(const nsAString& aMetadataList,
-                                    const nsIDocument* aDocument,
+                                    const nsACString& aSourceFileURI,
+                                    nsIConsoleReportCollector* aReporter,
                                     SRIMetadata* outMetadata);
 
   /**
    * Process the integrity attribute of the element.  A result of false
    * must prevent the resource from loading.
    */
   static nsresult VerifyIntegrity(const SRIMetadata& aMetadata,
                                   nsIUnicharStreamLoader* aLoader,
-                                  const CORSMode aCORSMode,
                                   const nsAString& aString,
-                                  const nsIDocument* aDocument);
+                                  const nsACString& aSourceFileURI,
+                                  nsIConsoleReportCollector* aReporter);
 };
 
 class SRICheckDataVerifier final
 {
   public:
     SRICheckDataVerifier(const SRIMetadata& aMetadata,
-                         const nsIDocument* aDocument);
+                         const nsACString& aSourceFileURI,
+                         nsIConsoleReportCollector* aReporter);
 
     nsresult Update(uint32_t aStringLen, const uint8_t* aString);
     nsresult Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel,
-                    const CORSMode aCORSMode, const nsIDocument* aDocument);
+                    const nsACString& aSourceFileURI,
+                    nsIConsoleReportCollector* aReporter);
 
   private:
     nsCOMPtr<nsICryptoHash> mCryptoHash;
     nsAutoCString           mComputedHash;
     size_t                  mBytesHashed;
     int8_t                  mHashType;
     bool                    mInvalidMetadata;
     bool                    mComplete;
 
     nsresult EnsureCryptoHash();
     nsresult Finish();
     nsresult VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex,
-                        const nsIDocument* aDocument);
+                        const nsACString& aSourceFileURI,
+                        nsIConsoleReportCollector* aReporter);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SRICheck_h
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -50,16 +50,17 @@
 #include "nsGkAtoms.h"
 #include "nsIThreadInternal.h"
 #include "nsINetworkPredictor.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/URL.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/StyleSheetHandle.h"
 #include "mozilla/StyleSheetHandleInlines.h"
+#include "mozilla/ConsoleReportCollector.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 
 #include "nsIMediaList.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsError.h"
@@ -515,27 +516,29 @@ LoaderReusableStyleSheets::FindReusableS
  *************************/
 
 Loader::Loader(StyleBackendType aType)
   : mDocument(nullptr)
   , mDatasToNotifyOn(0)
   , mCompatMode(eCompatibility_FullStandards)
   , mStyleBackendType(Some(aType))
   , mEnabled(true)
+  , mReporter(new ConsoleReportCollector())
 #ifdef DEBUG
   , mSyncCallback(false)
 #endif
 {
 }
 
 Loader::Loader(nsIDocument* aDocument)
   : mDocument(aDocument)
   , mDatasToNotifyOn(0)
   , mCompatMode(eCompatibility_FullStandards)
   , mEnabled(true)
+  , mReporter(new ConsoleReportCollector())
 #ifdef DEBUG
   , mSyncCallback(false)
 #endif
 {
   // We can just use the preferred set, since there are no sheets in the
   // document yet (if there are, how did they get there? _we_ load the sheets!)
   // and hence the selected set makes no sense at this time.
   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
@@ -950,19 +953,23 @@ SheetLoadData::OnStreamComplete(nsIUnich
       // line number unknown. mRequestingNode doesn't bear this info.
       csp->LogViolationDetails(
         nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_STYLE,
         NS_ConvertUTF8toUTF16(spec), EmptyString(),
         0, EmptyString(), EmptyString());
       return NS_OK;
     }
   } else {
-    nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader,
-                                            mSheet->GetCORSMode(), aBuffer,
-                                            mLoader->mDocument);
+    nsAutoCString sourceUri;
+    if (mLoader->mDocument && mLoader->mDocument->GetDocumentURI()) {
+      mLoader->mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
+    }
+    nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader, aBuffer,
+                                            sourceUri, mLoader->mReporter);
+    mLoader->mReporter->FlushConsoleReports(mLoader->mDocument);
     if (NS_FAILED(rv)) {
       LOG(("  Load was blocked by SRI"));
       MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
               ("css::Loader::OnStreamComplete, bad metadata"));
       mLoader->SheetComplete(this, NS_ERROR_SRI_CORRUPT);
       return NS_OK;
     }
   }
@@ -1231,17 +1238,22 @@ Loader::CreateSheet(nsIURI* aURI,
       originalURI = aURI;
     }
 
     SRIMetadata sriMetadata;
     if (!aIntegrity.IsEmpty()) {
       MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug,
               ("css::Loader::CreateSheet, integrity=%s",
                NS_ConvertUTF16toUTF8(aIntegrity).get()));
-      SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata);
+      nsAutoCString sourceUri;
+      if (mDocument && mDocument->GetDocumentURI()) {
+        mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
+      }
+      SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter,
+                                  &sriMetadata);
     }
 
     if (GetStyleBackendType() == StyleBackendType::Gecko) {
       *aSheet = new CSSStyleSheet(aParsingMode, aCORSMode, aReferrerPolicy, sriMetadata);
     } else {
       *aSheet = new ServoStyleSheet(aParsingMode, aCORSMode, aReferrerPolicy, sriMetadata);
     }
     (*aSheet)->SetURIs(sheetURI, originalURI, baseURI);
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -23,16 +23,17 @@
 #include "mozilla/CSSStyleSheet.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/StyleBackendType.h"
 #include "mozilla/StyleSheetHandle.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsICSSLoaderObserver;
+class nsIConsoleReportCollector;
 class nsIContent;
 class nsIDocument;
 class nsMediaList;
 class nsIStyleSheetLinkingElement;
 
 namespace mozilla {
 namespace dom {
 class Element;
@@ -579,16 +580,18 @@ private:
   nsString          mPreferredSheet;  // title of preferred sheet
 
   // Set explicitly when the Loader(StyleBackendType) constructor is used, or
   // taken from the document when the Loader(nsIDocument*) constructor is used.
   mozilla::Maybe<StyleBackendType> mStyleBackendType;
 
   bool              mEnabled; // is enabled to load new styles
 
+  nsCOMPtr<nsIConsoleReportCollector> mReporter;
+
 #ifdef DEBUG
   bool              mSyncCallback;
 #endif
 };
 
 } // namespace css
 } // namespace mozilla