Backed out changeset 9d8b4c0b99ed (bug 1945683) for causing btime failures. CLOSED...
[gecko.git] / dom / workers / WorkerEventTarget.cpp
blobfab73b4ff7d8d059e10f6d2d862e7efdb587e68f
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");
18 #ifdef LOG
19 # undef LOG
20 #endif
21 #ifdef LOGV
22 # undef LOGV
23 #endif
24 #define LOG(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Debug, args);
25 #define LOGV(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Verbose, args);
27 namespace {
29 class WrappedControlRunnable final : public WorkerControlRunnable {
30 nsCOMPtr<nsIRunnable> mInner;
32 ~WrappedControlRunnable() = default;
34 public:
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.
42 return true;
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 {
51 mInner->Run();
52 return true;
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().
60 if (!cr) {
61 return 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.
68 return cr->Cancel();
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);
78 } else {
79 aName.AppendLiteral("?");
81 aName.AppendLiteral(")");
82 return NS_OK;
84 #endif
87 } // anonymous namespace
89 NS_IMPL_ISUPPORTS(WorkerEventTarget, nsIEventTarget, nsISerialEventTarget)
91 WorkerEventTarget::WorkerEventTarget(WorkerPrivate* aWorkerPrivate,
92 Behavior aBehavior)
93 : mMutex("WorkerEventTarget"),
94 mWorkerPrivate(aWorkerPrivate),
95 mBehavior(aBehavior) {
96 LOG(("WorkerEventTarget::WorkerEventTarget [%p] aBehavior: %u", this,
97 (uint8_t)aBehavior));
98 MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate);
101 void WorkerEventTarget::ForgetWorkerPrivate(WorkerPrivate* aWorkerPrivate) {
102 LOG(("WorkerEventTarget::ForgetWorkerPrivate [%p] aWorkerPrivate: %p", this,
103 aWorkerPrivate));
104 MutexAutoLock lock(mMutex);
105 MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate || mWorkerPrivate == aWorkerPrivate);
106 mWorkerPrivate = nullptr;
109 NS_IMETHODIMP
110 WorkerEventTarget::DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) {
111 LOGV(("WorkerEventTarget::DispatchFromScript [%p] aRunnable: %p", this,
112 aRunnable));
113 nsCOMPtr<nsIRunnable> runnable(aRunnable);
114 return Dispatch(runnable.forget(), aFlags);
117 NS_IMETHODIMP
118 WorkerEventTarget::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
119 uint32_t aFlags) {
120 nsCOMPtr<nsIRunnable> runnable(aRunnable);
121 LOGV(
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)) {
137 return NS_OK;
139 runnable = std::move(r);
140 LOGV((
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));
147 LOGV(
148 ("WorkerEventTarget::Dispatch [%p] Wrapped runnable as control "
149 "runnable(%p)",
150 this, r.get()));
151 if (!r->Dispatch(mWorkerPrivate)) {
152 LOGV(
153 ("WorkerEventTarget::Dispatch [%p] Dispatch as control runnable(%p) "
154 "fail",
155 this, r.get()));
156 return NS_ERROR_FAILURE;
159 return NS_OK;
162 NS_IMETHODIMP
163 WorkerEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) {
164 return NS_ERROR_NOT_IMPLEMENTED;
167 NS_IMETHODIMP
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);
182 NS_IMETHODIMP
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);
195 NS_IMETHODIMP_(bool)
196 WorkerEventTarget::IsOnCurrentThreadInfallible() {
197 MutexAutoLock lock(mMutex);
199 if (!mWorkerPrivate) {
200 return false;
203 return mWorkerPrivate->IsOnCurrentThread();
206 NS_IMETHODIMP
207 WorkerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) {
208 MOZ_ASSERT(aIsOnCurrentThread);
209 *aIsOnCurrentThread = IsOnCurrentThreadInfallible();
210 return NS_OK;
213 } // namespace mozilla::dom