ConsoleReportCollector.cpp (6263B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/ConsoleReportCollector.h" 8 9 #include "ConsoleUtils.h" 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/net/NeckoChannelParams.h" 12 #include "nsIScriptError.h" 13 #include "nsNetUtil.h" 14 15 namespace mozilla { 16 17 using mozilla::dom::ConsoleUtils; 18 19 NS_IMPL_ISUPPORTS(ConsoleReportCollector, nsIConsoleReportCollector) 20 21 ConsoleReportCollector::ConsoleReportCollector() 22 : mMutex("mozilla::ConsoleReportCollector") {} 23 24 void ConsoleReportCollector::AddConsoleReport( 25 uint32_t aErrorFlags, const nsACString& aCategory, 26 nsContentUtils::PropertiesFile aPropertiesFile, 27 const nsACString& aSourceFileURI, uint32_t aLineNumber, 28 uint32_t aColumnNumber, const nsACString& aMessageName, 29 const nsTArray<nsString>& aStringParams) { 30 // any thread 31 MutexAutoLock lock(mMutex); 32 33 mPendingReports.EmplaceBack(aErrorFlags, aCategory, aPropertiesFile, 34 aSourceFileURI, aLineNumber, aColumnNumber, 35 aMessageName, aStringParams); 36 } 37 38 void ConsoleReportCollector::FlushReportsToConsole(uint64_t aInnerWindowID, 39 ReportAction aAction) { 40 nsTArray<PendingReport> reports; 41 42 { 43 MutexAutoLock lock(mMutex); 44 if (aAction == ReportAction::Forget) { 45 reports = std::move(mPendingReports); 46 } else { 47 reports = mPendingReports.Clone(); 48 } 49 } 50 51 for (uint32_t i = 0; i < reports.Length(); ++i) { 52 PendingReport& report = reports[i]; 53 54 nsAutoString errorText; 55 nsresult rv; 56 if (!report.mStringParams.IsEmpty()) { 57 rv = nsContentUtils::FormatLocalizedString( 58 report.mPropertiesFile, report.mMessageName.get(), 59 report.mStringParams, errorText); 60 } else { 61 rv = nsContentUtils::GetLocalizedString( 62 report.mPropertiesFile, report.mMessageName.get(), errorText); 63 } 64 if (NS_WARN_IF(NS_FAILED(rv))) { 65 continue; 66 } 67 68 // It would be nice if we did not have to do this since ReportToConsole() 69 // just turns around and converts it back to a spec. 70 nsCOMPtr<nsIURI> uri; 71 if (!report.mSourceFileURI.IsEmpty()) { 72 nsresult rv = NS_NewURI(getter_AddRefs(uri), report.mSourceFileURI); 73 if (NS_FAILED(rv)) { 74 NS_WARNING(nsPrintfCString("Failed to transform %s to uri", 75 report.mSourceFileURI.get()) 76 .get()); 77 continue; 78 } 79 } 80 81 SourceLocation loc{std::move(uri), report.mLineNumber, 82 report.mColumnNumber}; 83 84 nsContentUtils::ReportToConsoleByWindowID( 85 errorText, report.mErrorFlags, report.mCategory, aInnerWindowID, loc); 86 } 87 } 88 89 void ConsoleReportCollector::FlushReportsToConsoleForServiceWorkerScope( 90 const nsACString& aScope, ReportAction aAction) { 91 nsTArray<PendingReport> reports; 92 93 { 94 MutexAutoLock lock(mMutex); 95 if (aAction == ReportAction::Forget) { 96 reports = std::move(mPendingReports); 97 } else { 98 reports = mPendingReports.Clone(); 99 } 100 } 101 102 for (uint32_t i = 0; i < reports.Length(); ++i) { 103 PendingReport& report = reports[i]; 104 105 nsAutoString errorText; 106 nsresult rv; 107 if (!report.mStringParams.IsEmpty()) { 108 rv = nsContentUtils::FormatLocalizedString( 109 report.mPropertiesFile, report.mMessageName.get(), 110 report.mStringParams, errorText); 111 } else { 112 rv = nsContentUtils::GetLocalizedString( 113 report.mPropertiesFile, report.mMessageName.get(), errorText); 114 } 115 if (NS_WARN_IF(NS_FAILED(rv))) { 116 continue; 117 } 118 119 ConsoleUtils::Level level = ConsoleUtils::eLog; 120 switch (report.mErrorFlags) { 121 case nsIScriptError::errorFlag: 122 level = ConsoleUtils::eError; 123 break; 124 case nsIScriptError::warningFlag: 125 level = ConsoleUtils::eWarning; 126 break; 127 default: 128 // default to log otherwise 129 break; 130 } 131 132 ConsoleUtils::ReportForServiceWorkerScope( 133 NS_ConvertUTF8toUTF16(aScope), errorText, report.mSourceFileURI, 134 report.mLineNumber, report.mColumnNumber, level); 135 } 136 } 137 138 void ConsoleReportCollector::FlushConsoleReports(dom::Document* aDocument, 139 ReportAction aAction) { 140 MOZ_ASSERT(NS_IsMainThread()); 141 142 FlushReportsToConsole(aDocument ? aDocument->InnerWindowID() : 0, aAction); 143 } 144 145 void ConsoleReportCollector::FlushConsoleReports(nsILoadGroup* aLoadGroup, 146 ReportAction aAction) { 147 FlushReportsToConsole(nsContentUtils::GetInnerWindowID(aLoadGroup), aAction); 148 } 149 150 void ConsoleReportCollector::FlushConsoleReports( 151 nsIConsoleReportCollector* aCollector) { 152 MOZ_ASSERT(aCollector); 153 154 nsTArray<PendingReport> reports; 155 156 { 157 MutexAutoLock lock(mMutex); 158 reports = std::move(mPendingReports); 159 } 160 161 for (uint32_t i = 0; i < reports.Length(); ++i) { 162 PendingReport& report = reports[i]; 163 aCollector->AddConsoleReport( 164 report.mErrorFlags, report.mCategory, report.mPropertiesFile, 165 report.mSourceFileURI, report.mLineNumber, report.mColumnNumber, 166 report.mMessageName, 167 static_cast<const nsTArray<nsString>&>(report.mStringParams)); 168 } 169 } 170 171 void ConsoleReportCollector::StealConsoleReports( 172 nsTArray<net::ConsoleReportCollected>& aReports) { 173 aReports.Clear(); 174 175 nsTArray<PendingReport> reports; 176 177 { 178 MutexAutoLock lock(mMutex); 179 reports = std::move(mPendingReports); 180 } 181 182 for (const PendingReport& report : reports) { 183 aReports.AppendElement(net::ConsoleReportCollected( 184 report.mErrorFlags, report.mCategory, report.mPropertiesFile, 185 report.mSourceFileURI, report.mLineNumber, report.mColumnNumber, 186 report.mMessageName, report.mStringParams)); 187 } 188 } 189 190 void ConsoleReportCollector::ClearConsoleReports() { 191 MutexAutoLock lock(mMutex); 192 193 mPendingReports.Clear(); 194 } 195 196 ConsoleReportCollector::~ConsoleReportCollector() = default; 197 198 } // namespace mozilla