Bug 1856663 - Add more chunks for Android mochitest-plain. r=jmaher,taskgraph-reviewe...
[gecko.git] / dom / bindings / nsScriptError.cpp
blob53c1ba04b74748fa601b162411f9131e7f7dcdde
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/. */
7 /*
8 * nsIScriptError implementation.
9 */
11 #include "nsScriptError.h"
12 #include "js/Printf.h"
13 #include "MainThreadUtils.h"
14 #include "mozilla/Assertions.h"
15 #include "nsContentUtils.h"
16 #include "nsGlobalWindowInner.h"
17 #include "nsNetUtil.h"
18 #include "nsPIDOMWindow.h"
19 #include "nsIMutableArray.h"
20 #include "nsIScriptError.h"
21 #include "mozilla/BasePrincipal.h"
23 nsScriptErrorBase::nsScriptErrorBase()
24 : mMessage(),
25 mMessageName(),
26 mSourceName(),
27 mCssSelectors(),
28 mSourceId(0),
29 mLineNumber(0),
30 mSourceLine(),
31 mColumnNumber(0),
32 mFlags(0),
33 mCategory(),
34 mOuterWindowID(0),
35 mInnerWindowID(0),
36 mMicroSecondTimeStamp(0),
37 mInitializedOnMainThread(false),
38 mIsFromPrivateWindow(false),
39 mIsFromChromeContext(false),
40 mIsPromiseRejection(false),
41 mIsForwardedFromContentProcess(false) {}
43 nsScriptErrorBase::~nsScriptErrorBase() = default;
45 void nsScriptErrorBase::AddNote(nsIScriptErrorNote* note) {
46 mNotes.AppendObject(note);
49 void nsScriptErrorBase::InitializeOnMainThread() {
50 MOZ_ASSERT(NS_IsMainThread());
51 MOZ_ASSERT(!mInitializedOnMainThread);
53 if (mInnerWindowID) {
54 nsGlobalWindowInner* window =
55 nsGlobalWindowInner::GetInnerWindowWithId(mInnerWindowID);
56 if (window) {
57 nsPIDOMWindowOuter* outer = window->GetOuterWindow();
58 if (outer) mOuterWindowID = outer->WindowID();
59 mIsFromChromeContext = ComputeIsFromChromeContext(window);
60 mIsFromPrivateWindow = ComputeIsFromPrivateWindow(window);
64 mInitializedOnMainThread = true;
67 NS_IMETHODIMP
68 nsScriptErrorBase::InitSourceId(uint32_t value) {
69 mSourceId = value;
70 return NS_OK;
73 // nsIConsoleMessage methods
74 NS_IMETHODIMP
75 nsScriptErrorBase::GetMessageMoz(nsAString& aMessage) {
76 nsAutoCString message;
77 nsresult rv = ToString(message);
78 if (NS_FAILED(rv)) {
79 return rv;
82 CopyUTF8toUTF16(message, aMessage);
83 return NS_OK;
86 NS_IMETHODIMP
87 nsScriptErrorBase::GetLogLevel(uint32_t* aLogLevel) {
88 if (mFlags & (uint32_t)nsIScriptError::infoFlag) {
89 *aLogLevel = nsIConsoleMessage::info;
90 } else if (mFlags & (uint32_t)nsIScriptError::warningFlag) {
91 *aLogLevel = nsIConsoleMessage::warn;
92 } else {
93 *aLogLevel = nsIConsoleMessage::error;
95 return NS_OK;
98 // nsIScriptError methods
99 NS_IMETHODIMP
100 nsScriptErrorBase::GetErrorMessage(nsAString& aResult) {
101 aResult.Assign(mMessage);
102 return NS_OK;
105 NS_IMETHODIMP
106 nsScriptErrorBase::GetSourceName(nsAString& aResult) {
107 aResult.Assign(mSourceName);
108 return NS_OK;
111 NS_IMETHODIMP
112 nsScriptErrorBase::GetCssSelectors(nsAString& aResult) {
113 aResult.Assign(mCssSelectors);
114 return NS_OK;
117 NS_IMETHODIMP
118 nsScriptErrorBase::SetCssSelectors(const nsAString& aCssSelectors) {
119 mCssSelectors = aCssSelectors;
120 return NS_OK;
123 NS_IMETHODIMP
124 nsScriptErrorBase::GetSourceId(uint32_t* result) {
125 *result = mSourceId;
126 return NS_OK;
129 NS_IMETHODIMP
130 nsScriptErrorBase::GetSourceLine(nsAString& aResult) {
131 aResult.Assign(mSourceLine);
132 return NS_OK;
135 NS_IMETHODIMP
136 nsScriptErrorBase::GetLineNumber(uint32_t* result) {
137 *result = mLineNumber;
138 return NS_OK;
141 NS_IMETHODIMP
142 nsScriptErrorBase::GetColumnNumber(uint32_t* result) {
143 *result = mColumnNumber;
144 return NS_OK;
147 NS_IMETHODIMP
148 nsScriptErrorBase::GetFlags(uint32_t* result) {
149 *result = mFlags;
150 return NS_OK;
153 NS_IMETHODIMP
154 nsScriptErrorBase::GetCategory(char** result) {
155 *result = ToNewCString(mCategory);
156 return NS_OK;
159 NS_IMETHODIMP
160 nsScriptErrorBase::GetHasException(bool* aHasException) {
161 *aHasException = false;
162 return NS_OK;
165 NS_IMETHODIMP
166 nsScriptErrorBase::GetException(JS::MutableHandle<JS::Value> aException) {
167 aException.setUndefined();
168 return NS_OK;
171 NS_IMETHODIMP
172 nsScriptErrorBase::SetException(JS::Handle<JS::Value> aStack) {
173 return NS_ERROR_NOT_IMPLEMENTED;
176 NS_IMETHODIMP
177 nsScriptErrorBase::GetStack(JS::MutableHandle<JS::Value> aStack) {
178 aStack.setUndefined();
179 return NS_OK;
182 NS_IMETHODIMP
183 nsScriptErrorBase::SetStack(JS::Handle<JS::Value> aStack) { return NS_OK; }
185 NS_IMETHODIMP
186 nsScriptErrorBase::GetStackGlobal(JS::MutableHandle<JS::Value> aStackGlobal) {
187 aStackGlobal.setUndefined();
188 return NS_OK;
191 NS_IMETHODIMP
192 nsScriptErrorBase::GetErrorMessageName(nsAString& aErrorMessageName) {
193 aErrorMessageName = mMessageName;
194 return NS_OK;
197 NS_IMETHODIMP
198 nsScriptErrorBase::SetErrorMessageName(const nsAString& aErrorMessageName) {
199 mMessageName = aErrorMessageName;
200 return NS_OK;
203 static void AssignSourceNameHelper(nsString& aSourceNameDest,
204 const nsAString& aSourceNameSrc) {
205 if (aSourceNameSrc.IsEmpty()) return;
207 aSourceNameDest.Assign(aSourceNameSrc);
209 nsCOMPtr<nsIURI> uri;
210 nsAutoCString pass;
211 if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
212 NS_SUCCEEDED(uri->GetPassword(pass)) && !pass.IsEmpty()) {
213 NS_GetSanitizedURIStringFromURI(uri, aSourceNameDest);
217 static void AssignSourceNameHelper(nsIURI* aSourceURI,
218 nsString& aSourceNameDest) {
219 if (!aSourceURI) return;
221 if (NS_FAILED(NS_GetSanitizedURIStringFromURI(aSourceURI, aSourceNameDest))) {
222 aSourceNameDest.AssignLiteral("[nsIURI::GetSpec failed]");
226 NS_IMETHODIMP
227 nsScriptErrorBase::Init(const nsAString& message, const nsAString& sourceName,
228 const nsAString& sourceLine, uint32_t lineNumber,
229 uint32_t columnNumber, uint32_t flags,
230 const nsACString& category, bool fromPrivateWindow,
231 bool fromChromeContext) {
232 InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
233 category, 0 /* inner Window ID */, fromChromeContext);
234 AssignSourceNameHelper(mSourceName, sourceName);
236 mIsFromPrivateWindow = fromPrivateWindow;
237 mIsFromChromeContext = fromChromeContext;
238 return NS_OK;
241 void nsScriptErrorBase::InitializationHelper(
242 const nsAString& message, const nsAString& sourceLine, uint32_t lineNumber,
243 uint32_t columnNumber, uint32_t flags, const nsACString& category,
244 uint64_t aInnerWindowID, bool aFromChromeContext) {
245 mMessage.Assign(message);
246 mLineNumber = lineNumber;
247 mSourceLine.Assign(sourceLine);
248 mColumnNumber = columnNumber;
249 mFlags = flags;
250 mCategory = category;
251 mMicroSecondTimeStamp = JS_Now();
252 mInnerWindowID = aInnerWindowID;
253 mIsFromChromeContext = aFromChromeContext;
256 NS_IMETHODIMP
257 nsScriptErrorBase::InitWithWindowID(const nsAString& message,
258 const nsAString& sourceName,
259 const nsAString& sourceLine,
260 uint32_t lineNumber, uint32_t columnNumber,
261 uint32_t flags, const nsACString& category,
262 uint64_t aInnerWindowID,
263 bool aFromChromeContext) {
264 InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
265 category, aInnerWindowID, aFromChromeContext);
266 AssignSourceNameHelper(mSourceName, sourceName);
268 if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
270 return NS_OK;
273 NS_IMETHODIMP
274 nsScriptErrorBase::InitWithSanitizedSource(
275 const nsAString& message, const nsAString& sourceName,
276 const nsAString& sourceLine, uint32_t lineNumber, uint32_t columnNumber,
277 uint32_t flags, const nsACString& category, uint64_t aInnerWindowID,
278 bool aFromChromeContext) {
279 InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
280 category, aInnerWindowID, aFromChromeContext);
281 mSourceName = sourceName;
283 if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
285 return NS_OK;
288 NS_IMETHODIMP
289 nsScriptErrorBase::InitWithSourceURI(const nsAString& message,
290 nsIURI* sourceURI,
291 const nsAString& sourceLine,
292 uint32_t lineNumber, uint32_t columnNumber,
293 uint32_t flags, const nsACString& category,
294 uint64_t aInnerWindowID,
295 bool aFromChromeContext) {
296 InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
297 category, aInnerWindowID, aFromChromeContext);
298 AssignSourceNameHelper(sourceURI, mSourceName);
300 if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
302 return NS_OK;
305 static nsresult ToStringHelper(const char* aSeverity, const nsString& aMessage,
306 const nsString& aSourceName,
307 const nsString* aSourceLine,
308 uint32_t aLineNumber, uint32_t aColumnNumber,
309 nsACString& /*UTF8*/ aResult) {
310 static const char format0[] =
311 "[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
312 static const char format1[] = "[%s: \"%s\" {file: \"%s\" line: %d}]";
313 static const char format2[] = "[%s: \"%s\"]";
315 JS::UniqueChars temp;
316 char* tempMessage = nullptr;
317 char* tempSourceName = nullptr;
318 char* tempSourceLine = nullptr;
320 if (!aMessage.IsEmpty()) tempMessage = ToNewUTF8String(aMessage);
321 if (!aSourceName.IsEmpty())
322 // Use at most 512 characters from mSourceName.
323 tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512));
324 if (aSourceLine && !aSourceLine->IsEmpty())
325 // Use at most 512 characters from mSourceLine.
326 tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512));
328 if (nullptr != tempSourceName && nullptr != tempSourceLine) {
329 temp = JS_smprintf(format0, aSeverity, tempMessage, tempSourceName,
330 aLineNumber, aColumnNumber, tempSourceLine);
331 } else if (!aSourceName.IsEmpty()) {
332 temp = JS_smprintf(format1, aSeverity, tempMessage, tempSourceName,
333 aLineNumber);
334 } else {
335 temp = JS_smprintf(format2, aSeverity, tempMessage);
338 if (nullptr != tempMessage) free(tempMessage);
339 if (nullptr != tempSourceName) free(tempSourceName);
340 if (nullptr != tempSourceLine) free(tempSourceLine);
342 if (!temp) return NS_ERROR_OUT_OF_MEMORY;
344 aResult.Assign(temp.get());
345 return NS_OK;
348 NS_IMETHODIMP
349 nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult) {
350 static const char error[] = "JavaScript Error";
351 static const char warning[] = "JavaScript Warning";
353 const char* severity =
354 !(mFlags & nsIScriptError::warningFlag) ? error : warning;
356 return ToStringHelper(severity, mMessage, mSourceName, &mSourceLine,
357 mLineNumber, mColumnNumber, aResult);
360 NS_IMETHODIMP
361 nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID) {
362 NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
363 "This can't be safely determined off the main thread, "
364 "returning an inaccurate value!");
366 if (!mInitializedOnMainThread && NS_IsMainThread()) {
367 InitializeOnMainThread();
370 *aOuterWindowID = mOuterWindowID;
371 return NS_OK;
374 NS_IMETHODIMP
375 nsScriptErrorBase::GetInnerWindowID(uint64_t* aInnerWindowID) {
376 *aInnerWindowID = mInnerWindowID;
377 return NS_OK;
380 NS_IMETHODIMP
381 nsScriptErrorBase::GetTimeStamp(int64_t* aTimeStamp) {
382 *aTimeStamp = mMicroSecondTimeStamp / 1000;
383 return NS_OK;
386 NS_IMETHODIMP
387 nsScriptErrorBase::GetMicroSecondTimeStamp(int64_t* aTimeStamp) {
388 *aTimeStamp = mMicroSecondTimeStamp;
389 return NS_OK;
392 NS_IMETHODIMP
393 nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow) {
394 NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
395 "This can't be safely determined off the main thread, "
396 "returning an inaccurate value!");
398 if (!mInitializedOnMainThread && NS_IsMainThread()) {
399 InitializeOnMainThread();
402 *aIsFromPrivateWindow = mIsFromPrivateWindow;
403 return NS_OK;
406 NS_IMETHODIMP
407 nsScriptErrorBase::GetIsFromChromeContext(bool* aIsFromChromeContext) {
408 NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
409 "This can't be safely determined off the main thread, "
410 "returning an inaccurate value!");
411 if (!mInitializedOnMainThread && NS_IsMainThread()) {
412 InitializeOnMainThread();
414 *aIsFromChromeContext = mIsFromChromeContext;
415 return NS_OK;
418 NS_IMETHODIMP
419 nsScriptErrorBase::GetIsPromiseRejection(bool* aIsPromiseRejection) {
420 *aIsPromiseRejection = mIsPromiseRejection;
421 return NS_OK;
424 NS_IMETHODIMP
425 nsScriptErrorBase::InitIsPromiseRejection(bool aIsPromiseRejection) {
426 mIsPromiseRejection = aIsPromiseRejection;
427 return NS_OK;
430 NS_IMETHODIMP
431 nsScriptErrorBase::GetIsForwardedFromContentProcess(
432 bool* aIsForwardedFromContentProcess) {
433 *aIsForwardedFromContentProcess = mIsForwardedFromContentProcess;
434 return NS_OK;
437 NS_IMETHODIMP
438 nsScriptErrorBase::SetIsForwardedFromContentProcess(
439 bool aIsForwardedFromContentProcess) {
440 mIsForwardedFromContentProcess = aIsForwardedFromContentProcess;
441 return NS_OK;
444 NS_IMETHODIMP
445 nsScriptErrorBase::GetNotes(nsIArray** aNotes) {
446 nsresult rv = NS_OK;
447 nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
448 NS_ENSURE_SUCCESS(rv, rv);
450 uint32_t len = mNotes.Length();
451 for (uint32_t i = 0; i < len; i++) array->AppendElement(mNotes[i]);
452 array.forget(aNotes);
454 return NS_OK;
457 /* static */
458 bool nsScriptErrorBase::ComputeIsFromPrivateWindow(
459 nsGlobalWindowInner* aWindow) {
460 // Never mark exceptions from chrome windows as having come from private
461 // windows, since we always want them to be reported.
462 nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
463 return aWindow->IsPrivateBrowsing() && !winPrincipal->IsSystemPrincipal();
466 /* static */
467 bool nsScriptErrorBase::ComputeIsFromChromeContext(
468 nsGlobalWindowInner* aWindow) {
469 nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
470 return winPrincipal->IsSystemPrincipal();
473 NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
475 nsScriptErrorNote::nsScriptErrorNote()
476 : mMessage(),
477 mSourceName(),
478 mSourceId(0),
479 mLineNumber(0),
480 mColumnNumber(0) {}
482 nsScriptErrorNote::~nsScriptErrorNote() = default;
484 void nsScriptErrorNote::Init(const nsAString& message,
485 const nsAString& sourceName, uint32_t sourceId,
486 uint32_t lineNumber, uint32_t columnNumber) {
487 mMessage.Assign(message);
488 AssignSourceNameHelper(mSourceName, sourceName);
489 mSourceId = sourceId;
490 mLineNumber = lineNumber;
491 mColumnNumber = columnNumber;
494 // nsIScriptErrorNote methods
495 NS_IMETHODIMP
496 nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
497 aResult.Assign(mMessage);
498 return NS_OK;
501 NS_IMETHODIMP
502 nsScriptErrorNote::GetSourceName(nsAString& aResult) {
503 aResult.Assign(mSourceName);
504 return NS_OK;
507 NS_IMETHODIMP
508 nsScriptErrorNote::GetSourceId(uint32_t* result) {
509 *result = mSourceId;
510 return NS_OK;
513 NS_IMETHODIMP
514 nsScriptErrorNote::GetLineNumber(uint32_t* result) {
515 *result = mLineNumber;
516 return NS_OK;
519 NS_IMETHODIMP
520 nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
521 *result = mColumnNumber;
522 return NS_OK;
525 NS_IMETHODIMP
526 nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult) {
527 return ToStringHelper("JavaScript Note", mMessage, mSourceName, nullptr,
528 mLineNumber, mColumnNumber, aResult);
531 NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)