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