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/dom/ReferrerInfo.h"
13 namespace mozilla::dom
{
17 class WrappedControlRunnable final
: public WorkerControlRunnable
{
18 nsCOMPtr
<nsIRunnable
> mInner
;
20 ~WrappedControlRunnable() = default;
23 WrappedControlRunnable(WorkerPrivate
* aWorkerPrivate
,
24 nsCOMPtr
<nsIRunnable
>&& aInner
)
25 : WorkerControlRunnable(aWorkerPrivate
, WorkerThreadUnchangedBusyCount
),
26 mInner(std::move(aInner
)) {}
28 virtual bool PreDispatch(WorkerPrivate
* aWorkerPrivate
) override
{
29 // Silence bad assertions, this can be dispatched from any thread.
33 virtual void PostDispatch(WorkerPrivate
* aWorkerPrivate
,
34 bool aDispatchResult
) override
{
35 // Silence bad assertions, this can be dispatched from any thread.
38 bool WorkerRun(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
) override
{
43 nsresult
Cancel() override
{
44 nsCOMPtr
<nsICancelableRunnable
> cr
= do_QueryInterface(mInner
);
46 // If the inner runnable is not cancellable, then just do the normal
47 // WorkerControlRunnable thing. This will end up calling Run().
49 WorkerControlRunnable::Cancel();
53 // Otherwise call the inner runnable's Cancel() and treat this like
54 // a WorkerRunnable cancel. We can't call WorkerControlRunnable::Cancel()
55 // in this case since that would result in both Run() and the inner
56 // Cancel() being called.
57 Unused
<< cr
->Cancel();
58 return WorkerRunnable::Cancel();
62 } // anonymous namespace
64 NS_IMPL_ISUPPORTS(WorkerEventTarget
, nsIEventTarget
, nsISerialEventTarget
)
66 WorkerEventTarget::WorkerEventTarget(WorkerPrivate
* aWorkerPrivate
,
68 : mMutex("WorkerEventTarget"),
69 mWorkerPrivate(aWorkerPrivate
),
70 mBehavior(aBehavior
) {
71 MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate
);
74 void WorkerEventTarget::ForgetWorkerPrivate(WorkerPrivate
* aWorkerPrivate
) {
75 MutexAutoLock
lock(mMutex
);
76 MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate
|| mWorkerPrivate
== aWorkerPrivate
);
77 mWorkerPrivate
= nullptr;
81 WorkerEventTarget::DispatchFromScript(nsIRunnable
* aRunnable
, uint32_t aFlags
) {
82 nsCOMPtr
<nsIRunnable
> runnable(aRunnable
);
83 return Dispatch(runnable
.forget(), aFlags
);
87 WorkerEventTarget::Dispatch(already_AddRefed
<nsIRunnable
> aRunnable
,
89 nsCOMPtr
<nsIRunnable
> runnable(aRunnable
);
91 MutexAutoLock
lock(mMutex
);
93 if (!mWorkerPrivate
) {
94 return NS_ERROR_FAILURE
;
97 if (mBehavior
== Behavior::Hybrid
) {
98 RefPtr
<WorkerRunnable
> r
=
99 mWorkerPrivate
->MaybeWrapAsWorkerRunnable(runnable
.forget());
104 runnable
= std::move(r
);
107 RefPtr
<WorkerControlRunnable
> r
=
108 new WrappedControlRunnable(mWorkerPrivate
, std::move(runnable
));
109 if (!r
->Dispatch()) {
110 return NS_ERROR_FAILURE
;
117 WorkerEventTarget::DelayedDispatch(already_AddRefed
<nsIRunnable
>, uint32_t) {
118 return NS_ERROR_NOT_IMPLEMENTED
;
122 WorkerEventTarget::RegisterShutdownTask(nsITargetShutdownTask
*) {
123 return NS_ERROR_NOT_IMPLEMENTED
;
127 WorkerEventTarget::UnregisterShutdownTask(nsITargetShutdownTask
*) {
128 return NS_ERROR_NOT_IMPLEMENTED
;
132 WorkerEventTarget::IsOnCurrentThreadInfallible() {
133 MutexAutoLock
lock(mMutex
);
135 if (!mWorkerPrivate
) {
139 return mWorkerPrivate
->IsOnCurrentThread();
143 WorkerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread
) {
144 MOZ_ASSERT(aIsOnCurrentThread
);
145 *aIsOnCurrentThread
= IsOnCurrentThreadInfallible();
149 } // namespace mozilla::dom