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 "WorkerEventTarget.h"
8 #include "WorkerPrivate.h"
9 #include "WorkerRunnable.h"
11 #include "mozilla/Logging.h"
12 #include "mozilla/dom/ReferrerInfo.h"
14 namespace mozilla::dom
{
16 static mozilla::LazyLogModule
sWorkerEventTargetLog("WorkerEventTarget");
24 #define LOG(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Debug, args);
25 #define LOGV(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Verbose, args);
29 class WrappedControlRunnable final
: public WorkerControlRunnable
{
30 nsCOMPtr
<nsIRunnable
> mInner
;
32 ~WrappedControlRunnable() = default;
35 WrappedControlRunnable(WorkerPrivate
* aWorkerPrivate
,
36 nsCOMPtr
<nsIRunnable
>&& aInner
)
37 : WorkerControlRunnable("WrappedControlRunnable"),
38 mInner(std::move(aInner
)) {}
40 virtual bool PreDispatch(WorkerPrivate
* aWorkerPrivate
) override
{
41 // Silence bad assertions, this can be dispatched from any thread.
45 virtual void PostDispatch(WorkerPrivate
* aWorkerPrivate
,
46 bool aDispatchResult
) override
{
47 // Silence bad assertions, this can be dispatched from any thread.
50 bool WorkerRun(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
) override
{
55 nsresult
Cancel() override
{
56 nsCOMPtr
<nsICancelableRunnable
> cr
= do_QueryInterface(mInner
);
58 // If the inner runnable is not cancellable, then just do the normal
59 // WorkerControlRunnable thing. This will end up calling Run().
64 // Otherwise call the inner runnable's Cancel() and treat this like
65 // a WorkerRunnable cancel. We can't call WorkerControlRunnable::Cancel()
66 // in this case since that would result in both Run() and the inner
67 // Cancel() being called.
71 #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
72 NS_IMETHOD
GetName(nsACString
& aName
) override
{
73 aName
.AssignLiteral("WrappedControlRunnable(");
74 if (nsCOMPtr
<nsINamed
> named
= do_QueryInterface(mInner
)) {
75 nsAutoCString containedName
;
76 named
->GetName(containedName
);
77 aName
.Append(containedName
);
79 aName
.AppendLiteral("?");
81 aName
.AppendLiteral(")");
87 } // anonymous namespace
89 NS_IMPL_ISUPPORTS(WorkerEventTarget
, nsIEventTarget
, nsISerialEventTarget
)
91 WorkerEventTarget::WorkerEventTarget(WorkerPrivate
* aWorkerPrivate
,
93 : mMutex("WorkerEventTarget"),
94 mWorkerPrivate(aWorkerPrivate
),
95 mBehavior(aBehavior
) {
96 LOG(("WorkerEventTarget::WorkerEventTarget [%p] aBehavior: %u", this,
98 MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate
);
101 void WorkerEventTarget::ForgetWorkerPrivate(WorkerPrivate
* aWorkerPrivate
) {
102 LOG(("WorkerEventTarget::ForgetWorkerPrivate [%p] aWorkerPrivate: %p", this,
104 MutexAutoLock
lock(mMutex
);
105 MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate
|| mWorkerPrivate
== aWorkerPrivate
);
106 mWorkerPrivate
= nullptr;
110 WorkerEventTarget::DispatchFromScript(nsIRunnable
* aRunnable
, uint32_t aFlags
) {
111 LOGV(("WorkerEventTarget::DispatchFromScript [%p] aRunnable: %p", this,
113 nsCOMPtr
<nsIRunnable
> runnable(aRunnable
);
114 return Dispatch(runnable
.forget(), aFlags
);
118 WorkerEventTarget::Dispatch(already_AddRefed
<nsIRunnable
> aRunnable
,
120 nsCOMPtr
<nsIRunnable
> runnable(aRunnable
);
122 ("WorkerEventTarget::Dispatch [%p] aRunnable: %p", this, runnable
.get()));
124 MutexAutoLock
lock(mMutex
);
126 if (!mWorkerPrivate
) {
127 return NS_ERROR_FAILURE
;
130 if (mBehavior
== Behavior::Hybrid
) {
131 LOGV(("WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p)",
132 this, runnable
.get()));
134 RefPtr
<WorkerRunnable
> r
=
135 mWorkerPrivate
->MaybeWrapAsWorkerRunnable(runnable
.forget());
136 if (r
->Dispatch(mWorkerPrivate
)) {
139 runnable
= std::move(r
);
141 "WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p) fail",
142 this, runnable
.get()));
145 RefPtr
<WorkerControlRunnable
> r
=
146 new WrappedControlRunnable(mWorkerPrivate
, std::move(runnable
));
148 ("WorkerEventTarget::Dispatch [%p] Wrapped runnable as control "
151 if (!r
->Dispatch(mWorkerPrivate
)) {
153 ("WorkerEventTarget::Dispatch [%p] Dispatch as control runnable(%p) "
156 return NS_ERROR_FAILURE
;
163 WorkerEventTarget::DelayedDispatch(already_AddRefed
<nsIRunnable
>, uint32_t) {
164 return NS_ERROR_NOT_IMPLEMENTED
;
168 WorkerEventTarget::RegisterShutdownTask(nsITargetShutdownTask
* aTask
) {
169 NS_ENSURE_ARG(aTask
);
171 MutexAutoLock
lock(mMutex
);
173 // If mWorkerPrivate is gone, the event target is already late during
174 // shutdown, return NS_ERROR_UNEXPECTED as documented in `nsIEventTarget.idl`.
175 if (!mWorkerPrivate
) {
176 return NS_ERROR_UNEXPECTED
;
179 return mWorkerPrivate
->RegisterShutdownTask(aTask
);
183 WorkerEventTarget::UnregisterShutdownTask(nsITargetShutdownTask
* aTask
) {
184 NS_ENSURE_ARG(aTask
);
186 MutexAutoLock
lock(mMutex
);
188 if (!mWorkerPrivate
) {
189 return NS_ERROR_UNEXPECTED
;
192 return mWorkerPrivate
->UnregisterShutdownTask(aTask
);
196 WorkerEventTarget::IsOnCurrentThreadInfallible() {
197 MutexAutoLock
lock(mMutex
);
199 if (!mWorkerPrivate
) {
203 return mWorkerPrivate
->IsOnCurrentThread();
207 WorkerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread
) {
208 MOZ_ASSERT(aIsOnCurrentThread
);
209 *aIsOnCurrentThread
= IsOnCurrentThreadInfallible();
213 } // namespace mozilla::dom