Coverage Report

Created: 2018-09-25 14:53

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