diff options
author | Brian Smith <brian@dbsoft.org> | 2023-09-28 21:18:27 -0500 |
---|---|---|
committer | Brian Smith <brian@dbsoft.org> | 2023-09-28 21:18:27 -0500 |
commit | b1d111ab6b7e5493226f6d9fe1ba38dc5c467379 (patch) | |
tree | 73a3aa461f3977bc889898d0b9bf89e4ae6c38cc | |
parent | 99c25d8e984905ef96990df66fea6bc12c310bbb (diff) | |
download | uxp-b1d111ab6b7e5493226f6d9fe1ba38dc5c467379.tar.gz |
Issue #1442 - Part 16 - Report stream errors during consumption.
https://bugzilla.mozilla.org/show_bug.cgi?id=1128959
-rw-r--r-- | dom/base/nsContentUtils.cpp | 71 | ||||
-rw-r--r-- | dom/base/nsContentUtils.h | 4 | ||||
-rw-r--r-- | dom/fetch/Fetch.h | 2 | ||||
-rw-r--r-- | dom/fetch/FetchStreamReader.cpp | 51 | ||||
-rw-r--r-- | dom/fetch/FetchStreamReader.h | 3 | ||||
-rw-r--r-- | dom/workers/ServiceWorkerEvents.cpp | 85 |
6 files changed, 139 insertions, 77 deletions
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 8dac3e70d4..4c00f358f2 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -39,6 +39,8 @@ #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/CustomElementRegistry.h" #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/DOMException.h" +#include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/FileSystemSecurity.h" @@ -10079,3 +10081,72 @@ void nsContentUtils::StructuredClone(JSContext* aCx, nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts(); Unused << ports; } + +/* static */ void +nsContentUtils::ExtractErrorValues(JSContext* aCx, + JS::Handle<JS::Value> aValue, + nsACString& aSourceSpecOut, + uint32_t* aLineOut, + uint32_t* aColumnOut, + nsString& aMessageOut) +{ + MOZ_ASSERT(aLineOut); + MOZ_ASSERT(aColumnOut); + + if (aValue.isObject()) { + JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); + RefPtr<dom::DOMException> domException; + + // Try to process as an Error object. Use the file/line/column values + // from the Error as they will be more specific to the root cause of + // the problem. + JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr; + if (err) { + // Use xpc to extract the error message only. We don't actually send + // this report anywhere. + RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport(); + report->Init(err, + "<unknown>", // toString result + false, // chrome + 0); // window ID + + if (!report->mFileName.IsEmpty()) { + CopyUTF16toUTF8(report->mFileName, aSourceSpecOut); + *aLineOut = report->mLineNumber; + *aColumnOut = report->mColumn; + } + aMessageOut.Assign(report->mErrorMsg); + } + + // Next, try to unwrap the rejection value as a DOMException. + else if(NS_SUCCEEDED(UNWRAP_OBJECT(DOMException, obj, domException))) { + + nsAutoString filename; + domException->GetFilename(aCx, filename); + if (!filename.IsEmpty()) { + CopyUTF16toUTF8(filename, aSourceSpecOut); + *aLineOut = domException->LineNumber(aCx); + *aColumnOut = domException->ColumnNumber(); + } + + domException->GetName(aMessageOut); + aMessageOut.AppendLiteral(": "); + + nsAutoString message; + domException->GetMessageMoz(message); + aMessageOut.Append(message); + } + } + + // If we could not unwrap a specific error type, then perform default safe + // string conversions on primitives. Objects will result in "[Object]" + // unfortunately. + if (aMessageOut.IsEmpty()) { + nsAutoJSString jsString; + if (jsString.init(aCx, aValue)) { + aMessageOut = jsString; + } else { + JS_ClearPendingException(aCx); + } + } +} diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 9bfb91add2..6e9f23054a 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1010,6 +1010,10 @@ public: static bool PrefetchEnabled(nsIDocShell* aDocShell); + static void ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue, + nsACString& aSourceSpecOut, uint32_t *aLineOut, + uint32_t *aColumnOut, nsString& aMessageOut); + static nsresult CalculateBufferSizeForImage(const uint32_t& aStride, const mozilla::gfx::IntSize& aImageSize, const mozilla::gfx::SurfaceFormat& aFormat, diff --git a/dom/fetch/Fetch.h b/dom/fetch/Fetch.h index cd7dc598fb..839d003833 100644 --- a/dom/fetch/Fetch.h +++ b/dom/fetch/Fetch.h @@ -209,7 +209,7 @@ public: // reporting way.
//
// Exceptions generated when reading from the ReadableStream are directly sent
- // to the Console (NOTE FOR THE REVIEWER: this is part of patch 16)
+ // to the Console.
void
SetBodyUsed(JSContext* aCx, ErrorResult& aRv);
diff --git a/dom/fetch/FetchStreamReader.cpp b/dom/fetch/FetchStreamReader.cpp index 5d9719a0c1..3a24844dd9 100644 --- a/dom/fetch/FetchStreamReader.cpp +++ b/dom/fetch/FetchStreamReader.cpp @@ -7,6 +7,9 @@ #include "FetchStreamReader.h" #include "InternalResponse.h" #include "mozilla/dom/PromiseBinding.h" +#include "nsContentUtils.h" +#include "nsIScriptError.h" +#include "nsPIDOMWindow.h" namespace mozilla { namespace dom { @@ -296,8 +299,56 @@ void FetchStreamReader::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) { + ReportErrorToConsole(aCx, aValue); CloseAndRelease(NS_ERROR_FAILURE); } +void +FetchStreamReader::ReportErrorToConsole(JSContext* aCx, + JS::Handle<JS::Value> aValue) +{ + nsCString sourceSpec; + uint32_t line = 0; + uint32_t column = 0; + nsString valueString; + + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, + &column, valueString); + + nsTArray<nsString> params; + params.AppendElement(valueString); + + RefPtr<ConsoleReportCollector> reporter = new ConsoleReportCollector(); + reporter->AddConsoleReport(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("ReadableStreamReader.read"), + nsContentUtils::eDOM_PROPERTIES, + sourceSpec, line, column, + NS_LITERAL_CSTRING("ReadableStreamReadingFailed"), + params); + + uint64_t innerWindowId = 0; + + if (NS_IsMainThread()) { + nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mGlobal); + if (window) { + innerWindowId = window->WindowID(); + } + reporter->FlushReportsByWindowId(innerWindowId); + return; + } + + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + if (workerPrivate) { + innerWindowId = workerPrivate->WindowID(); + } + + RefPtr<Runnable> r = NS_NewRunnableFunction( + [reporter, innerWindowId] () { + reporter->FlushReportsByWindowId(innerWindowId); + }); + + workerPrivate->DispatchToMainThread(r.forget()); +} + } // dom namespace } // mozilla namespace diff --git a/dom/fetch/FetchStreamReader.h b/dom/fetch/FetchStreamReader.h index 8984a2ea73..d71021fdc8 100644 --- a/dom/fetch/FetchStreamReader.h +++ b/dom/fetch/FetchStreamReader.h @@ -55,6 +55,9 @@ private: nsresult WriteBuffer(); + void + ReportErrorToConsole(JSContext* aCx, JS::Handle<JS::Value> aValue); + nsCOMPtr<nsIGlobalObject> mGlobal; nsCOMPtr<nsIEventTarget> mOwningEventTarget; diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp index 7c9add4060..569422da25 100644 --- a/dom/workers/ServiceWorkerEvents.cpp +++ b/dom/workers/ServiceWorkerEvents.cpp @@ -6,6 +6,7 @@ #include "ServiceWorkerEvents.h" #include "nsAutoPtr.h" +#include "nsContentUtils.h" #include "nsIConsoleReportCollector.h" #include "nsIHttpChannelInternal.h" #include "nsINetworkInterceptController.h" @@ -30,8 +31,6 @@ #include "mozilla/Move.h" #include "mozilla/Preferences.h" #include "mozilla/dom/BodyUtil.h" -#include "mozilla/dom/DOMException.h" -#include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/EncodingUtils.h" #include "mozilla/dom/FetchEventBinding.h" #include "mozilla/dom/MessagePort.h" @@ -404,76 +403,6 @@ void RespondWithCopyComplete(void* aClosure, nsresult aStatus) MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event)); } -namespace { - -void -ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue, - nsACString& aSourceSpecOut, uint32_t *aLineOut, - uint32_t *aColumnOut, nsString& aMessageOut) -{ - MOZ_ASSERT(aLineOut); - MOZ_ASSERT(aColumnOut); - - if (aValue.isObject()) { - JS::Rooted<JSObject*> obj(aCx, &aValue.toObject()); - RefPtr<DOMException> domException; - - // Try to process as an Error object. Use the file/line/column values - // from the Error as they will be more specific to the root cause of - // the problem. - JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr; - if (err) { - // Use xpc to extract the error message only. We don't actually send - // this report anywhere. - RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport(); - report->Init(err, - "<unknown>", // toString result - false, // chrome - 0); // window ID - - if (!report->mFileName.IsEmpty()) { - CopyUTF16toUTF8(report->mFileName, aSourceSpecOut); - *aLineOut = report->mLineNumber; - *aColumnOut = report->mColumn; - } - aMessageOut.Assign(report->mErrorMsg); - } - - // Next, try to unwrap the rejection value as a DOMException. - else if(NS_SUCCEEDED(UNWRAP_OBJECT(DOMException, obj, domException))) { - - nsAutoString filename; - domException->GetFilename(aCx, filename); - if (!filename.IsEmpty()) { - CopyUTF16toUTF8(filename, aSourceSpecOut); - *aLineOut = domException->LineNumber(aCx); - *aColumnOut = domException->ColumnNumber(); - } - - domException->GetName(aMessageOut); - aMessageOut.AppendLiteral(": "); - - nsAutoString message; - domException->GetMessageMoz(message); - aMessageOut.Append(message); - } - } - - // If we could not unwrap a specific error type, then perform default safe - // string conversions on primitives. Objects will result in "[Object]" - // unfortunately. - if (aMessageOut.IsEmpty()) { - nsAutoJSString jsString; - if (jsString.init(aCx, aValue)) { - aMessageOut = jsString; - } else { - JS_ClearPendingException(aCx); - } - } -} - -} // anonymous namespace - class MOZ_STACK_CLASS AutoCancel { RefPtr<RespondWithHandler> mOwner; @@ -595,7 +524,8 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu uint32_t line = 0; uint32_t column = 0; nsString valueString; - ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString); + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, + valueString); autoCancel.SetCancelMessageAndLocation(sourceSpec, line, column, NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"), @@ -610,7 +540,8 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu uint32_t line = 0; uint32_t column = 0; nsString valueString; - ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString); + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, + valueString); autoCancel.SetCancelMessageAndLocation(sourceSpec, line, column, NS_LITERAL_CSTRING("InterceptedNonResponseWithURL"), @@ -758,7 +689,8 @@ RespondWithHandler::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu uint32_t column = mRespondWithColumnNumber; nsString valueString; - ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, valueString); + nsContentUtils::ExtractErrorValues(aCx, aValue, sourceSpec, &line, &column, + valueString); ::AsyncLog(mInterceptedChannel, sourceSpec, line, column, NS_LITERAL_CSTRING("InterceptionRejectedResponseWithURL"), @@ -896,7 +828,8 @@ public: nsCString spec; uint32_t line = 0; uint32_t column = 0; - ExtractErrorValues(aCx, aValue, spec, &line, &column, mRejectValue); + nsContentUtils::ExtractErrorValues(aCx, aValue, spec, &line, &column, + mRejectValue); // only use the extracted location if we found one if (!spec.IsEmpty()) { |