summaryrefslogtreecommitdiffstats
path: root/dom/bindings/nsScriptError.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/bindings/nsScriptError.cpp')
-rw-r--r--dom/bindings/nsScriptError.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/dom/bindings/nsScriptError.cpp b/dom/bindings/nsScriptError.cpp
new file mode 100644
index 0000000000..0cc71e0bcc
--- /dev/null
+++ b/dom/bindings/nsScriptError.cpp
@@ -0,0 +1,531 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+ * nsIScriptError implementation.
+ */
+
+#include "nsScriptError.h"
+#include "js/Printf.h"
+#include "MainThreadUtils.h"
+#include "mozilla/Assertions.h"
+#include "nsContentUtils.h"
+#include "nsGlobalWindow.h"
+#include "nsNetUtil.h"
+#include "nsPIDOMWindow.h"
+#include "nsIMutableArray.h"
+#include "nsIScriptError.h"
+#include "mozilla/BasePrincipal.h"
+
+nsScriptErrorBase::nsScriptErrorBase()
+ : mMessage(),
+ mMessageName(),
+ mSourceName(),
+ mCssSelectors(),
+ mSourceId(0),
+ mLineNumber(0),
+ mSourceLine(),
+ mColumnNumber(0),
+ mFlags(0),
+ mCategory(),
+ mOuterWindowID(0),
+ mInnerWindowID(0),
+ mMicroSecondTimeStamp(0),
+ mInitializedOnMainThread(false),
+ mIsFromPrivateWindow(false),
+ mIsFromChromeContext(false),
+ mIsPromiseRejection(false),
+ mIsForwardedFromContentProcess(false) {}
+
+nsScriptErrorBase::~nsScriptErrorBase() = default;
+
+void nsScriptErrorBase::AddNote(nsIScriptErrorNote* note) {
+ mNotes.AppendObject(note);
+}
+
+void nsScriptErrorBase::InitializeOnMainThread() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mInitializedOnMainThread);
+
+ if (mInnerWindowID) {
+ nsGlobalWindowInner* window =
+ nsGlobalWindowInner::GetInnerWindowWithId(mInnerWindowID);
+ if (window) {
+ nsPIDOMWindowOuter* outer = window->GetOuterWindow();
+ if (outer) mOuterWindowID = outer->WindowID();
+ mIsFromChromeContext = ComputeIsFromChromeContext(window);
+ mIsFromPrivateWindow = ComputeIsFromPrivateWindow(window);
+ }
+ }
+
+ mInitializedOnMainThread = true;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::InitSourceId(uint32_t value) {
+ mSourceId = value;
+ return NS_OK;
+}
+
+// nsIConsoleMessage methods
+NS_IMETHODIMP
+nsScriptErrorBase::GetMessageMoz(nsAString& aMessage) {
+ nsAutoCString message;
+ nsresult rv = ToString(message);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ CopyUTF8toUTF16(message, aMessage);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetLogLevel(uint32_t* aLogLevel) {
+ if (mFlags & (uint32_t)nsIScriptError::infoFlag) {
+ *aLogLevel = nsIConsoleMessage::info;
+ } else if (mFlags & (uint32_t)nsIScriptError::warningFlag) {
+ *aLogLevel = nsIConsoleMessage::warn;
+ } else {
+ *aLogLevel = nsIConsoleMessage::error;
+ }
+ return NS_OK;
+}
+
+// nsIScriptError methods
+NS_IMETHODIMP
+nsScriptErrorBase::GetErrorMessage(nsAString& aResult) {
+ aResult.Assign(mMessage);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetSourceName(nsAString& aResult) {
+ aResult.Assign(mSourceName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetCssSelectors(nsAString& aResult) {
+ aResult.Assign(mCssSelectors);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::SetCssSelectors(const nsAString& aCssSelectors) {
+ mCssSelectors = aCssSelectors;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetSourceId(uint32_t* result) {
+ *result = mSourceId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetSourceLine(nsAString& aResult) {
+ aResult.Assign(mSourceLine);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetLineNumber(uint32_t* result) {
+ *result = mLineNumber;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetColumnNumber(uint32_t* result) {
+ *result = mColumnNumber;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetFlags(uint32_t* result) {
+ *result = mFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetCategory(char** result) {
+ *result = ToNewCString(mCategory);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetHasException(bool* aHasException) {
+ *aHasException = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetException(JS::MutableHandle<JS::Value> aException) {
+ aException.setUndefined();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::SetException(JS::Handle<JS::Value> aStack) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetStack(JS::MutableHandle<JS::Value> aStack) {
+ aStack.setUndefined();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::SetStack(JS::Handle<JS::Value> aStack) { return NS_OK; }
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetStackGlobal(JS::MutableHandle<JS::Value> aStackGlobal) {
+ aStackGlobal.setUndefined();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetErrorMessageName(nsAString& aErrorMessageName) {
+ aErrorMessageName = mMessageName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::SetErrorMessageName(const nsAString& aErrorMessageName) {
+ mMessageName = aErrorMessageName;
+ return NS_OK;
+}
+
+static void AssignSourceNameHelper(nsString& aSourceNameDest,
+ const nsAString& aSourceNameSrc) {
+ if (aSourceNameSrc.IsEmpty()) return;
+
+ aSourceNameDest.Assign(aSourceNameSrc);
+
+ nsCOMPtr<nsIURI> uri;
+ nsAutoCString pass;
+ if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
+ NS_SUCCEEDED(uri->GetPassword(pass)) && !pass.IsEmpty()) {
+ NS_GetSanitizedURIStringFromURI(uri, aSourceNameDest);
+ }
+}
+
+static void AssignSourceNameHelper(nsIURI* aSourceURI,
+ nsString& aSourceNameDest) {
+ if (!aSourceURI) return;
+
+ if (NS_FAILED(NS_GetSanitizedURIStringFromURI(aSourceURI, aSourceNameDest))) {
+ aSourceNameDest.AssignLiteral("[nsIURI::GetSpec failed]");
+ }
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::Init(const nsAString& message, const nsAString& sourceName,
+ const nsAString& sourceLine, uint32_t lineNumber,
+ uint32_t columnNumber, uint32_t flags,
+ const nsACString& category, bool fromPrivateWindow,
+ bool fromChromeContext) {
+ InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
+ category, 0 /* inner Window ID */, fromChromeContext);
+ AssignSourceNameHelper(mSourceName, sourceName);
+
+ mIsFromPrivateWindow = fromPrivateWindow;
+ mIsFromChromeContext = fromChromeContext;
+ return NS_OK;
+}
+
+void nsScriptErrorBase::InitializationHelper(
+ const nsAString& message, const nsAString& sourceLine, uint32_t lineNumber,
+ uint32_t columnNumber, uint32_t flags, const nsACString& category,
+ uint64_t aInnerWindowID, bool aFromChromeContext) {
+ mMessage.Assign(message);
+ mLineNumber = lineNumber;
+ mSourceLine.Assign(sourceLine);
+ mColumnNumber = columnNumber;
+ mFlags = flags;
+ mCategory = category;
+ mMicroSecondTimeStamp = JS_Now();
+ mInnerWindowID = aInnerWindowID;
+ mIsFromChromeContext = aFromChromeContext;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::InitWithWindowID(const nsAString& message,
+ const nsAString& sourceName,
+ const nsAString& sourceLine,
+ uint32_t lineNumber, uint32_t columnNumber,
+ uint32_t flags, const nsACString& category,
+ uint64_t aInnerWindowID,
+ bool aFromChromeContext) {
+ InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
+ category, aInnerWindowID, aFromChromeContext);
+ AssignSourceNameHelper(mSourceName, sourceName);
+
+ if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::InitWithSanitizedSource(
+ const nsAString& message, const nsAString& sourceName,
+ const nsAString& sourceLine, uint32_t lineNumber, uint32_t columnNumber,
+ uint32_t flags, const nsACString& category, uint64_t aInnerWindowID,
+ bool aFromChromeContext) {
+ InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
+ category, aInnerWindowID, aFromChromeContext);
+ mSourceName = sourceName;
+
+ if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::InitWithSourceURI(const nsAString& message,
+ nsIURI* sourceURI,
+ const nsAString& sourceLine,
+ uint32_t lineNumber, uint32_t columnNumber,
+ uint32_t flags, const nsACString& category,
+ uint64_t aInnerWindowID,
+ bool aFromChromeContext) {
+ InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
+ category, aInnerWindowID, aFromChromeContext);
+ AssignSourceNameHelper(sourceURI, mSourceName);
+
+ if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
+
+ return NS_OK;
+}
+
+static nsresult ToStringHelper(const char* aSeverity, const nsString& aMessage,
+ const nsString& aSourceName,
+ const nsString* aSourceLine,
+ uint32_t aLineNumber, uint32_t aColumnNumber,
+ nsACString& /*UTF8*/ aResult) {
+ static const char format0[] =
+ "[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
+ static const char format1[] = "[%s: \"%s\" {file: \"%s\" line: %d}]";
+ static const char format2[] = "[%s: \"%s\"]";
+
+ JS::UniqueChars temp;
+ char* tempMessage = nullptr;
+ char* tempSourceName = nullptr;
+ char* tempSourceLine = nullptr;
+
+ if (!aMessage.IsEmpty()) tempMessage = ToNewUTF8String(aMessage);
+ if (!aSourceName.IsEmpty())
+ // Use at most 512 characters from mSourceName.
+ tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512));
+ if (aSourceLine && !aSourceLine->IsEmpty())
+ // Use at most 512 characters from mSourceLine.
+ tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512));
+
+ if (nullptr != tempSourceName && nullptr != tempSourceLine) {
+ temp = JS_smprintf(format0, aSeverity, tempMessage, tempSourceName,
+ aLineNumber, aColumnNumber, tempSourceLine);
+ } else if (!aSourceName.IsEmpty()) {
+ temp = JS_smprintf(format1, aSeverity, tempMessage, tempSourceName,
+ aLineNumber);
+ } else {
+ temp = JS_smprintf(format2, aSeverity, tempMessage);
+ }
+
+ if (nullptr != tempMessage) free(tempMessage);
+ if (nullptr != tempSourceName) free(tempSourceName);
+ if (nullptr != tempSourceLine) free(tempSourceLine);
+
+ if (!temp) return NS_ERROR_OUT_OF_MEMORY;
+
+ aResult.Assign(temp.get());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult) {
+ static const char error[] = "JavaScript Error";
+ static const char warning[] = "JavaScript Warning";
+
+ const char* severity =
+ !(mFlags & nsIScriptError::warningFlag) ? error : warning;
+
+ return ToStringHelper(severity, mMessage, mSourceName, &mSourceLine,
+ mLineNumber, mColumnNumber, aResult);
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID) {
+ NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
+ "This can't be safely determined off the main thread, "
+ "returning an inaccurate value!");
+
+ if (!mInitializedOnMainThread && NS_IsMainThread()) {
+ InitializeOnMainThread();
+ }
+
+ *aOuterWindowID = mOuterWindowID;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetInnerWindowID(uint64_t* aInnerWindowID) {
+ *aInnerWindowID = mInnerWindowID;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetTimeStamp(int64_t* aTimeStamp) {
+ *aTimeStamp = mMicroSecondTimeStamp / 1000;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetMicroSecondTimeStamp(int64_t* aTimeStamp) {
+ *aTimeStamp = mMicroSecondTimeStamp;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow) {
+ NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
+ "This can't be safely determined off the main thread, "
+ "returning an inaccurate value!");
+
+ if (!mInitializedOnMainThread && NS_IsMainThread()) {
+ InitializeOnMainThread();
+ }
+
+ *aIsFromPrivateWindow = mIsFromPrivateWindow;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetIsFromChromeContext(bool* aIsFromChromeContext) {
+ NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
+ "This can't be safely determined off the main thread, "
+ "returning an inaccurate value!");
+ if (!mInitializedOnMainThread && NS_IsMainThread()) {
+ InitializeOnMainThread();
+ }
+ *aIsFromChromeContext = mIsFromChromeContext;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetIsPromiseRejection(bool* aIsPromiseRejection) {
+ *aIsPromiseRejection = mIsPromiseRejection;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::InitIsPromiseRejection(bool aIsPromiseRejection) {
+ mIsPromiseRejection = aIsPromiseRejection;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetIsForwardedFromContentProcess(
+ bool* aIsForwardedFromContentProcess) {
+ *aIsForwardedFromContentProcess = mIsForwardedFromContentProcess;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::SetIsForwardedFromContentProcess(
+ bool aIsForwardedFromContentProcess) {
+ mIsForwardedFromContentProcess = aIsForwardedFromContentProcess;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorBase::GetNotes(nsIArray** aNotes) {
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t len = mNotes.Length();
+ for (uint32_t i = 0; i < len; i++) array->AppendElement(mNotes[i]);
+ array.forget(aNotes);
+
+ return NS_OK;
+}
+
+/* static */
+bool nsScriptErrorBase::ComputeIsFromPrivateWindow(
+ nsGlobalWindowInner* aWindow) {
+ // Never mark exceptions from chrome windows as having come from private
+ // windows, since we always want them to be reported.
+ nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
+ return aWindow->IsPrivateBrowsing() && !winPrincipal->IsSystemPrincipal();
+}
+
+/* static */
+bool nsScriptErrorBase::ComputeIsFromChromeContext(
+ nsGlobalWindowInner* aWindow) {
+ nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
+ return winPrincipal->IsSystemPrincipal();
+}
+
+NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
+
+nsScriptErrorNote::nsScriptErrorNote()
+ : mMessage(),
+ mSourceName(),
+ mSourceId(0),
+ mLineNumber(0),
+ mColumnNumber(0) {}
+
+nsScriptErrorNote::~nsScriptErrorNote() = default;
+
+void nsScriptErrorNote::Init(const nsAString& message,
+ const nsAString& sourceName, uint32_t sourceId,
+ uint32_t lineNumber, uint32_t columnNumber) {
+ mMessage.Assign(message);
+ AssignSourceNameHelper(mSourceName, sourceName);
+ mSourceId = sourceId;
+ mLineNumber = lineNumber;
+ mColumnNumber = columnNumber;
+}
+
+// nsIScriptErrorNote methods
+NS_IMETHODIMP
+nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
+ aResult.Assign(mMessage);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorNote::GetSourceName(nsAString& aResult) {
+ aResult.Assign(mSourceName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorNote::GetSourceId(uint32_t* result) {
+ *result = mSourceId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorNote::GetLineNumber(uint32_t* result) {
+ *result = mLineNumber;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
+ *result = mColumnNumber;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult) {
+ return ToStringHelper("JavaScript Note", mMessage, mSourceName, nullptr,
+ mLineNumber, mColumnNumber, aResult);
+}
+
+NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)