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(aWorkerPrivate
, "WrappedControlRunnable",
39 mInner(std::move(aInner
)) {}
41 virtual bool PreDispatch(WorkerPrivate
* aWorkerPrivate
) override
{
42 // Silence bad assertions, this can be dispatched from any thread.
46 virtual void PostDispatch(WorkerPrivate
* aWorkerPrivate
,
47 bool aDispatchResult
) override
{
48 // Silence bad assertions, this can be dispatched from any thread.
51 bool WorkerRun(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
) override
{
56 nsresult
Cancel() override
{
57 nsCOMPtr
<nsICancelableRunnable
> cr
= do_QueryInterface(mInner
);
59 // If the inner runnable is not cancellable, then just do the normal
60 // WorkerControlRunnable thing. This will end up calling Run().
65 // Otherwise call the inner runnable's Cancel() and treat this like
66 // a WorkerRunnable cancel. We can't call WorkerControlRunnable::Cancel()
67 // in this case since that would result in both Run() and the inner
68 // Cancel() being called.
73 } // anonymous namespace
75 NS_IMPL_ISUPPORTS(WorkerEventTarget
, nsIEventTarget
, nsISerialEventTarget
)
77 WorkerEventTarget::WorkerEventTarget(WorkerPrivate
* aWorkerPrivate
,
79 : mMutex("WorkerEventTarget"),
80 mWorkerPrivate(aWorkerPrivate
),
81 mBehavior(aBehavior
) {
82 LOG(("WorkerEventTarget::WorkerEventTarget [%p] aBehavior: %u", this,
84 MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate
);
87 void WorkerEventTarget::ForgetWorkerPrivate(WorkerPrivate
* aWorkerPrivate
) {
88 LOG(("WorkerEventTarget::ForgetWorkerPrivate [%p] aWorkerPrivate: %p", this,
90 MutexAutoLock
lock(mMutex
);
91 MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate
|| mWorkerPrivate
== aWorkerPrivate
);
92 mWorkerPrivate
= nullptr;
96 WorkerEventTarget::DispatchFromScript(nsIRunnable
* aRunnable
, uint32_t aFlags
) {
97 LOGV(("WorkerEventTarget::DispatchFromScript [%p] aRunnable: %p", this,
99 nsCOMPtr
<nsIRunnable
> runnable(aRunnable
);
100 return Dispatch(runnable
.forget(), aFlags
);
104 WorkerEventTarget::Dispatch(already_AddRefed
<nsIRunnable
> aRunnable
,
106 nsCOMPtr
<nsIRunnable
> runnable(aRunnable
);
108 ("WorkerEventTarget::Dispatch [%p] aRunnable: %p", this, runnable
.get()));
110 MutexAutoLock
lock(mMutex
);
112 if (!mWorkerPrivate
) {
113 return NS_ERROR_FAILURE
;
116 if (mBehavior
== Behavior::Hybrid
) {
117 LOGV(("WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p)",
118 this, runnable
.get()));
120 RefPtr
<WorkerRunnable
> r
=
121 mWorkerPrivate
->MaybeWrapAsWorkerRunnable(runnable
.forget());
125 runnable
= std::move(r
);
127 "WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p) fail",
128 this, runnable
.get()));
131 RefPtr
<WorkerControlRunnable
> r
=
132 new WrappedControlRunnable(mWorkerPrivate
, std::move(runnable
));
134 ("WorkerEventTarget::Dispatch [%p] Wrapped runnable as control "
137 if (!r
->Dispatch()) {
139 ("WorkerEventTarget::Dispatch [%p] Dispatch as control runnable(%p) "
142 return NS_ERROR_FAILURE
;
149 WorkerEventTarget::DelayedDispatch(already_AddRefed
<nsIRunnable
>, uint32_t) {
150 return NS_ERROR_NOT_IMPLEMENTED
;
154 WorkerEventTarget::RegisterShutdownTask(nsITargetShutdownTask
* aTask
) {
155 NS_ENSURE_ARG(aTask
);
157 MutexAutoLock
lock(mMutex
);
159 // If mWorkerPrivate is gone, the event target is already late during
160 // shutdown, return NS_ERROR_UNEXPECTED as documented in `nsIEventTarget.idl`.
161 if (!mWorkerPrivate
) {
162 return NS_ERROR_UNEXPECTED
;
165 return mWorkerPrivate
->RegisterShutdownTask(aTask
);
169 WorkerEventTarget::UnregisterShutdownTask(nsITargetShutdownTask
* aTask
) {
170 NS_ENSURE_ARG(aTask
);
172 MutexAutoLock
lock(mMutex
);
174 if (!mWorkerPrivate
) {
175 return NS_ERROR_UNEXPECTED
;
178 return mWorkerPrivate
->UnregisterShutdownTask(aTask
);
182 WorkerEventTarget::IsOnCurrentThreadInfallible() {
183 MutexAutoLock
lock(mMutex
);
185 if (!mWorkerPrivate
) {
189 return mWorkerPrivate
->IsOnCurrentThread();
193 WorkerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread
) {
194 MOZ_ASSERT(aIsOnCurrentThread
);
195 *aIsOnCurrentThread
= IsOnCurrentThreadInfallible();
199 } // namespace mozilla::dom