Bug 1220936 - Flush console report to innerWindowID by using nsIDocument and nsILoadGroup. r=bkelly.
authorTom Tung <shes050117@gmail.com>
Mon, 06 Feb 2017 09:19:34 +0800
changeset 479466 0d4ed23eb2f3037a2d06b34c685357474768c348
parent 479387 507fcddedb1f1d4a24ca98dc65633dd655c8f17d
child 479467 77d0c4f5e72ffdd8a0ed9360acd989aedc13adff
push id44267
push usermaglione.k@gmail.com
push dateMon, 06 Feb 2017 19:37:49 +0000
reviewersbkelly
bugs1220936
milestone54.0a1
Bug 1220936 - Flush console report to innerWindowID by using nsIDocument and nsILoadGroup. r=bkelly.
docshell/base/nsDocShell.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsScriptLoader.cpp
dom/console/ConsoleReportCollector.cpp
dom/console/ConsoleReportCollector.h
dom/console/nsIConsoleReportCollector.h
dom/fetch/Fetch.cpp
dom/workers/ServiceWorkerManager.cpp
dom/workers/WorkerPrivate.cpp
layout/style/Loader.cpp
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7567,17 +7567,23 @@ nsDocShell::EndPageLoad(nsIWebProgress* 
                         nsIChannel* aChannel, nsresult aStatus)
 {
   if (!aChannel) {
     return NS_ERROR_NULL_POINTER;
   }
 
   nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
   if (reporter) {
-    reporter->FlushConsoleReports(GetDocument());
+    nsCOMPtr<nsILoadGroup> loadGroup;
+    aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+    if (loadGroup) {
+      reporter->FlushConsoleReports(loadGroup);
+    } else {
+      reporter->FlushConsoleReports(GetDocument());
+    }
   }
 
   nsCOMPtr<nsIURI> url;
   nsresult rv = aChannel->GetURI(getter_AddRefs(url));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3667,16 +3667,32 @@ nsContentUtils::ReportToConsoleNonLocali
   uint64_t innerWindowID = 0;
   if (aDocument) {
     if (!aURI) {
       aURI = aDocument->GetDocumentURI();
     }
     innerWindowID = aDocument->InnerWindowID();
   }
 
+  return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
+                                   innerWindowID, aURI, aSourceLine,
+                                   aLineNumber, aColumnNumber, aLocationMode);
+}
+
+/* static */ nsresult
+nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
+                                          uint32_t aErrorFlags,
+                                          const nsACString& aCategory,
+                                          uint64_t aInnerWindowID,
+                                          nsIURI* aURI,
+                                          const nsAFlatString& aSourceLine,
+                                          uint32_t aLineNumber,
+                                          uint32_t aColumnNumber,
+                                          MissingErrorLocationMode aLocationMode)
+{
   nsresult rv;
   if (!sConsoleService) { // only need to bother null-checking here
     rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsAutoCString spec;
   if (!aLineNumber && aLocationMode == eUSE_CALLING_LOCATION) {
@@ -3693,17 +3709,17 @@ nsContentUtils::ReportToConsoleNonLocali
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = errorObject->InitWithWindowID(aErrorText,
                                      NS_ConvertUTF8toUTF16(spec), // file name
                                      aSourceLine,
                                      aLineNumber, aColumnNumber,
                                      aErrorFlags, aCategory,
-                                     innerWindowID);
+                                     aInnerWindowID);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return sConsoleService->LogMessage(errorObject);
 }
 
 void
 nsContentUtils::LogMessageToConsole(const char* aMsg)
 {
@@ -7332,18 +7348,28 @@ nsContentUtils::GetInnerWindowID(nsIRequ
 
   nsCOMPtr<nsILoadGroup> loadGroup;
   nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
 
   if (NS_FAILED(rv) || !loadGroup) {
     return 0;
   }
 
+  return GetInnerWindowID(loadGroup);
+}
+
+uint64_t
+nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup)
+{
+  if (!aLoadGroup) {
+    return 0;
+  }
+
   nsCOMPtr<nsIInterfaceRequestor> callbacks;
-  rv = loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
+  nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
   if (NS_FAILED(rv) || !callbacks) {
     return 0;
   }
 
   nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
   if (!loadContext) {
     return 0;
   }
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -880,16 +880,47 @@ public:
                                               const nsAFlatString& aSourceLine
                                                 = EmptyString(),
                                               uint32_t aLineNumber = 0,
                                               uint32_t aColumnNumber = 0,
                                               MissingErrorLocationMode aLocationMode
                                                 = eUSE_CALLING_LOCATION);
 
   /**
+   * Report a non-localized error message to the error console base on the
+   * innerWindowID.
+   *   @param aErrorText the error message
+   *   @param aErrorFlags See nsIScriptError.
+   *   @param aCategory Name of module reporting error.
+   *   @param [aInnerWindowID] Inner window ID for document which triggered the
+   *          message.
+   *   @param [aURI=nullptr] (Optional) URI of resource containing error.
+   *   @param [aSourceLine=EmptyString()] (Optional) The text of the line that
+              contains the error (may be empty).
+   *   @param [aLineNumber=0] (Optional) Line number within resource
+              containing error.
+   *   @param [aColumnNumber=0] (Optional) Column number within resource
+              containing error.
+              If aURI is null, then aDocument->GetDocumentURI() is used.
+   *   @param [aLocationMode] (Optional) Specifies the behavior if
+              error location information is omitted.
+   */
+  static nsresult ReportToConsoleByWindowID(const nsAString& aErrorText,
+                                            uint32_t aErrorFlags,
+                                            const nsACString& aCategory,
+                                            uint64_t aInnerWindowID,
+                                            nsIURI* aURI = nullptr,
+                                            const nsAFlatString& aSourceLine
+                                              = EmptyString(),
+                                            uint32_t aLineNumber = 0,
+                                            uint32_t aColumnNumber = 0,
+                                            MissingErrorLocationMode aLocationMode
+                                              = eUSE_CALLING_LOCATION);
+
+  /**
    * Report a localized error message to the error console.
    *   @param aErrorFlags See nsIScriptError.
    *   @param aCategory Name of module reporting error.
    *   @param aDocument Reference to the document which triggered the message.
    *   @param aFile Properties file containing localized message.
    *   @param aMessageName Name of localized message.
    *   @param [aParams=nullptr] (Optional) Parameters to be substituted into
               localized message.
@@ -2442,21 +2473,26 @@ public:
 
   /**
    * Returns whether a given header is forbidden for an XHR or fetch
    * response.
    */
   static bool IsForbiddenResponseHeader(const nsACString& aHeader);
 
   /**
-   * Returns the inner window ID for the window associated with a request,
+   * Returns the inner window ID for the window associated with a request.
    */
   static uint64_t GetInnerWindowID(nsIRequest* aRequest);
 
   /**
+   * Returns the inner window ID for the window associated with a load group.
+   */
+  static uint64_t GetInnerWindowID(nsILoadGroup* aLoadGroup);
+
+  /**
    * If the hostname for aURI is an IPv6 it encloses it in brackets,
    * otherwise it just outputs the hostname in aHost.
    */
   static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsAString& aHost);
   static nsresult GetHostOrIPv6WithBrackets(nsIURI* aURI, nsCString& aHost);
 
   /*
    * Call the given callback on all remote children of the given top-level
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -2483,17 +2483,22 @@ nsScriptLoader::OnStreamComplete(nsIIncr
     MOZ_ASSERT(mReporter);
 
     nsAutoCString sourceUri;
     if (mDocument && mDocument->GetDocumentURI()) {
       mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
     }
     rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, channel, sourceUri,
                                   mReporter);
-    mReporter->FlushConsoleReports(mDocument);
+    if (channelRequest) {
+      mReporter->FlushReportsToConsole(
+        nsContentUtils::GetInnerWindowID(channelRequest));
+    } else {
+      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,
--- a/dom/console/ConsoleReportCollector.cpp
+++ b/dom/console/ConsoleReportCollector.cpp
@@ -34,64 +34,85 @@ ConsoleReportCollector::AddConsoleReport
 
   mPendingReports.AppendElement(PendingReport(aErrorFlags, aCategory,
                                               aPropertiesFile, aSourceFileURI,
                                               aLineNumber, aColumnNumber,
                                               aMessageName, aStringParams));
 }
 
 void
-ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
-                                            ReportAction aAction)
+ConsoleReportCollector::FlushReportsToConsole(uint64_t aInnerWindowID,
+                                              ReportAction aAction)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
   nsTArray<PendingReport> reports;
 
   {
     MutexAutoLock lock(mMutex);
     if (aAction == ReportAction::Forget) {
       mPendingReports.SwapElements(reports);
     } else {
       reports = mPendingReports;
     }
   }
 
   for (uint32_t i = 0; i < reports.Length(); ++i) {
     PendingReport& report = reports[i];
 
+    nsXPIDLString errorText;
+    nsresult rv;
+    if (!report.mStringParams.IsEmpty()) {
+      rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile,
+                                                 report.mMessageName.get(),
+                                                 report.mStringParams,
+                                                 errorText);
+    } else {
+      rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile,
+                                              report.mMessageName.get(),
+                                              errorText);
+    }
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      continue;
+    }
+
     // It would be nice if we did not have to do this since ReportToConsole()
     // just turns around and converts it back to a spec.
     nsCOMPtr<nsIURI> uri;
     if (!report.mSourceFileURI.IsEmpty()) {
       nsresult rv = NS_NewURI(getter_AddRefs(uri), report.mSourceFileURI);
       MOZ_ALWAYS_SUCCEEDS(rv);
       if (NS_FAILED(rv)) {
         continue;
       }
     }
 
-    // Convert back from nsTArray<nsString> to the char16_t** format required
-    // by our l10n libraries and ReportToConsole. (bug 1219762)
-    UniquePtr<const char16_t*[]> params;
-    uint32_t paramsLength = report.mStringParams.Length();
-    if (paramsLength > 0) {
-      params = MakeUnique<const char16_t*[]>(paramsLength);
-      for (uint32_t j = 0; j < paramsLength; ++j) {
-        params[j] = report.mStringParams[j].get();
-      }
-    }
+    nsContentUtils::ReportToConsoleByWindowID(errorText,
+                                              report.mErrorFlags,
+                                              report.mCategory,
+                                              aInnerWindowID,
+                                              uri,
+                                              EmptyString(),
+                                              report.mLineNumber,
+                                              report.mColumnNumber);
+  }
+}
 
-    nsContentUtils::ReportToConsole(report.mErrorFlags, report.mCategory,
-                                    aDocument, report.mPropertiesFile,
-                                    report.mMessageName.get(),
-                                    params.get(),
-                                    paramsLength, uri, EmptyString(),
-                                    report.mLineNumber, report.mColumnNumber);
-  }
+void
+ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
+                                            ReportAction aAction)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  FlushReportsToConsole(aDocument ? aDocument->InnerWindowID() : 0, aAction);
+}
+
+void
+ConsoleReportCollector::FlushConsoleReports(nsILoadGroup* aLoadGroup,
+                                            ReportAction aAction)
+{
+  FlushReportsToConsole(nsContentUtils::GetInnerWindowID(aLoadGroup), aAction);
 }
 
 void
 ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
 {
   MOZ_ASSERT(aCollector);
 
   nsTArray<PendingReport> reports;
@@ -106,81 +127,16 @@ ConsoleReportCollector::FlushConsoleRepo
     aCollector->AddConsoleReport(report.mErrorFlags, report.mCategory,
                                  report.mPropertiesFile, report.mSourceFileURI,
                                  report.mLineNumber, report.mColumnNumber,
                                  report.mMessageName, report.mStringParams);
   }
 }
 
 void
-ConsoleReportCollector::FlushReportsByWindowId(uint64_t aWindowId,
-                                               ReportAction aAction)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsTArray<PendingReport> reports;
-
-  {
-    MutexAutoLock lock(mMutex);
-    if (aAction == ReportAction::Forget) {
-      mPendingReports.SwapElements(reports);
-    } else {
-      reports = mPendingReports;
-    }
-  }
-
-  nsCOMPtr<nsIConsoleService> consoleService =
-    do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-  if (!consoleService) {
-    NS_WARNING("GetConsoleService failed");
-    return;
-  }
-
-  nsresult rv;
-  for (uint32_t i = 0; i < reports.Length(); ++i) {
-    PendingReport& report = reports[i];
-
-    nsXPIDLString errorText;
-    if (!report.mStringParams.IsEmpty()) {
-      rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile,
-                                                 report.mMessageName.get(),
-                                                 report.mStringParams,
-                                                 errorText);
-    } else {
-      rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile,
-                                              report.mMessageName.get(),
-                                              errorText);
-    }
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      continue;
-    }
-
-    nsCOMPtr<nsIScriptError> errorObject =
-    do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      continue;
-    }
-
-    rv = errorObject->InitWithWindowID(errorText,
-                                       NS_ConvertUTF8toUTF16(report.mSourceFileURI),
-                                       EmptyString(),
-                                       report.mLineNumber,
-                                       report.mColumnNumber,
-                                       report.mErrorFlags,
-                                       report.mCategory,
-                                       aWindowId);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      continue;
-    }
-
-    consoleService->LogMessage(errorObject);
-  }
-}
-
-void
 ConsoleReportCollector::ClearConsoleReports()
 {
   MutexAutoLock lock(mMutex);
 
   mPendingReports.Clear();
 }
 
 ConsoleReportCollector::~ConsoleReportCollector()
--- a/dom/console/ConsoleReportCollector.h
+++ b/dom/console/ConsoleReportCollector.h
@@ -22,27 +22,31 @@ public:
   AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
                    nsContentUtils::PropertiesFile aPropertiesFile,
                    const nsACString& aSourceFileURI,
                    uint32_t aLineNumber, uint32_t aColumnNumber,
                    const nsACString& aMessageName,
                    const nsTArray<nsString>& aStringParams) override;
 
   void
+  FlushReportsToConsole(uint64_t aInnerWindowID,
+                        ReportAction aAction = ReportAction::Forget) override;
+
+  void
   FlushConsoleReports(nsIDocument* aDocument,
                       ReportAction aAction = ReportAction::Forget) override;
 
   void
+  FlushConsoleReports(nsILoadGroup* aLoadGroup,
+                      ReportAction aAction = ReportAction::Forget) override;
+
+  void
   FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
 
   void
-  FlushReportsByWindowId(uint64_t aWindowId,
-                         ReportAction aAction = ReportAction::Forget) override;
-
-  void
   ClearConsoleReports() override;
 
 private:
   ~ConsoleReportCollector();
 
   struct PendingReport
   {
     PendingReport(uint32_t aErrorFlags, const nsACString& aCategory,
--- a/dom/console/nsIConsoleReportCollector.h
+++ b/dom/console/nsIConsoleReportCollector.h
@@ -69,47 +69,58 @@ public:
   // An enum calss to indicate whether should free the pending reports or not.
   // Forget        Free the pending reports.
   // Save          Keep the pending reports.
   enum class ReportAction {
     Forget,
     Save
   };
 
+  // Flush all pending reports to the console.  May be called from any thread.
+  //
+  // aInnerWindowID A inner window ID representing where to flush the reports.
+  // aAction        An action to determine whether to reserve the pending
+  //                reports. Defalut action is to forget the report.
+  virtual void
+  FlushReportsToConsole(uint64_t aInnerWindowID,
+                        ReportAction aAction = ReportAction::Forget) = 0;
+
   // Flush all pending reports to the console.  Main thread only.
   //
   // aDocument      An optional document representing where to flush the
   //                reports.  If provided, then the corresponding window's
   //                web console will get the reports.  Otherwise the reports
   //                go to the browser console.
   // aAction        An action to determine whether to reserve the pending
   //                reports. Defalut action is to forget the report.
   virtual void
   FlushConsoleReports(nsIDocument* aDocument,
                       ReportAction aAction = ReportAction::Forget) = 0;
 
+  // Flush all pending reports to the console.  May be called from any thread.
+  //
+  // aLoadGroup     An optional loadGroup representing where to flush the
+  //                reports.  If provided, then the corresponding window's
+  //                web console will get the reports.  Otherwise the reports
+  //                go to the browser console.
+  // aAction        An action to determine whether to reserve the pending
+  //                reports. Defalut action is to forget the report.
+  virtual void
+  FlushConsoleReports(nsILoadGroup* aLoadGroup,
+                      ReportAction aAction = ReportAction::Forget) = 0;
+
+
   // Flush all pending reports to another collector.  May be called from any
   // thread.
   //
   // aCollector     A required collector object that will effectively take
   //                ownership of our currently console reports.
   virtual void
   FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0;
 
-  // Flush all pending reports to the console accroding to window ID. Main
-  // thread only.
-  //
-  // aWindowId      A window ID representing where to flush the reports and it's
-  //                typically the inner window ID.
-  //
-  // aAction        An action to decide whether free the pending reports or not.
-  virtual void
-  FlushReportsByWindowId(uint64_t aWindowId,
-                         ReportAction aAction = ReportAction::Forget) = 0;
-
   // Clear all pending reports.
   virtual void
   ClearConsoleReports() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIConsoleReportCollector, NS_NSICONSOLEREPORTCOLLECTOR_IID)
 
 #endif // nsIConsoleReportCollector_h
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -95,41 +95,41 @@ private:
   FlushConsoleReport() override;
 };
 
 class MainThreadFetchResolver final : public FetchDriverObserver
 {
   RefPtr<Promise> mPromise;
   RefPtr<Response> mResponse;
 
-  nsCOMPtr<nsIDocument> mDocument;
+  nsCOMPtr<nsILoadGroup> mLoadGroup;
 
   NS_DECL_OWNINGTHREAD
 public:
   explicit MainThreadFetchResolver(Promise* aPromise);
 
   void
   OnResponseAvailableInternal(InternalResponse* aResponse) override;
 
-  void SetDocument(nsIDocument* aDocument)
+  void SetLoadGroup(nsILoadGroup* aLoadGroup)
   {
-    mDocument = aDocument;
+    mLoadGroup = aLoadGroup;
   }
 
   virtual void OnResponseEnd() override
   {
     FlushConsoleReport();
   }
 
 private:
   ~MainThreadFetchResolver();
 
   void FlushConsoleReport() override
   {
-    mReporter->FlushConsoleReports(mDocument);
+    mReporter->FlushConsoleReports(mLoadGroup);
   }
 };
 
 class MainThreadFetchRunnable : public Runnable
 {
   RefPtr<WorkerFetchResolver> mResolver;
   RefPtr<InternalRequest> mRequest;
 
@@ -233,17 +233,17 @@ FetchRequest(nsIGlobalObject* aGlobal, c
       }
     }
 
     Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1);
 
     RefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p);
     RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup);
     fetch->SetDocument(doc);
-    resolver->SetDocument(doc);
+    resolver->SetLoadGroup(loadGroup);
     aRv = fetch->Fetch(resolver);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
   } else {
     WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(worker);
 
@@ -448,40 +448,40 @@ WorkerFetchResolver::FlushConsoleReport(
   MOZ_ASSERT(mPromiseProxy);
 
   if(!mReporter) {
     return;
   }
 
   workers::WorkerPrivate* worker = mPromiseProxy->GetWorkerPrivate();
   if (!worker) {
-    mReporter->FlushConsoleReports((nsIDocument*)nullptr);
+    mReporter->FlushReportsToConsole(0);
     return;
   }
 
   if (worker->IsServiceWorker()) {
     // Flush to service worker
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (!swm) {
-      mReporter->FlushConsoleReports((nsIDocument*)nullptr);
+      mReporter->FlushReportsToConsole(0);
       return;
     }
 
     swm->FlushReportsToAllClients(worker->WorkerName(), mReporter);
     return;
   }
 
   if (worker->IsSharedWorker()) {
     // Flush to shared worker
     worker->FlushReportsToSharedWorkers(mReporter);
     return;
   }
 
   // Flush to dedicated worker
-  mReporter->FlushConsoleReports(worker->GetDocument());
+  mReporter->FlushConsoleReports(worker->GetLoadGroup());
 }
 
 nsresult
 ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit,
                           nsIInputStream** aStream,
                           nsCString& aContentTypeWithCharset,
                           uint64_t& aContentLength)
 {
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -1649,20 +1649,21 @@ ServiceWorkerManager::FlushReportsToAllC
       continue;
     }
 
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(iter.Key());
     if (!doc || !doc->IsCurrentActiveDocument() || !doc->GetWindow()) {
       continue;
     }
 
-    windows.AppendElement(doc->InnerWindowID());
-
-    aReporter->FlushConsoleReports(doc,
-                                   nsIConsoleReportCollector::ReportAction::Save);
+    uint64_t innerWindowId = doc->InnerWindowID();
+    windows.AppendElement(innerWindowId);
+
+    aReporter->FlushReportsToConsole(
+      innerWindowId, nsIConsoleReportCollector::ReportAction::Save);
   }
 
   // Report to any documents that have called .register() for this scope.  They
   // may not be controlled, but will still want to see error reports.
   WeakDocumentList* regList = mRegisteringDocuments.Get(aScope);
   if (regList) {
     for (int32_t i = regList->Length() - 1; i >= 0; --i) {
       nsCOMPtr<nsIDocument> doc = do_QueryReferent(regList->ElementAt(i));
@@ -1677,18 +1678,18 @@ ServiceWorkerManager::FlushReportsToAllC
 
       uint64_t innerWindowId = doc->InnerWindowID();
       if (windows.Contains(innerWindowId)) {
         continue;
       }
 
       windows.AppendElement(innerWindowId);
 
-      aReporter->FlushConsoleReports(doc,
-                                     nsIConsoleReportCollector::ReportAction::Save);
+      aReporter->FlushReportsToConsole(
+        innerWindowId, nsIConsoleReportCollector::ReportAction::Save);
     }
 
     if (regList->IsEmpty()) {
       regList = nullptr;
       nsAutoPtr<WeakDocumentList> doomed;
       mRegisteringDocuments.RemoveAndForget(aScope, doomed);
     }
   }
@@ -1707,25 +1708,25 @@ ServiceWorkerManager::FlushReportsToAllC
 
       uint64_t innerWindowId = nsContentUtils::GetInnerWindowID(inner);
       if (innerWindowId == 0 || windows.Contains(innerWindowId)) {
         continue;
       }
 
       windows.AppendElement(innerWindowId);
 
-      aReporter->FlushReportsByWindowId(innerWindowId,
-                                        nsIConsoleReportCollector::ReportAction::Save);
+      aReporter->FlushReportsToConsole(
+        innerWindowId, nsIConsoleReportCollector::ReportAction::Save);
     }
   }
 
   // If there are no documents to report to, at least report something to the
   // browser console.
   if (windows.IsEmpty()) {
-    aReporter->FlushConsoleReports((nsIDocument*)nullptr);
+    aReporter->FlushReportsToConsole(0);
     return;
   }
 
   aReporter->ClearConsoleReports();
 }
 
 void
 ServiceWorkerManager::HandleError(JSContext* aCx,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3730,25 +3730,26 @@ WorkerPrivateParent<Derived>::FlushRepor
   }
 
   bool reportErrorToBrowserConsole = true;
 
   // Flush the reports.
   for (uint32_t index = 0; index < windowActions.Length(); index++) {
     WindowAction& windowAction = windowActions[index];
 
-    aReporter->FlushConsoleReports(windowAction.mWindow->GetExtantDoc(),
-                                   nsIConsoleReportCollector::ReportAction::Save);
+    aReporter->FlushReportsToConsole(
+      windowAction.mWindow->WindowID(),
+      nsIConsoleReportCollector::ReportAction::Save);
     reportErrorToBrowserConsole = false;
   }
 
   // Finally report to broswer console if there is no any window or shared
   // worker.
   if (reportErrorToBrowserConsole) {
-    aReporter->FlushConsoleReports((nsIDocument*)nullptr);
+    aReporter->FlushReportsToConsole(0);
     return;
   }
 
   aReporter->ClearConsoleReports();
 }
 
 template <class Derived>
 NS_IMPL_ADDREF_INHERITED(WorkerPrivateParent<Derived>, DOMEventTargetHelper)
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -961,17 +961,25 @@ SheetLoadData::OnStreamComplete(nsIUnich
     }
   } else {
     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);
+
+    nsCOMPtr<nsILoadGroup> loadGroup;
+    channel->GetLoadGroup(getter_AddRefs(loadGroup));
+    if (loadGroup) {
+      mLoader->mReporter->FlushConsoleReports(loadGroup);
+    } else {
+      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;
     }
   }
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -2747,36 +2747,43 @@ HttpBaseChannel::AddConsoleReport(uint32
 {
   mReportCollector->AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile,
                                      aSourceFileURI, aLineNumber,
                                      aColumnNumber, aMessageName,
                                      aStringParams);
 }
 
 void
+HttpBaseChannel::FlushReportsToConsole(uint64_t aInnerWindowID,
+                                       ReportAction aAction)
+{
+  mReportCollector->FlushReportsToConsole(aInnerWindowID, aAction);
+}
+
+void
 HttpBaseChannel::FlushConsoleReports(nsIDocument* aDocument,
                                      ReportAction aAction)
 {
   mReportCollector->FlushConsoleReports(aDocument, aAction);
 }
 
 void
+HttpBaseChannel::FlushConsoleReports(nsILoadGroup* aLoadGroup,
+                                     ReportAction aAction)
+{
+  mReportCollector->FlushConsoleReports(aLoadGroup, aAction);
+}
+
+void
 HttpBaseChannel::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
 {
   mReportCollector->FlushConsoleReports(aCollector);
 }
 
 void
-HttpBaseChannel::FlushReportsByWindowId(uint64_t aWindowId,
-                                        ReportAction aAction)
-{
-  mReportCollector->FlushReportsByWindowId(aWindowId, aAction);
-}
-
-void
 HttpBaseChannel::ClearConsoleReports()
 {
   mReportCollector->ClearConsoleReports();
 }
 
 nsIPrincipal *
 HttpBaseChannel::GetURIPrincipal()
 {
@@ -2933,21 +2940,25 @@ HttpBaseChannel::DoNotifyListener()
 
   DoNotifyListenerCleanup();
 
   // If this is a navigation, then we must let the docshell flush the reports
   // to the console later.  The LoadDocument() is pointing at the detached
   // document that started the navigation.  We want to show the reports on the
   // new document.  Otherwise the console is wiped and the user never sees
   // the information.
-  if (!IsNavigation() && mLoadInfo) {
-    nsCOMPtr<nsIDOMDocument> dommyDoc;
-    mLoadInfo->GetLoadingDocument(getter_AddRefs(dommyDoc));
-    nsCOMPtr<nsIDocument> doc = do_QueryInterface(dommyDoc);
-    FlushConsoleReports(doc);
+  if (!IsNavigation()) {
+    if (mLoadGroup) {
+      FlushConsoleReports(mLoadGroup);
+    } else if (mLoadInfo) {
+      nsCOMPtr<nsIDOMDocument> dommyDoc;
+      mLoadInfo->GetLoadingDocument(getter_AddRefs(dommyDoc));
+      nsCOMPtr<nsIDocument> doc = do_QueryInterface(dommyDoc);
+      FlushConsoleReports(doc);
+    }
   }
 }
 
 void
 HttpBaseChannel::AddCookiesToRequest()
 {
   if (mLoadFlags & LOAD_ANONYMOUS) {
     return;
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -273,27 +273,31 @@ public:
   AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
                    nsContentUtils::PropertiesFile aPropertiesFile,
                    const nsACString& aSourceFileURI,
                    uint32_t aLineNumber, uint32_t aColumnNumber,
                    const nsACString& aMessageName,
                    const nsTArray<nsString>& aStringParams) override;
 
   void
+  FlushReportsToConsole(uint64_t aInnerWindowID,
+                        ReportAction aAction = ReportAction::Forget) override;
+
+  void
   FlushConsoleReports(nsIDocument* aDocument,
                       ReportAction aAction = ReportAction::Forget) override;
 
   void
+  FlushConsoleReports(nsILoadGroup* aLoadGroup,
+                      ReportAction aAction = ReportAction::Forget) override;
+
+  void
   FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
 
   void
-  FlushReportsByWindowId(uint64_t aWindowId,
-                         ReportAction aAction = ReportAction::Forget) override;
-
-  void
   ClearConsoleReports() override;
 
   class nsContentEncodings : public nsIUTF8StringEnumerator
     {
     public:
         NS_DECL_ISUPPORTS
         NS_DECL_NSIUTF8STRINGENUMERATOR