nsScriptError.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * nsIScriptError implementation.
  7. */
  8. #include "nsScriptError.h"
  9. #include "jsprf.h"
  10. #include "MainThreadUtils.h"
  11. #include "mozilla/Assertions.h"
  12. #include "nsGlobalWindow.h"
  13. #include "nsNetUtil.h"
  14. #include "nsPIDOMWindow.h"
  15. #include "nsILoadContext.h"
  16. #include "nsIDocShell.h"
  17. #include "nsIMutableArray.h"
  18. #include "nsIScriptError.h"
  19. #include "nsISensitiveInfoHiddenURI.h"
  20. static_assert(nsIScriptError::errorFlag == JSREPORT_ERROR &&
  21. nsIScriptError::warningFlag == JSREPORT_WARNING &&
  22. nsIScriptError::exceptionFlag == JSREPORT_EXCEPTION &&
  23. nsIScriptError::strictFlag == JSREPORT_STRICT &&
  24. nsIScriptError::infoFlag == JSREPORT_USER_1,
  25. "flags should be consistent");
  26. nsScriptErrorBase::nsScriptErrorBase()
  27. : mMessage(),
  28. mMessageName(),
  29. mSourceName(),
  30. mLineNumber(0),
  31. mSourceLine(),
  32. mColumnNumber(0),
  33. mFlags(0),
  34. mCategory(),
  35. mOuterWindowID(0),
  36. mInnerWindowID(0),
  37. mTimeStamp(0),
  38. mInitializedOnMainThread(false),
  39. mIsFromPrivateWindow(false)
  40. {
  41. }
  42. nsScriptErrorBase::~nsScriptErrorBase() {}
  43. void
  44. nsScriptErrorBase::AddNote(nsIScriptErrorNote* note)
  45. {
  46. mNotes.AppendObject(note);
  47. }
  48. void
  49. nsScriptErrorBase::InitializeOnMainThread()
  50. {
  51. MOZ_ASSERT(NS_IsMainThread());
  52. MOZ_ASSERT(!mInitializedOnMainThread);
  53. if (mInnerWindowID) {
  54. nsGlobalWindow* window =
  55. nsGlobalWindow::GetInnerWindowWithId(mInnerWindowID);
  56. if (window) {
  57. nsPIDOMWindowOuter* outer = window->GetOuterWindow();
  58. if (outer)
  59. mOuterWindowID = outer->WindowID();
  60. nsIDocShell* docShell = window->GetDocShell();
  61. nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
  62. if (loadContext) {
  63. // Never mark exceptions from chrome windows as having come from
  64. // private windows, since we always want them to be reported.
  65. nsIPrincipal* winPrincipal = window->GetPrincipal();
  66. mIsFromPrivateWindow = loadContext->UsePrivateBrowsing() &&
  67. !nsContentUtils::IsSystemPrincipal(winPrincipal);
  68. }
  69. }
  70. }
  71. mInitializedOnMainThread = true;
  72. }
  73. // nsIConsoleMessage methods
  74. NS_IMETHODIMP
  75. nsScriptErrorBase::GetMessageMoz(char16_t** result) {
  76. nsresult rv;
  77. nsAutoCString message;
  78. rv = ToString(message);
  79. if (NS_FAILED(rv))
  80. return rv;
  81. *result = UTF8ToNewUnicode(message);
  82. if (!*result)
  83. return NS_ERROR_OUT_OF_MEMORY;
  84. return NS_OK;
  85. }
  86. NS_IMETHODIMP
  87. nsScriptErrorBase::GetLogLevel(uint32_t* aLogLevel)
  88. {
  89. if (mFlags & (uint32_t)nsIScriptError::infoFlag) {
  90. *aLogLevel = nsIConsoleMessage::info;
  91. } else if (mFlags & (uint32_t)nsIScriptError::warningFlag) {
  92. *aLogLevel = nsIConsoleMessage::warn;
  93. } else {
  94. *aLogLevel = nsIConsoleMessage::error;
  95. }
  96. return NS_OK;
  97. }
  98. // nsIScriptError methods
  99. NS_IMETHODIMP
  100. nsScriptErrorBase::GetErrorMessage(nsAString& aResult) {
  101. aResult.Assign(mMessage);
  102. return NS_OK;
  103. }
  104. NS_IMETHODIMP
  105. nsScriptErrorBase::GetSourceName(nsAString& aResult) {
  106. aResult.Assign(mSourceName);
  107. return NS_OK;
  108. }
  109. NS_IMETHODIMP
  110. nsScriptErrorBase::GetSourceLine(nsAString& aResult) {
  111. aResult.Assign(mSourceLine);
  112. return NS_OK;
  113. }
  114. NS_IMETHODIMP
  115. nsScriptErrorBase::GetLineNumber(uint32_t* result) {
  116. *result = mLineNumber;
  117. return NS_OK;
  118. }
  119. NS_IMETHODIMP
  120. nsScriptErrorBase::GetColumnNumber(uint32_t* result) {
  121. *result = mColumnNumber;
  122. return NS_OK;
  123. }
  124. NS_IMETHODIMP
  125. nsScriptErrorBase::GetFlags(uint32_t* result) {
  126. *result = mFlags;
  127. return NS_OK;
  128. }
  129. NS_IMETHODIMP
  130. nsScriptErrorBase::GetCategory(char** result) {
  131. *result = ToNewCString(mCategory);
  132. return NS_OK;
  133. }
  134. NS_IMETHODIMP
  135. nsScriptErrorBase::GetStack(JS::MutableHandleValue aStack) {
  136. aStack.setUndefined();
  137. return NS_OK;
  138. }
  139. NS_IMETHODIMP
  140. nsScriptErrorBase::SetStack(JS::HandleValue aStack) {
  141. return NS_OK;
  142. }
  143. NS_IMETHODIMP
  144. nsScriptErrorBase::GetErrorMessageName(nsAString& aErrorMessageName) {
  145. aErrorMessageName = mMessageName;
  146. return NS_OK;
  147. }
  148. NS_IMETHODIMP
  149. nsScriptErrorBase::SetErrorMessageName(const nsAString& aErrorMessageName) {
  150. mMessageName = aErrorMessageName;
  151. return NS_OK;
  152. }
  153. NS_IMETHODIMP
  154. nsScriptErrorBase::Init(const nsAString& message,
  155. const nsAString& sourceName,
  156. const nsAString& sourceLine,
  157. uint32_t lineNumber,
  158. uint32_t columnNumber,
  159. uint32_t flags,
  160. const char* category)
  161. {
  162. return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
  163. columnNumber, flags,
  164. category ? nsDependentCString(category)
  165. : EmptyCString(),
  166. 0);
  167. }
  168. static void
  169. AssignSourceNameHelper(nsString& aSourceNameDest, const nsAString& aSourceNameSrc)
  170. {
  171. if (aSourceNameSrc.IsEmpty())
  172. return;
  173. aSourceNameDest.Assign(aSourceNameSrc);
  174. nsCOMPtr<nsIURI> uri;
  175. nsAutoCString pass;
  176. if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
  177. NS_SUCCEEDED(uri->GetPassword(pass)) &&
  178. !pass.IsEmpty())
  179. {
  180. nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri);
  181. nsAutoCString loc;
  182. if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
  183. aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
  184. }
  185. }
  186. NS_IMETHODIMP
  187. nsScriptErrorBase::InitWithWindowID(const nsAString& message,
  188. const nsAString& sourceName,
  189. const nsAString& sourceLine,
  190. uint32_t lineNumber,
  191. uint32_t columnNumber,
  192. uint32_t flags,
  193. const nsACString& category,
  194. uint64_t aInnerWindowID)
  195. {
  196. mMessage.Assign(message);
  197. AssignSourceNameHelper(mSourceName, sourceName);
  198. mLineNumber = lineNumber;
  199. mSourceLine.Assign(sourceLine);
  200. mColumnNumber = columnNumber;
  201. mFlags = flags;
  202. mCategory = category;
  203. mTimeStamp = JS_Now() / 1000;
  204. mInnerWindowID = aInnerWindowID;
  205. if (aInnerWindowID && NS_IsMainThread()) {
  206. InitializeOnMainThread();
  207. }
  208. return NS_OK;
  209. }
  210. static nsresult
  211. ToStringHelper(const char* aSeverity, const nsString& aMessage,
  212. const nsString& aSourceName, const nsString* aSourceLine,
  213. uint32_t aLineNumber, uint32_t aColumnNumber,
  214. nsACString& /*UTF8*/ aResult)
  215. {
  216. static const char format0[] =
  217. "[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
  218. static const char format1[] =
  219. "[%s: \"%s\" {file: \"%s\" line: %d}]";
  220. static const char format2[] =
  221. "[%s: \"%s\"]";
  222. char* temp;
  223. char* tempMessage = nullptr;
  224. char* tempSourceName = nullptr;
  225. char* tempSourceLine = nullptr;
  226. if (!aMessage.IsEmpty())
  227. tempMessage = ToNewUTF8String(aMessage);
  228. if (!aSourceName.IsEmpty())
  229. // Use at most 512 characters from mSourceName.
  230. tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512));
  231. if (aSourceLine && !aSourceLine->IsEmpty())
  232. // Use at most 512 characters from mSourceLine.
  233. tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512));
  234. if (nullptr != tempSourceName && nullptr != tempSourceLine) {
  235. temp = JS_smprintf(format0,
  236. aSeverity,
  237. tempMessage,
  238. tempSourceName,
  239. aLineNumber,
  240. aColumnNumber,
  241. tempSourceLine);
  242. } else if (!aSourceName.IsEmpty()) {
  243. temp = JS_smprintf(format1,
  244. aSeverity,
  245. tempMessage,
  246. tempSourceName,
  247. aLineNumber);
  248. } else {
  249. temp = JS_smprintf(format2,
  250. aSeverity,
  251. tempMessage);
  252. }
  253. if (nullptr != tempMessage)
  254. free(tempMessage);
  255. if (nullptr != tempSourceName)
  256. free(tempSourceName);
  257. if (nullptr != tempSourceLine)
  258. free(tempSourceLine);
  259. if (!temp)
  260. return NS_ERROR_OUT_OF_MEMORY;
  261. aResult.Assign(temp);
  262. JS_smprintf_free(temp);
  263. return NS_OK;
  264. }
  265. NS_IMETHODIMP
  266. nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
  267. {
  268. static const char error[] = "JavaScript Error";
  269. static const char warning[] = "JavaScript Warning";
  270. const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning;
  271. return ToStringHelper(severity, mMessage, mSourceName, &mSourceLine,
  272. mLineNumber, mColumnNumber, aResult);
  273. }
  274. NS_IMETHODIMP
  275. nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID)
  276. {
  277. NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
  278. "This can't be safely determined off the main thread, "
  279. "returning an inaccurate value!");
  280. if (!mInitializedOnMainThread && NS_IsMainThread()) {
  281. InitializeOnMainThread();
  282. }
  283. *aOuterWindowID = mOuterWindowID;
  284. return NS_OK;
  285. }
  286. NS_IMETHODIMP
  287. nsScriptErrorBase::GetInnerWindowID(uint64_t* aInnerWindowID)
  288. {
  289. *aInnerWindowID = mInnerWindowID;
  290. return NS_OK;
  291. }
  292. NS_IMETHODIMP
  293. nsScriptErrorBase::GetTimeStamp(int64_t* aTimeStamp)
  294. {
  295. *aTimeStamp = mTimeStamp;
  296. return NS_OK;
  297. }
  298. NS_IMETHODIMP
  299. nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
  300. {
  301. NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
  302. "This can't be safely determined off the main thread, "
  303. "returning an inaccurate value!");
  304. if (!mInitializedOnMainThread && NS_IsMainThread()) {
  305. InitializeOnMainThread();
  306. }
  307. *aIsFromPrivateWindow = mIsFromPrivateWindow;
  308. return NS_OK;
  309. }
  310. NS_IMETHODIMP
  311. nsScriptErrorBase::GetNotes(nsIArray** aNotes)
  312. {
  313. nsresult rv = NS_OK;
  314. nsCOMPtr<nsIMutableArray> array =
  315. do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
  316. NS_ENSURE_SUCCESS(rv, rv);
  317. uint32_t len = mNotes.Length();
  318. for (uint32_t i = 0; i < len; i++)
  319. array->AppendElement(mNotes[i], false);
  320. array.forget(aNotes);
  321. return NS_OK;
  322. }
  323. NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
  324. nsScriptErrorNote::nsScriptErrorNote()
  325. : mMessage(),
  326. mSourceName(),
  327. mLineNumber(0),
  328. mColumnNumber(0)
  329. {
  330. }
  331. nsScriptErrorNote::~nsScriptErrorNote() {}
  332. void
  333. nsScriptErrorNote::Init(const nsAString& message,
  334. const nsAString& sourceName,
  335. uint32_t lineNumber,
  336. uint32_t columnNumber)
  337. {
  338. mMessage.Assign(message);
  339. AssignSourceNameHelper(mSourceName, sourceName);
  340. mLineNumber = lineNumber;
  341. mColumnNumber = columnNumber;
  342. }
  343. // nsIScriptErrorNote methods
  344. NS_IMETHODIMP
  345. nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
  346. aResult.Assign(mMessage);
  347. return NS_OK;
  348. }
  349. NS_IMETHODIMP
  350. nsScriptErrorNote::GetSourceName(nsAString& aResult) {
  351. aResult.Assign(mSourceName);
  352. return NS_OK;
  353. }
  354. NS_IMETHODIMP
  355. nsScriptErrorNote::GetLineNumber(uint32_t* result) {
  356. *result = mLineNumber;
  357. return NS_OK;
  358. }
  359. NS_IMETHODIMP
  360. nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
  361. *result = mColumnNumber;
  362. return NS_OK;
  363. }
  364. NS_IMETHODIMP
  365. nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult)
  366. {
  367. return ToStringHelper("JavaScript Note", mMessage, mSourceName, nullptr,
  368. mLineNumber, mColumnNumber, aResult);
  369. }
  370. NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)