WorkletImpl.cpp (4895B)
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 https://mozilla.org/MPL/2.0/. */ 6 7 #include "WorkletImpl.h" 8 9 #include "Worklet.h" 10 #include "WorkletThread.h" 11 #include "mozilla/BasePrincipal.h" 12 #include "mozilla/NullPrincipal.h" 13 #include "mozilla/dom/DocGroup.h" 14 #include "mozilla/dom/Document.h" 15 #include "mozilla/dom/RegisterWorkletBindings.h" 16 #include "mozilla/dom/ScriptSettings.h" 17 #include "mozilla/dom/WorkletBinding.h" 18 #include "mozilla/dom/WorkletGlobalScope.h" 19 #include "mozilla/dom/worklet/WorkletModuleLoader.h" 20 #include "nsGlobalWindowInner.h" 21 22 using mozilla::dom::loader::WorkletModuleLoader; 23 using mozilla::dom::loader::WorkletScriptLoader; 24 25 namespace mozilla { 26 // --------------------------------------------------------------------------- 27 // WorkletLoadInfo 28 29 WorkletLoadInfo::WorkletLoadInfo(nsPIDOMWindowInner* aWindow) 30 : mInnerWindowID(aWindow->WindowID()) { 31 MOZ_ASSERT(NS_IsMainThread()); 32 nsPIDOMWindowOuter* outerWindow = aWindow->GetOuterWindow(); 33 if (outerWindow) { 34 mOuterWindowID = outerWindow->WindowID(); 35 } else { 36 mOuterWindowID = 0; 37 } 38 } 39 40 // --------------------------------------------------------------------------- 41 // WorkletImpl 42 43 WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal) 44 : mPrincipal(NullPrincipal::CreateWithInheritedAttributes(aPrincipal)), 45 mWorkletLoadInfo(aWindow), 46 mTerminated(false), 47 mFinishedOnExecutionThread(false), 48 mIsPrivateBrowsing(false), 49 mTrials(OriginTrials::FromWindow(nsGlobalWindowInner::Cast(aWindow))) { 50 (void)NS_WARN_IF( 51 NS_FAILED(ipc::PrincipalToPrincipalInfo(mPrincipal, &mPrincipalInfo))); 52 53 if (aWindow->GetDocGroup()) { 54 mAgentClusterId.emplace(aWindow->GetDocGroup()->AgentClusterId()); 55 } 56 57 mSharedMemoryAllowed = 58 nsGlobalWindowInner::Cast(aWindow)->IsSharedMemoryAllowed(); 59 60 mShouldResistFingerprinting = aWindow->AsGlobal()->ShouldResistFingerprinting( 61 RFPTarget::IsAlwaysEnabledForPrecompute); 62 63 RefPtr<dom::Document> doc = nsGlobalWindowInner::Cast(aWindow)->GetDocument(); 64 if (doc) { 65 mIsPrivateBrowsing = doc->IsInPrivateBrowsing(); 66 mOverriddenFingerprintingSettings = 67 doc->GetOverriddenFingerprintingSettings(); 68 } 69 } 70 71 WorkletImpl::~WorkletImpl() { MOZ_ASSERT(!mGlobalScope); } 72 73 JSObject* WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, 74 JS::Handle<JSObject*> aGivenProto) { 75 MOZ_ASSERT(NS_IsMainThread()); 76 return dom::Worklet_Binding::Wrap(aCx, aWorklet, aGivenProto); 77 } 78 79 dom::WorkletGlobalScope* WorkletImpl::GetGlobalScope() { 80 dom::WorkletThread::AssertIsOnWorkletThread(); 81 82 if (mGlobalScope) { 83 return mGlobalScope; 84 } 85 if (mFinishedOnExecutionThread) { 86 return nullptr; 87 } 88 89 dom::AutoJSAPI jsapi; 90 jsapi.Init(); 91 JSContext* cx = jsapi.cx(); 92 93 mGlobalScope = ConstructGlobalScope(cx); 94 95 JS::Rooted<JSObject*> global(cx); 96 NS_ENSURE_TRUE(mGlobalScope->WrapGlobalObject(cx, &global), nullptr); 97 98 JSAutoRealm ar(cx, global); 99 100 // Init Web IDL bindings 101 if (!dom::RegisterWorkletBindings(cx, global)) { 102 return nullptr; 103 } 104 105 JS_FireOnNewGlobalObject(cx, global); 106 107 MOZ_ASSERT(!mGlobalScope->GetModuleLoader(cx)); 108 109 RefPtr<WorkletScriptLoader> scriptLoader = new WorkletScriptLoader(); 110 RefPtr<WorkletModuleLoader> moduleLoader = 111 new WorkletModuleLoader(scriptLoader, mGlobalScope); 112 mGlobalScope->InitModuleLoader(moduleLoader); 113 114 return mGlobalScope; 115 } 116 117 void WorkletImpl::NotifyWorkletFinished() { 118 MOZ_ASSERT(NS_IsMainThread()); 119 120 if (mTerminated) { 121 return; 122 } 123 124 // Release global scope on its thread. 125 SendControlMessage( 126 NS_NewRunnableFunction("WorkletImpl::NotifyWorkletFinished", 127 [self = RefPtr<WorkletImpl>(this)]() { 128 self->mFinishedOnExecutionThread = true; 129 self->mGlobalScope = nullptr; 130 })); 131 132 mTerminated = true; 133 if (mWorkletThread) { 134 mWorkletThread->Terminate(); 135 mWorkletThread = nullptr; 136 } 137 } 138 139 nsresult WorkletImpl::SendControlMessage( 140 already_AddRefed<nsIRunnable> aRunnable) { 141 MOZ_ASSERT(NS_IsMainThread()); 142 RefPtr<nsIRunnable> runnable = std::move(aRunnable); 143 144 // TODO: bug 1492011 re ConsoleWorkletRunnable. 145 if (mTerminated) { 146 return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; 147 } 148 149 if (!mWorkletThread) { 150 // Thread creation. FIXME: this will change. 151 mWorkletThread = dom::WorkletThread::Create(this); 152 if (!mWorkletThread) { 153 return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; 154 } 155 } 156 157 return mWorkletThread->DispatchRunnable(runnable.forget()); 158 } 159 160 } // namespace mozilla