gecko-dev/dom/console/ConsoleUtils.cpp

169 строки
4.5 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ConsoleUtils.h"
#include "ConsoleCommon.h"
#include "mozilla/ClearOnShutdown.h"
#include "NullPrincipal.h"
namespace mozilla {
namespace dom {
namespace {
StaticRefPtr<ConsoleUtils> gConsoleUtilsService;
}
/* static */ ConsoleUtils*
ConsoleUtils::GetOrCreate()
{
if (!gConsoleUtilsService) {
MOZ_ASSERT(NS_IsMainThread());
gConsoleUtilsService = new ConsoleUtils();
ClearOnShutdown(&gConsoleUtilsService);
}
return gConsoleUtilsService;
}
ConsoleUtils::ConsoleUtils() = default;
ConsoleUtils::~ConsoleUtils() = default;
/* static */ void
ConsoleUtils::ReportForServiceWorkerScope(const nsAString& aScope,
const nsAString& aMessage,
const nsAString& aFilename,
uint32_t aLineNumber,
uint32_t aColumnNumber,
Level aLevel)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<ConsoleUtils> service = ConsoleUtils::GetOrCreate();
if (NS_WARN_IF(!service)) {
return;
}
service->ReportForServiceWorkerScopeInternal(aScope, aMessage, aFilename,
aLineNumber, aColumnNumber,
aLevel);
}
void
ConsoleUtils::ReportForServiceWorkerScopeInternal(const nsAString& aScope,
const nsAString& aMessage,
const nsAString& aFilename,
uint32_t aLineNumber,
uint32_t aColumnNumber,
Level aLevel)
{
MOZ_ASSERT(NS_IsMainThread());
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
ConsoleCommon::ClearException ce(cx);
JS::Rooted<JSObject*> global(cx, GetOrCreateSandbox(cx));
if (NS_WARN_IF(!global)) {
return;
}
// The GetOrCreateSandbox call returns a proxy to the actual sandbox object.
// We don't need a proxy here.
global = js::UncheckedUnwrap(global);
JSAutoRealm ar(cx, global);
RootedDictionary<ConsoleEvent> event(cx);
event.mID.Construct();
event.mID.Value().SetAsString() = aScope;
event.mInnerID.Construct();
event.mInnerID.Value().SetAsString() = NS_LITERAL_STRING("ServiceWorker");
switch (aLevel) {
case eLog:
event.mLevel = NS_LITERAL_STRING("log");
break;
case eWarning:
event.mLevel = NS_LITERAL_STRING("warn");
break;
case eError:
event.mLevel = NS_LITERAL_STRING("error");
break;
}
event.mFilename = aFilename;
event.mLineNumber = aLineNumber;
event.mColumnNumber = aColumnNumber;
event.mTimeStamp = JS_Now() / PR_USEC_PER_MSEC;
JS::Rooted<JS::Value> messageValue(cx);
if (!dom::ToJSValue(cx, aMessage, &messageValue)) {
return;
}
event.mArguments.Construct();
if (!event.mArguments.Value().AppendElement(messageValue, fallible)) {
return;
}
nsCOMPtr<nsIConsoleAPIStorage> storage =
do_GetService("@mozilla.org/consoleAPI-storage;1");
if (NS_WARN_IF(!storage)) {
return;
}
JS::Rooted<JS::Value> eventValue(cx);
if (!ToJSValue(cx, event, &eventValue)) {
return;
}
// This is a legacy property.
JS::Rooted<JSObject*> eventObj(cx, &eventValue.toObject());
if (NS_WARN_IF(!JS_DefineProperty(cx, eventObj, "wrappedJSObject", eventObj,
JSPROP_ENUMERATE))) {
return;
}
storage->RecordEvent(NS_LITERAL_STRING("ServiceWorker"), aScope, eventValue);
}
JSObject*
ConsoleUtils::GetOrCreateSandbox(JSContext* aCx)
{
AssertIsOnMainThread();
if (!mSandbox) {
nsIXPConnect* xpc = nsContentUtils::XPConnect();
MOZ_ASSERT(xpc, "This should never be null!");
RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
JS::Rooted<JSObject*> sandbox(aCx);
nsresult rv = xpc->CreateSandbox(aCx, nullPrincipal, sandbox.address());
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
mSandbox = new JSObjectHolder(aCx, sandbox);
}
return mSandbox->GetJSObject();
}
} // namespace dom
} // namespace mozilla