tor-browser

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

ConsoleUtils.cpp (4607B)


      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 #include "ConsoleUtils.h"
      8 
      9 #include "ConsoleCommon.h"
     10 #include "js/PropertyAndElement.h"  // JS_DefineProperty
     11 #include "mozilla/ClearOnShutdown.h"
     12 #include "mozilla/NullPrincipal.h"
     13 #include "mozilla/dom/ConsoleBinding.h"
     14 #include "mozilla/dom/ConsoleInstanceBinding.h"
     15 #include "mozilla/dom/RootedDictionary.h"
     16 #include "mozilla/dom/ScriptSettings.h"
     17 #include "nsContentUtils.h"
     18 #include "nsIConsoleAPIStorage.h"
     19 #include "nsIXPConnect.h"
     20 #include "nsServiceManagerUtils.h"
     21 
     22 namespace mozilla::dom {
     23 
     24 namespace {
     25 
     26 StaticRefPtr<ConsoleUtils> gConsoleUtilsService;
     27 
     28 }
     29 
     30 /* static */
     31 ConsoleUtils* ConsoleUtils::GetOrCreate() {
     32  if (!gConsoleUtilsService) {
     33    MOZ_ASSERT(NS_IsMainThread());
     34 
     35    gConsoleUtilsService = new ConsoleUtils();
     36    ClearOnShutdown(&gConsoleUtilsService);
     37  }
     38 
     39  return gConsoleUtilsService;
     40 }
     41 
     42 ConsoleUtils::ConsoleUtils() = default;
     43 ConsoleUtils::~ConsoleUtils() = default;
     44 
     45 /* static */
     46 void ConsoleUtils::ReportForServiceWorkerScope(const nsAString& aScope,
     47                                               const nsAString& aMessage,
     48                                               const nsACString& aFilename,
     49                                               uint32_t aLineNumber,
     50                                               uint32_t aColumnNumber,
     51                                               Level aLevel) {
     52  MOZ_ASSERT(NS_IsMainThread());
     53 
     54  RefPtr<ConsoleUtils> service = ConsoleUtils::GetOrCreate();
     55  if (NS_WARN_IF(!service)) {
     56    return;
     57  }
     58 
     59  service->ReportForServiceWorkerScopeInternal(
     60      aScope, aMessage, aFilename, aLineNumber, aColumnNumber, aLevel);
     61 }
     62 
     63 void ConsoleUtils::ReportForServiceWorkerScopeInternal(
     64    const nsAString& aScope, const nsAString& aMessage,
     65    const nsACString& aFilename, uint32_t aLineNumber, uint32_t aColumnNumber,
     66    Level aLevel) {
     67  MOZ_ASSERT(NS_IsMainThread());
     68 
     69  AutoJSAPI jsapi;
     70  jsapi.Init();
     71 
     72  JSContext* cx = jsapi.cx();
     73 
     74  ConsoleCommon::ClearException ce(cx);
     75  JS::Rooted<JSObject*> global(cx, GetOrCreateSandbox(cx));
     76  if (NS_WARN_IF(!global)) {
     77    return;
     78  }
     79 
     80  // The GetOrCreateSandbox call returns a proxy to the actual sandbox object.
     81  // We don't need a proxy here.
     82  global = js::UncheckedUnwrap(global);
     83 
     84  JSAutoRealm ar(cx, global);
     85 
     86  RootedDictionary<ConsoleEvent> event(cx);
     87 
     88  event.mID.Construct();
     89  event.mID.Value().SetAsString() = aScope;
     90 
     91  event.mInnerID.Construct();
     92  event.mInnerID.Value().SetAsString() = u"ServiceWorker"_ns;
     93 
     94  switch (aLevel) {
     95    case eLog:
     96      event.mLevel = u"log"_ns;
     97      break;
     98 
     99    case eWarning:
    100      event.mLevel = u"warn"_ns;
    101      break;
    102 
    103    case eError:
    104      event.mLevel = u"error"_ns;
    105      break;
    106  }
    107 
    108  event.mFilename = aFilename;
    109  event.mLineNumber = aLineNumber;
    110  event.mColumnNumber = aColumnNumber;
    111  event.mTimeStamp = JS_Now() / PR_USEC_PER_MSEC;
    112  event.mMicroSecondTimeStamp = JS_Now();
    113 
    114  JS::Rooted<JS::Value> messageValue(cx);
    115  if (!dom::ToJSValue(cx, aMessage, &messageValue)) {
    116    return;
    117  }
    118 
    119  event.mArguments.Construct();
    120  if (!event.mArguments.Value().AppendElement(messageValue, fallible)) {
    121    return;
    122  }
    123 
    124  nsCOMPtr<nsIConsoleAPIStorage> storage =
    125      do_GetService("@mozilla.org/consoleAPI-storage;1");
    126 
    127  if (NS_WARN_IF(!storage)) {
    128    return;
    129  }
    130 
    131  JS::Rooted<JS::Value> eventValue(cx);
    132  if (!ToJSValue(cx, event, &eventValue)) {
    133    return;
    134  }
    135 
    136  // This is a legacy property.
    137  JS::Rooted<JSObject*> eventObj(cx, &eventValue.toObject());
    138  if (NS_WARN_IF(!JS_DefineProperty(cx, eventObj, "wrappedJSObject", eventObj,
    139                                    JSPROP_ENUMERATE))) {
    140    return;
    141  }
    142 
    143  storage->RecordEvent(u"ServiceWorker"_ns, eventValue);
    144 }
    145 
    146 JSObject* ConsoleUtils::GetOrCreateSandbox(JSContext* aCx) {
    147  AssertIsOnMainThread();
    148 
    149  if (!mSandbox) {
    150    nsIXPConnect* xpc = nsContentUtils::XPConnect();
    151    MOZ_ASSERT(xpc, "This should never be null!");
    152 
    153    RefPtr<NullPrincipal> nullPrincipal =
    154        NullPrincipal::CreateWithoutOriginAttributes();
    155 
    156    JS::Rooted<JSObject*> sandbox(aCx);
    157    nsresult rv = xpc->CreateSandbox(aCx, nullPrincipal, sandbox.address());
    158    if (NS_WARN_IF(NS_FAILED(rv))) {
    159      return nullptr;
    160    }
    161 
    162    mSandbox = new JSObjectHolder(aCx, sandbox);
    163  }
    164 
    165  return mSandbox->GetJSObject();
    166 }
    167 
    168 }  // namespace mozilla::dom