Bug 1429174 - Introducing ConsoleUtils for logging messages to console, r=bkelly

This commit is contained in:
Andrea Marchesini 2018-01-10 22:06:37 +01:00
parent fff3bf05d6
commit c3e1816c7f
6 changed files with 259 additions and 30 deletions

View File

@ -7,6 +7,7 @@
#include "mozilla/dom/Console.h"
#include "mozilla/dom/ConsoleInstance.h"
#include "mozilla/dom/ConsoleBinding.h"
#include "ConsoleCommon.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/Exceptions.h"
@ -295,24 +296,6 @@ private:
}
};
// This class is used to clear any exception at the end of this method.
class ClearException
{
public:
explicit ClearException(JSContext* aCx)
: mCx(aCx)
{
}
~ClearException()
{
JS_ClearPendingException(mCx);
}
private:
JSContext* mCx;
};
class ConsoleRunnable : public WorkerProxyToMainThreadRunnable
, public StructuredCloneHolderBase
{
@ -536,7 +519,7 @@ private:
mWorkerPrivate->AssertIsOnWorkerThread();
mCallData->AssertIsOnOwningThread();
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
JS::Rooted<JSObject*> arguments(aCx,
JS_NewArrayObject(aCx, mCallData->mCopiedArguments.Length()));
@ -623,7 +606,7 @@ private:
{
AssertIsOnMainThread();
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
JS::Rooted<JS::Value> argumentsValue(aCx);
if (!Read(aCx, &argumentsValue)) {
@ -681,7 +664,7 @@ private:
bool
PreDispatch(JSContext* aCx) override
{
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
JS::Rooted<JSObject*> arguments(aCx,
JS_NewArrayObject(aCx, mArguments.Length()));
@ -713,7 +696,7 @@ private:
{
AssertIsOnMainThread();
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
// Now we could have the correct window (if we are not window-less).
mClonedData.mParent = aInnerWindow;
@ -1014,7 +997,7 @@ Console::StringMethodInternal(JSContext* aCx, const nsAString& aLabel,
MethodName aMethodName,
const nsAString& aMethodString)
{
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(aCx, &data);
@ -1037,7 +1020,7 @@ Console::TimeStamp(const GlobalObject& aGlobal,
{
JSContext* cx = aGlobal.Context();
ClearException ce(cx);
ConsoleCommon::ClearException ce(cx);
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(cx, &data);
@ -1113,7 +1096,7 @@ Console::ProfileMethodInternal(JSContext* aCx, MethodName aMethodName,
return;
}
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
RootedDictionary<ConsoleProfileEvent> event(aCx);
event.mAction = aAction;
@ -1264,7 +1247,7 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
RefPtr<ConsoleCallData> callData(new ConsoleCallData());
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
if (NS_WARN_IF(!callData->Initialize(aCx, aMethodName, aMethodString,
aData, this))) {
@ -1530,7 +1513,7 @@ Console::PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
frame = *aData->mTopStackFrame;
}
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
RootedDictionary<ConsoleEvent> event(aCx);
event.mAddonId = aData->mAddonId;
@ -2188,7 +2171,7 @@ Console::IncreaseCounter(JSContext* aCx, const Sequence<JS::Value>& aArguments,
{
AssertIsOnOwningThread();
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
MOZ_ASSERT(!aArguments.IsEmpty());
@ -2224,7 +2207,7 @@ JS::Value
Console::CreateCounterValue(JSContext* aCx, const nsAString& aCountLabel,
uint32_t aCountValue) const
{
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
if (aCountValue == MAX_PAGE_COUNTERS) {
RootedDictionary<ConsoleCounterError> error(aCx);

View File

@ -0,0 +1,38 @@
/* -*- 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/. */
#ifndef mozilla_dom_ConsoleCommon_h
#define mozilla_dom_ConsoleCommon_h
#include "nsString.h"
namespace mozilla {
namespace dom {
namespace ConsoleCommon {
// This class is used to clear any exception at the end of this method.
class MOZ_RAII ClearException
{
public:
explicit ClearException(JSContext* aCx)
: mCx(aCx)
{
}
~ClearException()
{
JS_ClearPendingException(mCx);
}
private:
JSContext* mCx;
};
} // namespace ConsoleCommon
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_ConsoleCommon_h */

View File

@ -6,6 +6,7 @@
#include "mozilla/dom/ConsoleInstance.h"
#include "mozilla/dom/ConsoleBinding.h"
#include "ConsoleCommon.h"
namespace mozilla {
namespace dom {
@ -132,7 +133,7 @@ ConsoleInstance::TimeEnd(JSContext* aCx, const nsAString& aLabel)
void
ConsoleInstance::TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData)
{
ClearException ce(aCx);
ConsoleCommon::ClearException ce(aCx);
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(aCx, &data);

View File

@ -0,0 +1,152 @@
/* -*- 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)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<ConsoleUtils> service = ConsoleUtils::GetOrCreate();
if (NS_WARN_IF(!service)) {
return;
}
service->ReportForServiceWorkerScopeInternal(aScope, aMessage, aFilename,
aLineNumber, aColumnNumber);
}
void
ConsoleUtils::ReportForServiceWorkerScopeInternal(const nsAString& aScope,
const nsAString& aMessage,
const nsAString& aFilename,
uint32_t aLineNumber,
uint32_t aColumnNumber)
{
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);
JSAutoCompartment ac(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");
event.mLevel = NS_LITERAL_STRING("log");
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::Create();
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

View File

@ -0,0 +1,53 @@
/* -*- 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/. */
#ifndef mozilla_dom_ConsoleUtils_h
#define mozilla_dom_ConsoleUtils_h
#include "mozilla/JSObjectHolder.h"
#include "nsISupportsImpl.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
class ConsoleUtils final
{
public:
NS_INLINE_DECL_REFCOUNTING(ConsoleUtils)
// Main-thread only, reports a console message from a ServiceWorker.
static void
ReportForServiceWorkerScope(const nsAString& aScope,
const nsAString& aMessage,
const nsAString& aFilename,
uint32_t aLineNumber,
uint32_t aColumnNumber);
private:
ConsoleUtils();
~ConsoleUtils();
static ConsoleUtils*
GetOrCreate();
JSObject*
GetOrCreateSandbox(JSContext* aCx);
void
ReportForServiceWorkerScopeInternal(const nsAString& aScope,
const nsAString& aMessage,
const nsAString& aFilename,
uint32_t aLineNumber,
uint32_t aColumnNumber);
RefPtr<JSObjectHolder> mSandbox;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_ConsoleUtils_h */

View File

@ -24,12 +24,14 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.dom += [
'Console.h',
'ConsoleInstance.h',
'ConsoleUtils.h',
]
UNIFIED_SOURCES += [
'Console.cpp',
'ConsoleInstance.cpp',
'ConsoleReportCollector.cpp',
'ConsoleUtils.cpp',
]
EXTRA_COMPONENTS += [