ChromeWorker.cpp (3116B)
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 "ChromeWorker.h" 8 9 #include "WorkerPrivate.h" 10 #include "mozilla/AppShutdown.h" 11 #include "mozilla/dom/BindingUtils.h" 12 #include "mozilla/dom/WorkerBinding.h" 13 #include "nsContentUtils.h" 14 #include "nsIXPConnect.h" 15 16 namespace mozilla::dom { 17 18 /* static */ 19 already_AddRefed<ChromeWorker> ChromeWorker::Constructor( 20 const GlobalObject& aGlobal, const nsAString& aScriptURL, 21 const WorkerOptions& aOptions, ErrorResult& aRv) { 22 // Dump the JS stack if somebody's creating a ChromeWorker after shutdown has 23 // begun. See bug 1813353. 24 if (xpc::IsInAutomation() && 25 AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown)) { 26 NS_WARNING("ChromeWorker construction during shutdown"); 27 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect(); 28 (void)xpc->DebugDumpJSStack(true, true, false); 29 } 30 31 JSContext* cx = aGlobal.Context(); 32 33 RefPtr<WorkerPrivate> workerPrivate = WorkerPrivate::Constructor( 34 cx, aScriptURL, true /* aIsChromeWorker */, WorkerKindDedicated, 35 RequestCredentials::Omit, aOptions.mType, aOptions.mName, VoidCString(), 36 nullptr /*aLoadInfo */, aRv); 37 if (NS_WARN_IF(aRv.Failed())) { 38 return nullptr; 39 } 40 41 nsCOMPtr<nsIGlobalObject> globalObject = 42 do_QueryInterface(aGlobal.GetAsSupports()); 43 44 RefPtr<ChromeWorker> worker = 45 new ChromeWorker(globalObject, workerPrivate.forget()); 46 return worker.forget(); 47 } 48 49 /* static */ 50 bool ChromeWorker::WorkerAvailable(JSContext* aCx, JSObject* /* unused */) { 51 // Chrome is always allowed to use workers, and content is never 52 // allowed to use ChromeWorker, so all we have to check is the 53 // caller. However, chrome workers apparently might not have a 54 // system principal, so we have to check for them manually. 55 if (NS_IsMainThread()) { 56 return nsContentUtils::IsSystemCaller(aCx); 57 } 58 59 return GetWorkerPrivateFromContext(aCx)->IsChromeWorker(); 60 } 61 62 ChromeWorker::ChromeWorker(nsIGlobalObject* aGlobalObject, 63 already_AddRefed<WorkerPrivate> aWorkerPrivate) 64 : Worker(aGlobalObject, std::move(aWorkerPrivate)) {} 65 66 ChromeWorker::~ChromeWorker() = default; 67 68 JSObject* ChromeWorker::WrapObject(JSContext* aCx, 69 JS::Handle<JSObject*> aGivenProto) { 70 JS::Rooted<JSObject*> wrapper( 71 aCx, ChromeWorker_Binding::Wrap(aCx, this, aGivenProto)); 72 if (wrapper) { 73 // Most DOM objects don't assume they have a reflector. If they don't have 74 // one and need one, they create it. But in workers code, we assume that the 75 // reflector is always present. In order to guarantee that it's always 76 // present, we have to preserve it. Otherwise the GC will happily collect it 77 // as needed. 78 MOZ_ALWAYS_TRUE(TryPreserveWrapper(wrapper)); 79 } 80 81 return wrapper; 82 } 83 84 } // namespace mozilla::dom