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/. */
7 #include "mozilla/dom/WorkerScope.h"
13 #include "GeckoProfiler.h"
14 #include "MainThreadUtils.h"
15 #include "ScriptLoader.h"
16 #include "js/CompilationAndEvaluation.h"
17 #include "js/CompileOptions.h"
18 #include "js/RealmOptions.h"
19 #include "js/RootingAPI.h"
20 #include "js/SourceText.h"
22 #include "js/Wrapper.h"
24 #include "jsfriendapi.h"
25 #include "mozilla/AlreadyAddRefed.h"
26 #include "mozilla/BaseProfilerMarkersPrerequisites.h"
27 #include "mozilla/CycleCollectedJSContext.h"
28 #include "mozilla/ErrorResult.h"
29 #include "mozilla/EventListenerManager.h"
30 #include "mozilla/Logging.h"
31 #include "mozilla/Maybe.h"
32 #include "mozilla/MozPromise.h"
33 #include "mozilla/Mutex.h"
34 #include "mozilla/NotNull.h"
35 #include "mozilla/RefPtr.h"
36 #include "mozilla/Result.h"
37 #include "mozilla/StaticAnalysisFunctions.h"
38 #include "mozilla/StorageAccess.h"
39 #include "mozilla/UniquePtr.h"
40 #include "mozilla/Unused.h"
41 #include "mozilla/dom/AutoEntryScript.h"
42 #include "mozilla/ipc/BackgroundChild.h"
43 #include "mozilla/dom/BindingDeclarations.h"
44 #include "mozilla/dom/BindingUtils.h"
45 #include "mozilla/dom/BlobURLProtocolHandler.h"
46 #include "mozilla/dom/CSPEvalChecker.h"
47 #include "mozilla/dom/CallbackDebuggerNotification.h"
48 #include "mozilla/dom/ClientSource.h"
49 #include "mozilla/dom/Clients.h"
50 #include "mozilla/dom/Console.h"
51 #include "mozilla/dom/DOMMozPromiseRequestHolder.h"
52 #include "mozilla/dom/DebuggerNotification.h"
53 #include "mozilla/dom/DebuggerNotificationBinding.h"
54 #include "mozilla/dom/DebuggerNotificationManager.h"
55 #include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
56 #include "mozilla/dom/DOMString.h"
57 #include "mozilla/dom/Fetch.h"
58 #include "mozilla/dom/FontFaceSet.h"
59 #include "mozilla/dom/IDBFactory.h"
60 #include "mozilla/dom/ImageBitmap.h"
61 #include "mozilla/dom/ImageBitmapSource.h"
62 #include "mozilla/dom/MessagePortBinding.h"
63 #include "mozilla/ipc/PBackgroundChild.h"
64 #include "mozilla/ipc/PBackgroundSharedTypes.h"
65 #include "mozilla/dom/Performance.h"
66 #include "mozilla/dom/Promise.h"
67 #include "mozilla/dom/PromiseWorkerProxy.h"
68 #include "mozilla/dom/WebTaskSchedulerWorker.h"
69 #include "mozilla/dom/ScriptSettings.h"
70 #include "mozilla/dom/SerializedStackHolder.h"
71 #include "mozilla/dom/ServiceWorkerDescriptor.h"
72 #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
73 #include "mozilla/dom/ServiceWorkerManager.h"
74 #include "mozilla/dom/ServiceWorkerRegistration.h"
75 #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
76 #include "mozilla/dom/ServiceWorkerUtils.h"
77 #include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
78 #include "mozilla/dom/SimpleGlobalObject.h"
79 #include "mozilla/dom/TimeoutHandler.h"
80 #include "mozilla/dom/TestUtils.h"
81 #include "mozilla/dom/WorkerCommon.h"
82 #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
83 #include "mozilla/dom/WorkerGlobalScopeBinding.h"
84 #include "mozilla/dom/WorkerLocation.h"
85 #include "mozilla/dom/WorkerNavigator.h"
86 #include "mozilla/dom/WorkerPrivate.h"
87 #include "mozilla/dom/WorkerRunnable.h"
88 #include "mozilla/dom/WorkerDocumentListener.h"
89 #include "mozilla/dom/VsyncWorkerChild.h"
90 #include "mozilla/dom/cache/CacheStorage.h"
91 #include "mozilla/dom/cache/Types.h"
92 #include "mozilla/extensions/ExtensionBrowser.h"
93 #include "mozilla/fallible.h"
94 #include "mozilla/gfx/Rect.h"
97 #include "nsContentUtils.h"
99 #include "nsGkAtoms.h"
100 #include "nsIEventTarget.h"
101 #include "nsIGlobalObject.h"
102 #include "nsIScriptError.h"
103 #include "nsISerialEventTarget.h"
104 #include "nsIWeakReference.h"
105 #include "nsJSUtils.h"
106 #include "nsLiteralString.h"
107 #include "nsQueryObject.h"
108 #include "nsReadableUtils.h"
109 #include "nsRFPService.h"
110 #include "nsString.h"
111 #include "nsTArray.h"
112 #include "nsTLiteralString.h"
113 #include "nsThreadUtils.h"
114 #include "nsWeakReference.h"
115 #include "nsWrapperCacheInlines.h"
117 #include "xpcpublic.h"
120 # include <android/log.h>
127 using mozilla::dom::cache::CacheStorage
;
128 using mozilla::dom::workerinternals::NamedWorkerGlobalScopeMixin
;
129 using mozilla::ipc::BackgroundChild
;
130 using mozilla::ipc::PBackgroundChild
;
131 using mozilla::ipc::PrincipalInfo
;
133 namespace mozilla::dom
{
135 static mozilla::LazyLogModule
sWorkerScopeLog("WorkerScope");
140 #define LOG(args) MOZ_LOG(sWorkerScopeLog, LogLevel::Debug, args);
142 class WorkerScriptTimeoutHandler final
: public ScriptTimeoutHandler
{
144 NS_DECL_ISUPPORTS_INHERITED
145 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WorkerScriptTimeoutHandler
,
146 ScriptTimeoutHandler
)
148 WorkerScriptTimeoutHandler(JSContext
* aCx
, nsIGlobalObject
* aGlobal
,
149 const nsAString
& aExpression
)
150 : ScriptTimeoutHandler(aCx
, aGlobal
, aExpression
) {}
152 MOZ_CAN_RUN_SCRIPT
virtual bool Call(const char* aExecutionReason
) override
;
155 virtual ~WorkerScriptTimeoutHandler() = default;
158 NS_IMPL_CYCLE_COLLECTION_INHERITED(WorkerScriptTimeoutHandler
,
159 ScriptTimeoutHandler
)
161 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerScriptTimeoutHandler
)
162 NS_INTERFACE_MAP_END_INHERITING(ScriptTimeoutHandler
)
164 NS_IMPL_ADDREF_INHERITED(WorkerScriptTimeoutHandler
, ScriptTimeoutHandler
)
165 NS_IMPL_RELEASE_INHERITED(WorkerScriptTimeoutHandler
, ScriptTimeoutHandler
)
167 bool WorkerScriptTimeoutHandler::Call(const char* aExecutionReason
) {
169 AutoEntryScript
aes(mGlobal
, aExecutionReason
, false);
171 JSContext
* cx
= aes
.cx();
172 JS::CompileOptions
options(cx
);
173 options
.setFileAndLine(mFileName
.get(), mLineNo
).setNoScriptRval(true);
174 options
.setIntroductionType("domTimer");
176 JS::Rooted
<JS::Value
> unused(cx
);
177 JS::SourceText
<char16_t
> srcBuf
;
178 if (!srcBuf
.init(cx
, mExpr
.BeginReading(), mExpr
.Length(),
179 JS::SourceOwnership::Borrowed
) ||
180 !JS::Evaluate(cx
, options
, srcBuf
, &unused
)) {
181 if (!JS_IsExceptionPending(cx
)) {
189 namespace workerinternals
{
190 void NamedWorkerGlobalScopeMixin::GetName(DOMString
& aName
) const {
191 aName
.AsAString() = mName
;
193 } // namespace workerinternals
195 NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScopeBase
)
197 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScopeBase
,
198 DOMEventTargetHelper
)
199 tmp
->AssertIsOnWorkerThread();
200 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole
)
201 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mModuleLoader
)
202 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSerialEventTarget
)
203 tmp
->TraverseObjectsInGlobal(cb
);
204 // If we already exited WorkerThreadPrimaryRunnable, we will find it
205 // nullptr and there is nothing left to do here on the WorkerPrivate,
206 // in particular the timeouts have already been canceled and unlinked.
207 if (tmp
->mWorkerPrivate
) {
208 tmp
->mWorkerPrivate
->TraverseTimeouts(cb
);
210 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
212 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScopeBase
,
213 DOMEventTargetHelper
)
214 tmp
->AssertIsOnWorkerThread();
215 NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole
)
216 NS_IMPL_CYCLE_COLLECTION_UNLINK(mModuleLoader
)
217 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSerialEventTarget
)
218 tmp
->UnlinkObjectsInGlobal();
219 // If we already exited WorkerThreadPrimaryRunnable, we will find it
220 // nullptr and there is nothing left to do here on the WorkerPrivate,
221 // in particular the timeouts have already been canceled and unlinked.
222 if (tmp
->mWorkerPrivate
) {
223 tmp
->mWorkerPrivate
->UnlinkTimeouts();
225 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
226 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
228 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScopeBase
,
229 DOMEventTargetHelper
)
230 tmp
->AssertIsOnWorkerThread();
231 NS_IMPL_CYCLE_COLLECTION_TRACE_END
233 NS_IMPL_ADDREF_INHERITED(WorkerGlobalScopeBase
, DOMEventTargetHelper
)
234 NS_IMPL_RELEASE_INHERITED(WorkerGlobalScopeBase
, DOMEventTargetHelper
)
236 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScopeBase
)
237 NS_INTERFACE_MAP_ENTRY(nsIGlobalObject
)
238 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
239 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
241 WorkerGlobalScopeBase::WorkerGlobalScopeBase(
242 WorkerPrivate
* aWorkerPrivate
, UniquePtr
<ClientSource
> aClientSource
)
243 : mWorkerPrivate(aWorkerPrivate
),
244 mClientSource(std::move(aClientSource
)),
245 mSerialEventTarget(aWorkerPrivate
->HybridEventTarget()) {
246 LOG(("WorkerGlobalScopeBase::WorkerGlobalScopeBase [%p]", this));
247 MOZ_ASSERT(mWorkerPrivate
);
249 mWorkerPrivate
->AssertIsOnWorkerThread();
250 mWorkerThreadUsedOnlyForAssert
= PR_GetCurrentThread();
252 MOZ_ASSERT(mClientSource
);
254 MOZ_DIAGNOSTIC_ASSERT(
256 "There should be an event target when a worker global is created.");
258 // In workers, each DETH must have an owner. Because the global scope doesn't
259 // have one, let's set it as owner of itself.
260 BindToOwner(static_cast<nsIGlobalObject
*>(this));
263 WorkerGlobalScopeBase::~WorkerGlobalScopeBase() = default;
265 JSObject
* WorkerGlobalScopeBase::GetGlobalJSObject() {
266 AssertIsOnWorkerThread();
270 JSObject
* WorkerGlobalScopeBase::GetGlobalJSObjectPreserveColor() const {
271 AssertIsOnWorkerThread();
272 return GetWrapperPreserveColor();
275 bool WorkerGlobalScopeBase::IsSharedMemoryAllowed() const {
276 AssertIsOnWorkerThread();
277 return mWorkerPrivate
->IsSharedMemoryAllowed();
280 bool WorkerGlobalScopeBase::ShouldResistFingerprinting(
281 RFPTarget aTarget
) const {
282 AssertIsOnWorkerThread();
283 return mWorkerPrivate
->ShouldResistFingerprinting(aTarget
);
286 OriginTrials
WorkerGlobalScopeBase::Trials() const {
287 AssertIsOnWorkerThread();
288 return mWorkerPrivate
->Trials();
291 StorageAccess
WorkerGlobalScopeBase::GetStorageAccess() {
292 AssertIsOnWorkerThread();
293 return mWorkerPrivate
->StorageAccess();
296 Maybe
<ClientInfo
> WorkerGlobalScopeBase::GetClientInfo() const {
297 return Some(mClientSource
->Info());
300 Maybe
<ServiceWorkerDescriptor
> WorkerGlobalScopeBase::GetController() const {
301 return mClientSource
->GetController();
304 mozilla::Result
<mozilla::ipc::PrincipalInfo
, nsresult
>
305 WorkerGlobalScopeBase::GetStorageKey() {
306 AssertIsOnWorkerThread();
308 const mozilla::ipc::PrincipalInfo
& principalInfo
=
309 mWorkerPrivate
->GetEffectiveStoragePrincipalInfo();
311 // Block expanded and null principals, let content and system through.
312 if (principalInfo
.type() !=
313 mozilla::ipc::PrincipalInfo::TContentPrincipalInfo
&&
314 principalInfo
.type() !=
315 mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo
) {
316 return Err(NS_ERROR_DOM_SECURITY_ERR
);
319 return principalInfo
;
322 void WorkerGlobalScopeBase::Control(
323 const ServiceWorkerDescriptor
& aServiceWorker
) {
324 AssertIsOnWorkerThread();
325 MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate
->IsChromeWorker());
326 MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate
->Kind() != WorkerKindService
);
328 if (IsBlobURI(mWorkerPrivate
->GetBaseURI())) {
329 // Blob URL workers can only become controlled by inheriting from
330 // their parent. Make sure to note this properly.
331 mClientSource
->InheritController(aServiceWorker
);
333 // Otherwise this is a normal interception and we simply record the
334 // controller locally.
335 mClientSource
->SetController(aServiceWorker
);
339 nsresult
WorkerGlobalScopeBase::Dispatch(
340 already_AddRefed
<nsIRunnable
>&& aRunnable
) const {
341 return SerialEventTarget()->Dispatch(std::move(aRunnable
),
345 nsISerialEventTarget
* WorkerGlobalScopeBase::SerialEventTarget() const {
346 AssertIsOnWorkerThread();
347 return mSerialEventTarget
;
350 // See also AutoJSAPI::ReportException
351 void WorkerGlobalScopeBase::ReportError(JSContext
* aCx
,
352 JS::Handle
<JS::Value
> aError
,
353 CallerType
, ErrorResult
& aRv
) {
354 JS::ErrorReportBuilder
jsReport(aCx
);
355 JS::ExceptionStack
exnStack(aCx
, aError
, nullptr);
356 if (!jsReport
.init(aCx
, exnStack
, JS::ErrorReportBuilder::NoSideEffects
)) {
357 return aRv
.NoteJSContextException(aCx
);
360 // Before invoking ReportError, put the exception back on the context,
361 // because it may want to put it in its error events and has no other way
362 // to get hold of it. After we invoke ReportError, clear the exception on
363 // cx(), just in case ReportError didn't.
364 JS::SetPendingExceptionStack(aCx
, exnStack
);
365 mWorkerPrivate
->ReportError(aCx
, jsReport
.toStringResult(),
367 JS_ClearPendingException(aCx
);
370 void WorkerGlobalScopeBase::Atob(const nsAString
& aAtob
, nsAString
& aOut
,
371 ErrorResult
& aRv
) const {
372 AssertIsOnWorkerThread();
373 aRv
= nsContentUtils::Atob(aAtob
, aOut
);
376 void WorkerGlobalScopeBase::Btoa(const nsAString
& aBtoa
, nsAString
& aOut
,
377 ErrorResult
& aRv
) const {
378 AssertIsOnWorkerThread();
379 aRv
= nsContentUtils::Btoa(aBtoa
, aOut
);
382 already_AddRefed
<Console
> WorkerGlobalScopeBase::GetConsole(ErrorResult
& aRv
) {
383 AssertIsOnWorkerThread();
386 mConsole
= Console::Create(mWorkerPrivate
->GetJSContext(), nullptr, aRv
);
387 if (NS_WARN_IF(aRv
.Failed())) {
392 RefPtr
<Console
> console
= mConsole
;
393 return console
.forget();
396 uint64_t WorkerGlobalScopeBase::WindowID() const {
397 return mWorkerPrivate
->WindowID();
400 NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope
)
402 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope
,
403 WorkerGlobalScopeBase
)
404 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto
)
405 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance
)
406 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebTaskScheduler
)
407 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrustedTypePolicyFactory
)
408 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation
)
409 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator
)
410 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet
)
411 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB
)
412 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage
)
413 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager
)
414 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
416 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope
,
417 WorkerGlobalScopeBase
)
418 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto
)
419 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance
)
420 if (tmp
->mWebTaskScheduler
) {
421 tmp
->mWebTaskScheduler
->Disconnect();
422 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebTaskScheduler
)
424 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrustedTypePolicyFactory
)
425 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation
)
426 NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator
)
427 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet
)
428 NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB
)
429 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage
)
430 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager
)
431 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
433 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(WorkerGlobalScope
,
434 WorkerGlobalScopeBase
)
436 WorkerGlobalScope::~WorkerGlobalScope() = default;
438 void WorkerGlobalScope::NoteTerminating() {
439 LOG(("WorkerGlobalScope::NoteTerminating [%p]", this));
447 void WorkerGlobalScope::NoteShuttingDown() {
448 MOZ_ASSERT(IsDying());
449 LOG(("WorkerGlobalScope::NoteShuttingDown [%p]", this));
452 mNavigator
->Invalidate();
453 mNavigator
= nullptr;
457 Crypto
* WorkerGlobalScope::GetCrypto(ErrorResult
& aError
) {
458 AssertIsOnWorkerThread();
461 mCrypto
= new Crypto(this);
467 already_AddRefed
<CacheStorage
> WorkerGlobalScope::GetCaches(ErrorResult
& aRv
) {
468 if (!mCacheStorage
) {
469 mCacheStorage
= CacheStorage::CreateOnWorker(cache::DEFAULT_NAMESPACE
, this,
470 mWorkerPrivate
, aRv
);
473 RefPtr
<CacheStorage
> ref
= mCacheStorage
;
477 bool WorkerGlobalScope::IsSecureContext() const {
478 bool globalSecure
= JS::GetIsSecureContext(
479 js::GetNonCCWObjectRealm(GetWrapperPreserveColor()));
480 MOZ_ASSERT(globalSecure
== mWorkerPrivate
->IsSecureContext());
484 already_AddRefed
<WorkerLocation
> WorkerGlobalScope::Location() {
485 AssertIsOnWorkerThread();
488 mLocation
= WorkerLocation::Create(mWorkerPrivate
->GetLocationInfo());
489 MOZ_ASSERT(mLocation
);
492 RefPtr
<WorkerLocation
> location
= mLocation
;
493 return location
.forget();
496 already_AddRefed
<WorkerNavigator
> WorkerGlobalScope::Navigator() {
497 AssertIsOnWorkerThread();
500 mNavigator
= WorkerNavigator::Create(mWorkerPrivate
->OnLine());
501 MOZ_ASSERT(mNavigator
);
504 RefPtr
<WorkerNavigator
> navigator
= mNavigator
;
505 return navigator
.forget();
508 already_AddRefed
<WorkerNavigator
> WorkerGlobalScope::GetExistingNavigator()
510 AssertIsOnWorkerThread();
512 RefPtr
<WorkerNavigator
> navigator
= mNavigator
;
513 return navigator
.forget();
516 FontFaceSet
* WorkerGlobalScope::GetFonts(ErrorResult
& aRv
) {
517 AssertIsOnWorkerThread();
520 mFontFaceSet
= FontFaceSet::CreateForWorker(this, mWorkerPrivate
);
521 if (MOZ_UNLIKELY(!mFontFaceSet
)) {
522 aRv
.ThrowInvalidStateError("Couldn't acquire worker reference");
530 OnErrorEventHandlerNonNull
* WorkerGlobalScope::GetOnerror() {
531 AssertIsOnWorkerThread();
533 EventListenerManager
* elm
= GetExistingListenerManager();
534 return elm
? elm
->GetOnErrorEventHandler() : nullptr;
537 void WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull
* aHandler
) {
538 AssertIsOnWorkerThread();
540 EventListenerManager
* elm
= GetOrCreateListenerManager();
542 elm
->SetEventHandler(aHandler
);
546 void WorkerGlobalScope::ImportScripts(JSContext
* aCx
,
547 const Sequence
<nsString
>& aScriptURLs
,
549 AssertIsOnWorkerThread();
551 UniquePtr
<SerializedStackHolder
> stack
;
552 if (mWorkerPrivate
->IsWatchedByDevTools()) {
553 stack
= GetCurrentStackForNetMonitor(aCx
);
557 AUTO_PROFILER_MARKER_TEXT(
558 "ImportScripts", JS
, MarkerStack::Capture(),
559 profiler_thread_is_being_profiled_for_markers()
560 ? StringJoin(","_ns
, aScriptURLs
,
561 [](nsACString
& dest
, const auto& scriptUrl
) {
565 std::min(size_t(128), scriptUrl
.Length())),
569 workerinternals::Load(mWorkerPrivate
, std::move(stack
), aScriptURLs
,
574 int32_t WorkerGlobalScope::SetTimeout(JSContext
* aCx
, Function
& aHandler
,
575 const int32_t aTimeout
,
576 const Sequence
<JS::Value
>& aArguments
,
578 return SetTimeoutOrInterval(aCx
, aHandler
, aTimeout
, aArguments
, false, aRv
);
581 int32_t WorkerGlobalScope::SetTimeout(JSContext
* aCx
, const nsAString
& aHandler
,
582 const int32_t aTimeout
,
583 const Sequence
<JS::Value
>& /* unused */,
585 return SetTimeoutOrInterval(aCx
, aHandler
, aTimeout
, false, aRv
);
588 void WorkerGlobalScope::ClearTimeout(int32_t aHandle
) {
589 AssertIsOnWorkerThread();
591 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearTimeout
);
593 mWorkerPrivate
->ClearTimeout(aHandle
, Timeout::Reason::eTimeoutOrInterval
);
596 int32_t WorkerGlobalScope::SetInterval(JSContext
* aCx
, Function
& aHandler
,
597 const int32_t aTimeout
,
598 const Sequence
<JS::Value
>& aArguments
,
600 return SetTimeoutOrInterval(aCx
, aHandler
, aTimeout
, aArguments
, true, aRv
);
603 int32_t WorkerGlobalScope::SetInterval(JSContext
* aCx
,
604 const nsAString
& aHandler
,
605 const int32_t aTimeout
,
606 const Sequence
<JS::Value
>& /* unused */,
608 return SetTimeoutOrInterval(aCx
, aHandler
, aTimeout
, true, aRv
);
611 void WorkerGlobalScope::ClearInterval(int32_t aHandle
) {
612 AssertIsOnWorkerThread();
614 DebuggerNotificationDispatch(this, DebuggerNotificationType::ClearInterval
);
616 mWorkerPrivate
->ClearTimeout(aHandle
, Timeout::Reason::eTimeoutOrInterval
);
619 int32_t WorkerGlobalScope::SetTimeoutOrInterval(
620 JSContext
* aCx
, Function
& aHandler
, const int32_t aTimeout
,
621 const Sequence
<JS::Value
>& aArguments
, bool aIsInterval
, ErrorResult
& aRv
) {
622 AssertIsOnWorkerThread();
624 DebuggerNotificationDispatch(
625 this, aIsInterval
? DebuggerNotificationType::SetInterval
626 : DebuggerNotificationType::SetTimeout
);
628 nsTArray
<JS::Heap
<JS::Value
>> args
;
629 if (!args
.AppendElements(aArguments
, fallible
)) {
630 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
634 RefPtr
<TimeoutHandler
> handler
=
635 new CallbackTimeoutHandler(aCx
, this, &aHandler
, std::move(args
));
637 return mWorkerPrivate
->SetTimeout(aCx
, handler
, aTimeout
, aIsInterval
,
638 Timeout::Reason::eTimeoutOrInterval
, aRv
);
641 int32_t WorkerGlobalScope::SetTimeoutOrInterval(JSContext
* aCx
,
642 const nsAString
& aHandler
,
643 const int32_t aTimeout
,
646 AssertIsOnWorkerThread();
648 DebuggerNotificationDispatch(
649 this, aIsInterval
? DebuggerNotificationType::SetInterval
650 : DebuggerNotificationType::SetTimeout
);
652 bool allowEval
= false;
654 CSPEvalChecker::CheckForWorker(aCx
, mWorkerPrivate
, aHandler
, &allowEval
);
655 if (NS_WARN_IF(aRv
.Failed()) || !allowEval
) {
659 RefPtr
<TimeoutHandler
> handler
=
660 new WorkerScriptTimeoutHandler(aCx
, this, aHandler
);
662 return mWorkerPrivate
->SetTimeout(aCx
, handler
, aTimeout
, aIsInterval
,
663 Timeout::Reason::eTimeoutOrInterval
, aRv
);
666 void WorkerGlobalScope::GetOrigin(nsAString
& aOrigin
) const {
667 AssertIsOnWorkerThread();
668 nsContentUtils::GetWebExposedOriginSerialization(
669 mWorkerPrivate
->GetPrincipal(), aOrigin
);
672 bool WorkerGlobalScope::CrossOriginIsolated() const {
673 return mWorkerPrivate
->CrossOriginIsolated();
676 void WorkerGlobalScope::Dump(const Optional
<nsAString
>& aString
) const {
677 AssertIsOnWorkerThread();
679 if (!aString
.WasPassed()) {
683 if (!nsJSUtils::DumpEnabled()) {
687 NS_ConvertUTF16toUTF8
str(aString
.Value());
689 MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug
,
690 ("[Worker.Dump] %s", str
.get()));
692 __android_log_print(ANDROID_LOG_INFO
, "Gecko", "%s", str
.get());
694 fputs(str
.get(), stdout
);
698 Performance
* WorkerGlobalScope::GetPerformance() {
699 AssertIsOnWorkerThread();
702 mPerformance
= Performance::CreateForWorker(this);
708 bool WorkerGlobalScope::IsInAutomation(JSContext
* aCx
, JSObject
* /* unused */) {
709 return GetWorkerPrivateFromContext(aCx
)->IsInAutomation();
712 void WorkerGlobalScope::GetJSTestingFunctions(
713 JSContext
* aCx
, JS::MutableHandle
<JSObject
*> aFunctions
, ErrorResult
& aRv
) {
714 JSObject
* obj
= js::GetTestingFunctions(aCx
);
716 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
723 already_AddRefed
<Promise
> WorkerGlobalScope::Fetch(
724 const RequestOrUTF8String
& aInput
, const RequestInit
& aInit
,
725 CallerType aCallerType
, ErrorResult
& aRv
) {
726 return FetchRequest(this, aInput
, aInit
, aCallerType
, aRv
);
729 already_AddRefed
<IDBFactory
> WorkerGlobalScope::GetIndexedDB(
730 JSContext
* aCx
, ErrorResult
& aErrorResult
) {
731 AssertIsOnWorkerThread();
733 RefPtr
<IDBFactory
> indexedDB
= mIndexedDB
;
736 StorageAccess access
= mWorkerPrivate
->StorageAccess();
738 if (access
== StorageAccess::eDeny
) {
739 NS_WARNING("IndexedDB is not allowed in this worker!");
740 aErrorResult
= NS_ERROR_DOM_SECURITY_ERR
;
744 if (ShouldPartitionStorage(access
) &&
745 !StoragePartitioningEnabled(access
,
746 mWorkerPrivate
->CookieJarSettings())) {
747 NS_WARNING("IndexedDB is not allowed in this worker!");
748 aErrorResult
= NS_ERROR_DOM_SECURITY_ERR
;
752 const PrincipalInfo
& principalInfo
=
753 mWorkerPrivate
->GetEffectiveStoragePrincipalInfo();
755 auto res
= IDBFactory::CreateForWorker(this, principalInfo
,
756 mWorkerPrivate
->WindowID());
757 if (NS_WARN_IF(res
.isErr())) {
758 aErrorResult
= res
.unwrapErr();
762 indexedDB
= res
.unwrap();
763 mIndexedDB
= indexedDB
;
766 return indexedDB
.forget();
769 WebTaskScheduler
* WorkerGlobalScope::Scheduler() {
770 mWorkerPrivate
->AssertIsOnWorkerThread();
772 if (!mWebTaskScheduler
) {
773 mWebTaskScheduler
= WebTaskScheduler::CreateForWorker(mWorkerPrivate
);
776 MOZ_ASSERT(mWebTaskScheduler
);
777 return mWebTaskScheduler
;
780 WebTaskScheduler
* WorkerGlobalScope::GetExistingScheduler() const {
781 return mWebTaskScheduler
;
784 already_AddRefed
<Promise
> WorkerGlobalScope::CreateImageBitmap(
785 const ImageBitmapSource
& aImage
, const ImageBitmapOptions
& aOptions
,
787 return ImageBitmap::Create(this, aImage
, Nothing(), aOptions
, aRv
);
790 already_AddRefed
<Promise
> WorkerGlobalScope::CreateImageBitmap(
791 const ImageBitmapSource
& aImage
, int32_t aSx
, int32_t aSy
, int32_t aSw
,
792 int32_t aSh
, const ImageBitmapOptions
& aOptions
, ErrorResult
& aRv
) {
793 return ImageBitmap::Create(
794 this, aImage
, Some(gfx::IntRect(aSx
, aSy
, aSw
, aSh
)), aOptions
, aRv
);
797 // https://html.spec.whatwg.org/#structured-cloning
798 void WorkerGlobalScope::StructuredClone(
799 JSContext
* aCx
, JS::Handle
<JS::Value
> aValue
,
800 const StructuredSerializeOptions
& aOptions
,
801 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aError
) {
802 nsContentUtils::StructuredClone(aCx
, this, aValue
, aOptions
, aRetval
, aError
);
805 mozilla::dom::DebuggerNotificationManager
*
806 WorkerGlobalScope::GetOrCreateDebuggerNotificationManager() {
807 if (!mDebuggerNotificationManager
) {
808 mDebuggerNotificationManager
= new DebuggerNotificationManager(this);
811 return mDebuggerNotificationManager
;
814 mozilla::dom::DebuggerNotificationManager
*
815 WorkerGlobalScope::GetExistingDebuggerNotificationManager() {
816 return mDebuggerNotificationManager
;
819 Maybe
<EventCallbackDebuggerNotificationType
>
820 WorkerGlobalScope::GetDebuggerNotificationType() const {
821 return Some(EventCallbackDebuggerNotificationType::Global
);
824 RefPtr
<ServiceWorkerRegistration
>
825 WorkerGlobalScope::GetServiceWorkerRegistration(
826 const ServiceWorkerRegistrationDescriptor
& aDescriptor
) const {
827 AssertIsOnWorkerThread();
828 RefPtr
<ServiceWorkerRegistration
> ref
;
829 ForEachGlobalTeardownObserver(
830 [&](GlobalTeardownObserver
* aObserver
, bool* aDoneOut
) {
831 RefPtr
<ServiceWorkerRegistration
> swr
= do_QueryObject(aObserver
);
832 if (!swr
|| !swr
->MatchesDescriptor(aDescriptor
)) {
836 ref
= std::move(swr
);
842 RefPtr
<ServiceWorkerRegistration
>
843 WorkerGlobalScope::GetOrCreateServiceWorkerRegistration(
844 const ServiceWorkerRegistrationDescriptor
& aDescriptor
) {
845 AssertIsOnWorkerThread();
846 RefPtr
<ServiceWorkerRegistration
> ref
=
847 GetServiceWorkerRegistration(aDescriptor
);
849 ref
= ServiceWorkerRegistration::CreateForWorker(mWorkerPrivate
, this,
855 mozilla::dom::StorageManager
* WorkerGlobalScope::GetStorageManager() {
856 return RefPtr(Navigator())->Storage();
859 // https://html.spec.whatwg.org/multipage/web-messaging.html#eligible-for-messaging
860 // * a WorkerGlobalScope object whose closing flag is false and whose worker
861 // is not a suspendable worker.
862 bool WorkerGlobalScope::IsEligibleForMessaging() {
863 return mIsEligibleForMessaging
;
865 void WorkerGlobalScope::StorageAccessPermissionGranted() {
866 // Reset the IndexedDB factory.
867 mIndexedDB
= nullptr;
870 mCacheStorage
= nullptr;
873 TrustedTypePolicyFactory
* WorkerGlobalScope::TrustedTypes() {
874 if (!mTrustedTypePolicyFactory
) {
875 mTrustedTypePolicyFactory
= MakeRefPtr
<TrustedTypePolicyFactory
>(this);
878 return mTrustedTypePolicyFactory
;
881 bool WorkerGlobalScope::WindowInteractionAllowed() const {
882 AssertIsOnWorkerThread();
883 return mWindowInteractionsAllowed
> 0;
886 void WorkerGlobalScope::AllowWindowInteraction() {
887 AssertIsOnWorkerThread();
888 mWindowInteractionsAllowed
++;
891 void WorkerGlobalScope::ConsumeWindowInteraction() {
892 AssertIsOnWorkerThread();
893 MOZ_ASSERT(mWindowInteractionsAllowed
);
894 mWindowInteractionsAllowed
--;
897 NS_IMPL_CYCLE_COLLECTION_INHERITED(DedicatedWorkerGlobalScope
,
898 WorkerGlobalScope
, mFrameRequestManager
)
900 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DedicatedWorkerGlobalScope
,
902 NS_IMPL_CYCLE_COLLECTION_TRACE_END
904 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(DedicatedWorkerGlobalScope
,
907 DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(
908 WorkerPrivate
* aWorkerPrivate
, UniquePtr
<ClientSource
> aClientSource
,
909 const nsString
& aName
)
910 : WorkerGlobalScope(std::move(aWorkerPrivate
), std::move(aClientSource
)),
911 NamedWorkerGlobalScopeMixin(aName
) {}
913 bool DedicatedWorkerGlobalScope::WrapGlobalObject(
914 JSContext
* aCx
, JS::MutableHandle
<JSObject
*> aReflector
) {
915 AssertIsOnWorkerThread();
916 MOZ_ASSERT(!mWorkerPrivate
->IsSharedWorker());
918 JS::RealmOptions options
;
919 mWorkerPrivate
->CopyJSRealmOptions(options
);
921 xpc::SetPrefableRealmOptions(options
);
923 return DedicatedWorkerGlobalScope_Binding::Wrap(
924 aCx
, this, this, options
,
925 nsJSPrincipals::get(mWorkerPrivate
->GetPrincipal()), aReflector
);
928 void DedicatedWorkerGlobalScope::PostMessage(
929 JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
930 const Sequence
<JSObject
*>& aTransferable
, ErrorResult
& aRv
) {
931 AssertIsOnWorkerThread();
932 mWorkerPrivate
->PostMessageToParent(aCx
, aMessage
, aTransferable
, aRv
);
935 void DedicatedWorkerGlobalScope::PostMessage(
936 JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
937 const StructuredSerializeOptions
& aOptions
, ErrorResult
& aRv
) {
938 AssertIsOnWorkerThread();
939 mWorkerPrivate
->PostMessageToParent(aCx
, aMessage
, aOptions
.mTransfer
, aRv
);
942 void DedicatedWorkerGlobalScope::Close() {
943 AssertIsOnWorkerThread();
944 mWorkerPrivate
->CloseInternal();
947 int32_t DedicatedWorkerGlobalScope::RequestAnimationFrame(
948 FrameRequestCallback
& aCallback
, ErrorResult
& aError
) {
949 AssertIsOnWorkerThread();
951 DebuggerNotificationDispatch(this,
952 DebuggerNotificationType::RequestAnimationFrame
);
954 // Ensure the worker is associated with a window.
955 if (mWorkerPrivate
->WindowID() == UINT64_MAX
) {
956 aError
.ThrowNotSupportedError("Worker has no associated owner Window");
961 PBackgroundChild
* bgChild
= BackgroundChild::GetOrCreateForCurrentThread();
962 mVsyncChild
= MakeRefPtr
<VsyncWorkerChild
>();
964 if (!bgChild
|| !mVsyncChild
->Initialize(mWorkerPrivate
) ||
965 !bgChild
->SendPVsyncConstructor(mVsyncChild
)) {
966 mVsyncChild
->Destroy();
967 mVsyncChild
= nullptr;
968 aError
.ThrowNotSupportedError(
969 "Worker failed to register for vsync to drive event loop");
975 mDocListener
= WorkerDocumentListener::Create(mWorkerPrivate
);
977 aError
.ThrowNotSupportedError(
978 "Worker failed to register for document visibility events");
984 aError
= mFrameRequestManager
.Schedule(aCallback
, &handle
);
985 if (!aError
.Failed() && mDocumentVisible
) {
986 mVsyncChild
->TryObserve();
991 void DedicatedWorkerGlobalScope::CancelAnimationFrame(int32_t aHandle
,
992 ErrorResult
& aError
) {
993 AssertIsOnWorkerThread();
995 DebuggerNotificationDispatch(this,
996 DebuggerNotificationType::CancelAnimationFrame
);
998 // Ensure the worker is associated with a window.
999 if (mWorkerPrivate
->WindowID() == UINT64_MAX
) {
1000 aError
.ThrowNotSupportedError("Worker has no associated owner Window");
1004 mFrameRequestManager
.Cancel(aHandle
);
1005 if (mVsyncChild
&& mFrameRequestManager
.IsEmpty()) {
1006 mVsyncChild
->TryUnobserve();
1010 void DedicatedWorkerGlobalScope::OnDocumentVisible(bool aVisible
) {
1011 AssertIsOnWorkerThread();
1013 mDocumentVisible
= aVisible
;
1015 // We only change state immediately when we become visible. If we become
1016 // hidden, then we wait for the next vsync tick to apply that.
1017 if (aVisible
&& !mFrameRequestManager
.IsEmpty()) {
1018 mVsyncChild
->TryObserve();
1022 void DedicatedWorkerGlobalScope::OnVsync(const VsyncEvent
& aVsync
) {
1023 AssertIsOnWorkerThread();
1025 if (mFrameRequestManager
.IsEmpty() || !mDocumentVisible
) {
1026 // If we ever receive a vsync event, and there are still no callbacks to
1027 // process, or we remain hidden, we should disable observing them. By
1028 // waiting an extra tick, we ensure we minimize extra IPC for content that
1029 // does not call requestFrameAnimation directly during the callback, or
1030 // that is rapidly toggling between hidden and visible.
1031 mVsyncChild
->TryUnobserve();
1035 nsTArray
<FrameRequest
> callbacks
;
1036 mFrameRequestManager
.Take(callbacks
);
1038 RefPtr
<DedicatedWorkerGlobalScope
> scope(this);
1039 CallbackDebuggerNotificationGuard
guard(
1040 scope
, DebuggerNotificationType::RequestAnimationFrameCallback
);
1042 // This is similar to what we do in nsRefreshDriver::RunFrameRequestCallbacks
1043 // and Performance::TimeStampToDOMHighResForRendering in order to have the
1044 // same behaviour for requestAnimationFrame on both the main and worker
1046 DOMHighResTimeStamp timeStamp
= 0;
1047 if (!aVsync
.mTime
.IsNull()) {
1048 timeStamp
= mWorkerPrivate
->TimeStampToDOMHighRes(aVsync
.mTime
);
1049 // 0 is an inappropriate mixin for this this area; however CSS Animations
1050 // needs to have it's Time Reduction Logic refactored, so it's currently
1051 // only clamping for RFP mode. RFP mode gives a much lower time precision,
1052 // so we accept the security leak here for now.
1053 timeStamp
= nsRFPService::ReduceTimePrecisionAsMSecsRFPOnly(
1054 timeStamp
, 0, this->GetRTPCallerType());
1057 for (auto& callback
: callbacks
) {
1058 if (mFrameRequestManager
.IsCanceled(callback
.mHandle
)) {
1062 // MOZ_KnownLive is OK, because the stack array `callbacks` keeps the
1063 // callback alive and the mCallback strong reference can't be mutated by
1065 LogFrameRequestCallback::Run
run(callback
.mCallback
);
1066 MOZ_KnownLive(callback
.mCallback
)->Call(timeStamp
);
1070 SharedWorkerGlobalScope::SharedWorkerGlobalScope(
1071 WorkerPrivate
* aWorkerPrivate
, UniquePtr
<ClientSource
> aClientSource
,
1072 const nsString
& aName
)
1073 : WorkerGlobalScope(std::move(aWorkerPrivate
), std::move(aClientSource
)),
1074 NamedWorkerGlobalScopeMixin(aName
) {}
1076 bool SharedWorkerGlobalScope::WrapGlobalObject(
1077 JSContext
* aCx
, JS::MutableHandle
<JSObject
*> aReflector
) {
1078 AssertIsOnWorkerThread();
1079 MOZ_ASSERT(mWorkerPrivate
->IsSharedWorker());
1081 JS::RealmOptions options
;
1082 mWorkerPrivate
->CopyJSRealmOptions(options
);
1084 return SharedWorkerGlobalScope_Binding::Wrap(
1085 aCx
, this, this, options
,
1086 nsJSPrincipals::get(mWorkerPrivate
->GetPrincipal()), aReflector
);
1089 void SharedWorkerGlobalScope::Close() {
1090 AssertIsOnWorkerThread();
1091 mWorkerPrivate
->CloseInternal();
1094 NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope
, WorkerGlobalScope
,
1095 mClients
, mExtensionBrowser
, mRegistration
)
1096 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerGlobalScope
)
1097 NS_INTERFACE_MAP_END_INHERITING(WorkerGlobalScope
)
1099 NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope
, WorkerGlobalScope
)
1100 NS_IMPL_RELEASE_INHERITED(ServiceWorkerGlobalScope
, WorkerGlobalScope
)
1102 ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(
1103 WorkerPrivate
* aWorkerPrivate
, UniquePtr
<ClientSource
> aClientSource
,
1104 const ServiceWorkerRegistrationDescriptor
& aRegistrationDescriptor
)
1105 : WorkerGlobalScope(std::move(aWorkerPrivate
), std::move(aClientSource
)),
1106 mScope(NS_ConvertUTF8toUTF16(aRegistrationDescriptor
.Scope()))
1108 // Eagerly create the registration because we will need to receive
1109 // updates about the state of the registration. We can't wait until
1110 // first access to start receiving these.
1113 GetOrCreateServiceWorkerRegistration(aRegistrationDescriptor
)) {}
1115 ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() = default;
1117 bool ServiceWorkerGlobalScope::WrapGlobalObject(
1118 JSContext
* aCx
, JS::MutableHandle
<JSObject
*> aReflector
) {
1119 AssertIsOnWorkerThread();
1120 MOZ_ASSERT(mWorkerPrivate
->IsServiceWorker());
1122 JS::RealmOptions options
;
1123 mWorkerPrivate
->CopyJSRealmOptions(options
);
1125 return ServiceWorkerGlobalScope_Binding::Wrap(
1126 aCx
, this, this, options
,
1127 nsJSPrincipals::get(mWorkerPrivate
->GetPrincipal()), aReflector
);
1130 already_AddRefed
<Clients
> ServiceWorkerGlobalScope::GetClients() {
1132 mClients
= new Clients(this);
1135 RefPtr
<Clients
> ref
= mClients
;
1136 return ref
.forget();
1139 ServiceWorkerRegistration
* ServiceWorkerGlobalScope::Registration() {
1140 return mRegistration
;
1143 EventHandlerNonNull
* ServiceWorkerGlobalScope::GetOnfetch() {
1144 AssertIsOnWorkerThread();
1146 return GetEventHandler(nsGkAtoms::onfetch
);
1151 class ReportFetchListenerWarningRunnable final
: public Runnable
{
1152 const nsCString mScope
;
1153 nsString mSourceSpec
;
1158 explicit ReportFetchListenerWarningRunnable(const nsString
& aScope
)
1159 : mozilla::Runnable("ReportFetchListenerWarningRunnable"),
1160 mScope(NS_ConvertUTF16toUTF8(aScope
)) {
1161 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
1162 MOZ_ASSERT(workerPrivate
);
1163 JSContext
* cx
= workerPrivate
->GetJSContext();
1166 nsJSUtils::GetCallingLocation(cx
, mSourceSpec
, &mLine
, &mColumn
);
1171 AssertIsOnMainThread();
1173 ServiceWorkerManager::LocalizeAndReportToAllClients(
1174 mScope
, "ServiceWorkerNoFetchHandler", nsTArray
<nsString
>{},
1175 nsIScriptError::warningFlag
, mSourceSpec
, u
""_ns
, mLine
, mColumn
);
1181 } // anonymous namespace
1183 void ServiceWorkerGlobalScope::NoteFetchHandlerWasAdded() const {
1184 if (mWorkerPrivate
->WorkerScriptExecutedSuccessfully()) {
1185 RefPtr
<Runnable
> r
= new ReportFetchListenerWarningRunnable(mScope
);
1186 mWorkerPrivate
->DispatchToMainThreadForMessaging(r
.forget());
1188 mWorkerPrivate
->SetFetchHandlerWasAdded();
1191 void ServiceWorkerGlobalScope::SetOnfetch(
1192 mozilla::dom::EventHandlerNonNull
* aCallback
) {
1193 AssertIsOnWorkerThread();
1196 NoteFetchHandlerWasAdded();
1198 SetEventHandler(nsGkAtoms::onfetch
, aCallback
);
1201 void ServiceWorkerGlobalScope::EventListenerAdded(nsAtom
* aType
) {
1202 AssertIsOnWorkerThread();
1204 if (aType
== nsGkAtoms::onfetch
) {
1205 NoteFetchHandlerWasAdded();
1209 already_AddRefed
<Promise
> ServiceWorkerGlobalScope::SkipWaiting(
1211 AssertIsOnWorkerThread();
1212 MOZ_ASSERT(mWorkerPrivate
->IsServiceWorker());
1214 RefPtr
<Promise
> promise
= Promise::Create(this, aRv
);
1215 if (NS_WARN_IF(aRv
.Failed())) {
1219 using MozPromiseType
=
1220 decltype(mWorkerPrivate
->SetServiceWorkerSkipWaitingFlag())::element_type
;
1221 auto holder
= MakeRefPtr
<DOMMozPromiseRequestHolder
<MozPromiseType
>>(this);
1223 mWorkerPrivate
->SetServiceWorkerSkipWaitingFlag()
1224 ->Then(GetCurrentSerialEventTarget(), __func__
,
1225 [holder
, promise
](const MozPromiseType::ResolveOrRejectValue
&) {
1227 promise
->MaybeResolveWithUndefined();
1231 return promise
.forget();
1234 SafeRefPtr
<extensions::ExtensionBrowser
>
1235 ServiceWorkerGlobalScope::AcquireExtensionBrowser() {
1236 if (!mExtensionBrowser
) {
1237 mExtensionBrowser
= MakeSafeRefPtr
<extensions::ExtensionBrowser
>(this);
1240 return mExtensionBrowser
.clonePtr();
1243 bool WorkerDebuggerGlobalScope::WrapGlobalObject(
1244 JSContext
* aCx
, JS::MutableHandle
<JSObject
*> aReflector
) {
1245 AssertIsOnWorkerThread();
1247 JS::RealmOptions options
;
1248 mWorkerPrivate
->CopyJSRealmOptions(options
);
1250 return WorkerDebuggerGlobalScope_Binding::Wrap(
1251 aCx
, this, this, options
,
1252 nsJSPrincipals::get(mWorkerPrivate
->GetPrincipal()), aReflector
);
1255 void WorkerDebuggerGlobalScope::GetGlobal(JSContext
* aCx
,
1256 JS::MutableHandle
<JSObject
*> aGlobal
,
1258 WorkerGlobalScope
* scope
= mWorkerPrivate
->GetOrCreateGlobalScope(aCx
);
1260 aRv
.Throw(NS_ERROR_FAILURE
);
1264 aGlobal
.set(scope
->GetWrapper());
1267 void WorkerDebuggerGlobalScope::CreateSandbox(
1268 JSContext
* aCx
, const nsAString
& aName
, JS::Handle
<JSObject
*> aPrototype
,
1269 JS::MutableHandle
<JSObject
*> aResult
, ErrorResult
& aRv
) {
1270 AssertIsOnWorkerThread();
1272 aResult
.set(nullptr);
1274 JS::Rooted
<JS::Value
> protoVal(aCx
);
1275 protoVal
.setObjectOrNull(aPrototype
);
1276 JS::Rooted
<JSObject
*> sandbox(
1278 SimpleGlobalObject::Create(
1279 SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox
, protoVal
));
1282 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
1286 if (!JS_WrapObject(aCx
, &sandbox
)) {
1287 aRv
.NoteJSContextException(aCx
);
1291 aResult
.set(sandbox
);
1294 void WorkerDebuggerGlobalScope::LoadSubScript(
1295 JSContext
* aCx
, const nsAString
& aURL
,
1296 const Optional
<JS::Handle
<JSObject
*>>& aSandbox
, ErrorResult
& aRv
) {
1297 AssertIsOnWorkerThread();
1299 Maybe
<JSAutoRealm
> ar
;
1300 if (aSandbox
.WasPassed()) {
1301 // We only care about worker debugger sandbox objects here, so
1302 // CheckedUnwrapStatic is fine.
1303 JS::Rooted
<JSObject
*> sandbox(aCx
,
1304 js::CheckedUnwrapStatic(aSandbox
.Value()));
1305 if (!sandbox
|| !IsWorkerDebuggerSandbox(sandbox
)) {
1306 aRv
.Throw(NS_ERROR_INVALID_ARG
);
1310 ar
.emplace(aCx
, sandbox
);
1313 nsTArray
<nsString
> urls
;
1314 urls
.AppendElement(aURL
);
1315 workerinternals::Load(mWorkerPrivate
, nullptr, urls
, DebuggerScript
, aRv
);
1318 void WorkerDebuggerGlobalScope::EnterEventLoop() {
1319 // We're on the worker thread here, and WorkerPrivate's refcounting is
1320 // non-threadsafe: you can only do it on the parent thread. What that
1321 // means in practice is that we're relying on it being kept alive while
1322 // we run. Hopefully.
1323 MOZ_KnownLive(mWorkerPrivate
)->EnterDebuggerEventLoop();
1326 void WorkerDebuggerGlobalScope::LeaveEventLoop() {
1327 mWorkerPrivate
->LeaveDebuggerEventLoop();
1330 void WorkerDebuggerGlobalScope::PostMessage(const nsAString
& aMessage
) {
1331 mWorkerPrivate
->PostMessageToDebugger(aMessage
);
1334 void WorkerDebuggerGlobalScope::SetImmediate(Function
& aHandler
,
1336 mWorkerPrivate
->SetDebuggerImmediate(aHandler
, aRv
);
1339 void WorkerDebuggerGlobalScope::ReportError(JSContext
* aCx
,
1340 const nsAString
& aMessage
) {
1341 JS::AutoFilename chars
;
1342 uint32_t lineno
= 0;
1343 JS::DescribeScriptedCaller(aCx
, &chars
, &lineno
);
1344 nsString
filename(NS_ConvertUTF8toUTF16(chars
.get()));
1345 mWorkerPrivate
->ReportErrorToDebugger(filename
, lineno
, aMessage
);
1348 void WorkerDebuggerGlobalScope::RetrieveConsoleEvents(
1349 JSContext
* aCx
, nsTArray
<JS::Value
>& aEvents
, ErrorResult
& aRv
) {
1350 WorkerGlobalScope
* scope
= mWorkerPrivate
->GetOrCreateGlobalScope(aCx
);
1352 aRv
.Throw(NS_ERROR_FAILURE
);
1356 RefPtr
<Console
> console
= scope
->GetConsole(aRv
);
1357 if (NS_WARN_IF(aRv
.Failed())) {
1361 console
->RetrieveConsoleEvents(aCx
, aEvents
, aRv
);
1364 void WorkerDebuggerGlobalScope::ClearConsoleEvents(JSContext
* aCx
,
1366 WorkerGlobalScope
* scope
= mWorkerPrivate
->GetOrCreateGlobalScope(aCx
);
1368 aRv
.Throw(NS_ERROR_FAILURE
);
1372 RefPtr
<Console
> console
= scope
->GetConsoleIfExists();
1374 console
->ClearStorage();
1378 void WorkerDebuggerGlobalScope::SetConsoleEventHandler(JSContext
* aCx
,
1379 AnyCallback
* aHandler
,
1381 WorkerGlobalScope
* scope
= mWorkerPrivate
->GetOrCreateGlobalScope(aCx
);
1383 aRv
.Throw(NS_ERROR_FAILURE
);
1387 RefPtr
<Console
> console
= scope
->GetConsole(aRv
);
1388 if (NS_WARN_IF(aRv
.Failed())) {
1392 console
->SetConsoleEventHandler(aHandler
);
1395 void WorkerDebuggerGlobalScope::Dump(JSContext
* aCx
,
1396 const Optional
<nsAString
>& aString
) const {
1397 WorkerGlobalScope
* scope
= mWorkerPrivate
->GetOrCreateGlobalScope(aCx
);
1399 scope
->Dump(aString
);
1403 bool IsWorkerGlobal(JSObject
* object
) {
1404 return IS_INSTANCE_OF(WorkerGlobalScope
, object
);
1407 bool IsWorkerDebuggerGlobal(JSObject
* object
) {
1408 return IS_INSTANCE_OF(WorkerDebuggerGlobalScope
, object
);
1411 bool IsWorkerDebuggerSandbox(JSObject
* object
) {
1412 return SimpleGlobalObject::SimpleGlobalType(object
) ==
1413 SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox
;
1416 } // namespace mozilla::dom