tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsScriptError.cpp (15031B)


      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 /*
      8 * nsIScriptError implementation.
      9 */
     10 
     11 #include "nsScriptError.h"
     12 
     13 #include "MainThreadUtils.h"
     14 #include "js/Printf.h"
     15 #include "mozilla/Assertions.h"
     16 #include "mozilla/BasePrincipal.h"
     17 #include "nsContentUtils.h"
     18 #include "nsGlobalWindowInner.h"
     19 #include "nsIMutableArray.h"
     20 #include "nsIScriptError.h"
     21 #include "nsNetUtil.h"
     22 #include "nsPIDOMWindow.h"
     23 
     24 nsScriptErrorBase::nsScriptErrorBase()
     25    : mSourceId(0),
     26      mLineNumber(0),
     27      mColumnNumber(0),
     28      mFlags(0),
     29      mOuterWindowID(0),
     30      mInnerWindowID(0),
     31      mMicroSecondTimeStamp(0),
     32      mInitializedOnMainThread(false),
     33      mIsFromPrivateWindow(false),
     34      mIsFromChromeContext(false),
     35      mIsPromiseRejection(false),
     36      mIsForwardedFromContentProcess(false) {}
     37 
     38 nsScriptErrorBase::~nsScriptErrorBase() = default;
     39 
     40 void nsScriptErrorBase::AddNote(nsIScriptErrorNote* note) {
     41  mNotes.AppendObject(note);
     42 }
     43 
     44 void nsScriptErrorBase::InitializeOnMainThread() {
     45  MOZ_ASSERT(NS_IsMainThread());
     46  MOZ_ASSERT(!mInitializedOnMainThread);
     47 
     48  if (mInnerWindowID) {
     49    nsGlobalWindowInner* window =
     50        nsGlobalWindowInner::GetInnerWindowWithId(mInnerWindowID);
     51    if (window) {
     52      nsPIDOMWindowOuter* outer = window->GetOuterWindow();
     53      if (outer) mOuterWindowID = outer->WindowID();
     54      mIsFromChromeContext = ComputeIsFromChromeContext(window);
     55      mIsFromPrivateWindow = ComputeIsFromPrivateWindow(window);
     56    }
     57  }
     58 
     59  mInitializedOnMainThread = true;
     60 }
     61 
     62 NS_IMETHODIMP
     63 nsScriptErrorBase::InitSourceId(uint32_t value) {
     64  mSourceId = value;
     65  return NS_OK;
     66 }
     67 
     68 // nsIConsoleMessage methods
     69 NS_IMETHODIMP
     70 nsScriptErrorBase::GetMessageMoz(nsAString& aMessage) {
     71  nsAutoCString message;
     72  nsresult rv = ToString(message);
     73  if (NS_FAILED(rv)) {
     74    return rv;
     75  }
     76 
     77  CopyUTF8toUTF16(message, aMessage);
     78  return NS_OK;
     79 }
     80 
     81 NS_IMETHODIMP
     82 nsScriptErrorBase::GetLogLevel(uint32_t* aLogLevel) {
     83  if (mFlags & (uint32_t)nsIScriptError::infoFlag) {
     84    *aLogLevel = nsIConsoleMessage::info;
     85  } else if (mFlags & (uint32_t)nsIScriptError::warningFlag) {
     86    *aLogLevel = nsIConsoleMessage::warn;
     87  } else {
     88    *aLogLevel = nsIConsoleMessage::error;
     89  }
     90  return NS_OK;
     91 }
     92 
     93 // nsIScriptError methods
     94 NS_IMETHODIMP
     95 nsScriptErrorBase::GetErrorMessage(nsAString& aResult) {
     96  aResult.Assign(mMessage);
     97  return NS_OK;
     98 }
     99 
    100 NS_IMETHODIMP
    101 nsScriptErrorBase::GetSourceName(nsACString& aResult) {
    102  aResult.Assign(mSourceName);
    103  return NS_OK;
    104 }
    105 
    106 NS_IMETHODIMP
    107 nsScriptErrorBase::GetCssSelectors(nsAString& aResult) {
    108  aResult.Assign(mCssSelectors);
    109  return NS_OK;
    110 }
    111 
    112 NS_IMETHODIMP
    113 nsScriptErrorBase::SetCssSelectors(const nsAString& aCssSelectors) {
    114  mCssSelectors = aCssSelectors;
    115  return NS_OK;
    116 }
    117 
    118 NS_IMETHODIMP
    119 nsScriptErrorBase::GetSourceId(uint32_t* result) {
    120  *result = mSourceId;
    121  return NS_OK;
    122 }
    123 
    124 NS_IMETHODIMP
    125 nsScriptErrorBase::GetLineNumber(uint32_t* result) {
    126  *result = mLineNumber;
    127  return NS_OK;
    128 }
    129 
    130 NS_IMETHODIMP
    131 nsScriptErrorBase::GetColumnNumber(uint32_t* result) {
    132  *result = mColumnNumber;
    133  return NS_OK;
    134 }
    135 
    136 NS_IMETHODIMP
    137 nsScriptErrorBase::GetFlags(uint32_t* result) {
    138  *result = mFlags;
    139  return NS_OK;
    140 }
    141 
    142 NS_IMETHODIMP
    143 nsScriptErrorBase::GetCategory(char** result) {
    144  *result = ToNewCString(mCategory);
    145  return NS_OK;
    146 }
    147 
    148 NS_IMETHODIMP
    149 nsScriptErrorBase::GetHasException(bool* aHasException) {
    150  *aHasException = false;
    151  return NS_OK;
    152 }
    153 
    154 NS_IMETHODIMP
    155 nsScriptErrorBase::GetException(JS::MutableHandle<JS::Value> aException) {
    156  aException.setUndefined();
    157  return NS_OK;
    158 }
    159 
    160 NS_IMETHODIMP
    161 nsScriptErrorBase::SetException(JS::Handle<JS::Value> aStack) {
    162  return NS_ERROR_NOT_IMPLEMENTED;
    163 }
    164 
    165 NS_IMETHODIMP
    166 nsScriptErrorBase::GetStack(JS::MutableHandle<JS::Value> aStack) {
    167  aStack.setUndefined();
    168  return NS_OK;
    169 }
    170 
    171 NS_IMETHODIMP
    172 nsScriptErrorBase::SetStack(JS::Handle<JS::Value> aStack) { return NS_OK; }
    173 
    174 NS_IMETHODIMP
    175 nsScriptErrorBase::GetStackGlobal(JS::MutableHandle<JS::Value> aStackGlobal) {
    176  aStackGlobal.setUndefined();
    177  return NS_OK;
    178 }
    179 
    180 NS_IMETHODIMP
    181 nsScriptErrorBase::GetErrorMessageName(nsAString& aErrorMessageName) {
    182  aErrorMessageName = mMessageName;
    183  return NS_OK;
    184 }
    185 
    186 NS_IMETHODIMP
    187 nsScriptErrorBase::SetErrorMessageName(const nsAString& aErrorMessageName) {
    188  mMessageName = aErrorMessageName;
    189  return NS_OK;
    190 }
    191 
    192 static void AssignSourceNameHelper(nsCString& aSourceNameDest,
    193                                   const nsACString& aSourceNameSrc) {
    194  if (aSourceNameSrc.IsEmpty()) {
    195    return;
    196  }
    197 
    198  aSourceNameDest.Assign(aSourceNameSrc);
    199 
    200  nsCOMPtr<nsIURI> uri;
    201  nsAutoCString pass;
    202  if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
    203      NS_SUCCEEDED(uri->GetPassword(pass)) && !pass.IsEmpty()) {
    204    NS_GetSanitizedURIStringFromURI(uri, aSourceNameDest);
    205  }
    206 }
    207 
    208 static void AssignSourceNameHelper(nsIURI* aSourceURI,
    209                                   nsCString& aSourceNameDest) {
    210  if (!aSourceURI) return;
    211 
    212  if (NS_FAILED(NS_GetSanitizedURIStringFromURI(aSourceURI, aSourceNameDest))) {
    213    aSourceNameDest.AssignLiteral("[nsIURI::GetSpec failed]");
    214  }
    215 }
    216 
    217 NS_IMETHODIMP
    218 nsScriptErrorBase::Init(const nsAString& message, const nsACString& sourceName,
    219                        uint32_t lineNumber, uint32_t columnNumber,
    220                        uint32_t flags, const nsACString& category,
    221                        bool fromPrivateWindow, bool fromChromeContext) {
    222  InitializationHelper(message, lineNumber, columnNumber, flags, category,
    223                       0 /* inner Window ID */, fromChromeContext);
    224  AssignSourceNameHelper(mSourceName, sourceName);
    225 
    226  mIsFromPrivateWindow = fromPrivateWindow;
    227  mIsFromChromeContext = fromChromeContext;
    228  return NS_OK;
    229 }
    230 
    231 void nsScriptErrorBase::InitializationHelper(
    232    const nsAString& message, uint32_t lineNumber, uint32_t columnNumber,
    233    uint32_t flags, const nsACString& category, uint64_t aInnerWindowID,
    234    bool aFromChromeContext) {
    235  mMessage.Assign(message);
    236  mLineNumber = lineNumber;
    237  mColumnNumber = columnNumber;
    238  mFlags = flags;
    239  mCategory = category;
    240  mMicroSecondTimeStamp = JS_Now();
    241  mInnerWindowID = aInnerWindowID;
    242  mIsFromChromeContext = aFromChromeContext;
    243 }
    244 
    245 NS_IMETHODIMP
    246 nsScriptErrorBase::InitWithWindowID(const nsAString& message,
    247                                    const nsACString& sourceName,
    248                                    uint32_t lineNumber, uint32_t columnNumber,
    249                                    uint32_t flags, const nsACString& category,
    250                                    uint64_t aInnerWindowID,
    251                                    bool aFromChromeContext) {
    252  InitializationHelper(message, lineNumber, columnNumber, flags, category,
    253                       aInnerWindowID, aFromChromeContext);
    254  AssignSourceNameHelper(mSourceName, sourceName);
    255 
    256  if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
    257 
    258  return NS_OK;
    259 }
    260 
    261 NS_IMETHODIMP
    262 nsScriptErrorBase::InitWithSanitizedSource(
    263    const nsAString& message, const nsACString& sourceName, uint32_t lineNumber,
    264    uint32_t columnNumber, uint32_t flags, const nsACString& category,
    265    uint64_t aInnerWindowID, bool aFromChromeContext) {
    266  InitializationHelper(message, lineNumber, columnNumber, flags, category,
    267                       aInnerWindowID, aFromChromeContext);
    268  mSourceName = sourceName;
    269 
    270  if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
    271 
    272  return NS_OK;
    273 }
    274 
    275 NS_IMETHODIMP
    276 nsScriptErrorBase::InitWithSourceURI(const nsAString& message,
    277                                     nsIURI* sourceURI, uint32_t lineNumber,
    278                                     uint32_t columnNumber, uint32_t flags,
    279                                     const nsACString& category,
    280                                     uint64_t aInnerWindowID,
    281                                     bool aFromChromeContext) {
    282  InitializationHelper(message, lineNumber, columnNumber, flags, category,
    283                       aInnerWindowID, aFromChromeContext);
    284  AssignSourceNameHelper(sourceURI, mSourceName);
    285 
    286  if (aInnerWindowID && NS_IsMainThread()) InitializeOnMainThread();
    287 
    288  return NS_OK;
    289 }
    290 
    291 static nsresult ToStringHelper(const char* aSeverity, const nsString& aMessage,
    292                               const nsCString& aSourceName,
    293                               uint32_t aLineNumber, uint32_t aColumnNumber,
    294                               nsACString& /*UTF8*/ aResult) {
    295  static const char format0[] =
    296      "[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
    297  static const char format1[] = "[%s: \"%s\" {file: \"%s\" line: %d}]";
    298  static const char format2[] = "[%s: \"%s\"]";
    299 
    300  JS::UniqueChars temp;
    301  char* tempMessage = nullptr;
    302  char* tempSourceName = nullptr;
    303  char* tempSourceLine = nullptr;
    304 
    305  if (!aMessage.IsEmpty()) {
    306    tempMessage = ToNewUTF8String(aMessage);
    307  }
    308  if (!aSourceName.IsEmpty()) {
    309    // Use at most 512 characters from mSourceName.
    310    tempSourceName = ToNewCString(StringHead(aSourceName, 512));
    311  }
    312 
    313  if (tempSourceName && tempSourceLine) {
    314    temp = JS_smprintf(format0, aSeverity, tempMessage, tempSourceName,
    315                       aLineNumber, aColumnNumber, tempSourceLine);
    316  } else if (!aSourceName.IsEmpty()) {
    317    temp = JS_smprintf(format1, aSeverity, tempMessage, tempSourceName,
    318                       aLineNumber);
    319  } else {
    320    temp = JS_smprintf(format2, aSeverity, tempMessage);
    321  }
    322 
    323  if (tempMessage) free(tempMessage);
    324  if (tempSourceName) free(tempSourceName);
    325  if (tempSourceLine) free(tempSourceLine);
    326 
    327  if (!temp) return NS_ERROR_OUT_OF_MEMORY;
    328 
    329  aResult.Assign(temp.get());
    330  return NS_OK;
    331 }
    332 
    333 NS_IMETHODIMP
    334 nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult) {
    335  static const char error[] = "JavaScript Error";
    336  static const char warning[] = "JavaScript Warning";
    337 
    338  const char* severity =
    339      !(mFlags & nsIScriptError::warningFlag) ? error : warning;
    340 
    341  return ToStringHelper(severity, mMessage, mSourceName, mLineNumber,
    342                        mColumnNumber, aResult);
    343 }
    344 
    345 NS_IMETHODIMP
    346 nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID) {
    347  NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
    348                       "This can't be safely determined off the main thread, "
    349                       "returning an inaccurate value!");
    350 
    351  if (!mInitializedOnMainThread && NS_IsMainThread()) {
    352    InitializeOnMainThread();
    353  }
    354 
    355  *aOuterWindowID = mOuterWindowID;
    356  return NS_OK;
    357 }
    358 
    359 NS_IMETHODIMP
    360 nsScriptErrorBase::GetInnerWindowID(uint64_t* aInnerWindowID) {
    361  *aInnerWindowID = mInnerWindowID;
    362  return NS_OK;
    363 }
    364 
    365 NS_IMETHODIMP
    366 nsScriptErrorBase::GetTimeStamp(int64_t* aTimeStamp) {
    367  *aTimeStamp = mMicroSecondTimeStamp / 1000;
    368  return NS_OK;
    369 }
    370 
    371 NS_IMETHODIMP
    372 nsScriptErrorBase::GetMicroSecondTimeStamp(int64_t* aTimeStamp) {
    373  *aTimeStamp = mMicroSecondTimeStamp;
    374  return NS_OK;
    375 }
    376 
    377 NS_IMETHODIMP
    378 nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow) {
    379  NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
    380                       "This can't be safely determined off the main thread, "
    381                       "returning an inaccurate value!");
    382 
    383  if (!mInitializedOnMainThread && NS_IsMainThread()) {
    384    InitializeOnMainThread();
    385  }
    386 
    387  *aIsFromPrivateWindow = mIsFromPrivateWindow;
    388  return NS_OK;
    389 }
    390 
    391 NS_IMETHODIMP
    392 nsScriptErrorBase::GetIsFromChromeContext(bool* aIsFromChromeContext) {
    393  NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
    394                       "This can't be safely determined off the main thread, "
    395                       "returning an inaccurate value!");
    396  if (!mInitializedOnMainThread && NS_IsMainThread()) {
    397    InitializeOnMainThread();
    398  }
    399  *aIsFromChromeContext = mIsFromChromeContext;
    400  return NS_OK;
    401 }
    402 
    403 NS_IMETHODIMP
    404 nsScriptErrorBase::GetIsPromiseRejection(bool* aIsPromiseRejection) {
    405  *aIsPromiseRejection = mIsPromiseRejection;
    406  return NS_OK;
    407 }
    408 
    409 NS_IMETHODIMP
    410 nsScriptErrorBase::InitIsPromiseRejection(bool aIsPromiseRejection) {
    411  mIsPromiseRejection = aIsPromiseRejection;
    412  return NS_OK;
    413 }
    414 
    415 NS_IMETHODIMP
    416 nsScriptErrorBase::GetIsForwardedFromContentProcess(
    417    bool* aIsForwardedFromContentProcess) {
    418  *aIsForwardedFromContentProcess = mIsForwardedFromContentProcess;
    419  return NS_OK;
    420 }
    421 
    422 NS_IMETHODIMP
    423 nsScriptErrorBase::SetIsForwardedFromContentProcess(
    424    bool aIsForwardedFromContentProcess) {
    425  mIsForwardedFromContentProcess = aIsForwardedFromContentProcess;
    426  return NS_OK;
    427 }
    428 
    429 NS_IMETHODIMP
    430 nsScriptErrorBase::GetNotes(nsIArray** aNotes) {
    431  nsresult rv = NS_OK;
    432  nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
    433  NS_ENSURE_SUCCESS(rv, rv);
    434 
    435  uint32_t len = mNotes.Length();
    436  for (uint32_t i = 0; i < len; i++) array->AppendElement(mNotes[i]);
    437  array.forget(aNotes);
    438 
    439  return NS_OK;
    440 }
    441 
    442 /* static */
    443 bool nsScriptErrorBase::ComputeIsFromPrivateWindow(
    444    nsGlobalWindowInner* aWindow) {
    445  // Never mark exceptions from chrome windows as having come from private
    446  // windows, since we always want them to be reported.
    447  nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
    448  return aWindow->IsPrivateBrowsing() && !winPrincipal->IsSystemPrincipal();
    449 }
    450 
    451 /* static */
    452 bool nsScriptErrorBase::ComputeIsFromChromeContext(
    453    nsGlobalWindowInner* aWindow) {
    454  nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
    455  return winPrincipal->IsSystemPrincipal();
    456 }
    457 
    458 NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
    459 
    460 nsScriptErrorNote::nsScriptErrorNote()
    461    : mSourceId(0), mLineNumber(0), mColumnNumber(0) {}
    462 
    463 nsScriptErrorNote::~nsScriptErrorNote() = default;
    464 
    465 void nsScriptErrorNote::Init(const nsAString& message,
    466                             const nsACString& sourceName, uint32_t sourceId,
    467                             uint32_t lineNumber, uint32_t columnNumber) {
    468  mMessage.Assign(message);
    469  AssignSourceNameHelper(mSourceName, sourceName);
    470  mSourceId = sourceId;
    471  mLineNumber = lineNumber;
    472  mColumnNumber = columnNumber;
    473 }
    474 
    475 // nsIScriptErrorNote methods
    476 NS_IMETHODIMP
    477 nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
    478  aResult.Assign(mMessage);
    479  return NS_OK;
    480 }
    481 
    482 NS_IMETHODIMP
    483 nsScriptErrorNote::GetSourceName(nsACString& aResult) {
    484  aResult.Assign(mSourceName);
    485  return NS_OK;
    486 }
    487 
    488 NS_IMETHODIMP
    489 nsScriptErrorNote::GetSourceId(uint32_t* result) {
    490  *result = mSourceId;
    491  return NS_OK;
    492 }
    493 
    494 NS_IMETHODIMP
    495 nsScriptErrorNote::GetLineNumber(uint32_t* result) {
    496  *result = mLineNumber;
    497  return NS_OK;
    498 }
    499 
    500 NS_IMETHODIMP
    501 nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
    502  *result = mColumnNumber;
    503  return NS_OK;
    504 }
    505 
    506 NS_IMETHODIMP
    507 nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult) {
    508  return ToStringHelper("JavaScript Note", mMessage, mSourceName, mLineNumber,
    509                        mColumnNumber, aResult);
    510 }
    511 
    512 NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)