Bug 1795723 - Unified extensions UI should support High Contrast Mode. r=ayeddi,deskt...
[gecko.git] / dom / workers / WorkerRef.cpp
blob9fcf329495b7a6f5e44ec6e1df872c07c6042c44
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/WorkerRef.h"
9 #include "nsDebug.h"
10 #include "WorkerRunnable.h"
11 #include "WorkerPrivate.h"
13 namespace mozilla::dom {
15 namespace {
17 // This runnable is used to release the StrongWorkerRef on the worker thread
18 // when a ThreadSafeWorkerRef is released.
19 class ReleaseRefControlRunnable final : public WorkerControlRunnable {
20 public:
21 ReleaseRefControlRunnable(WorkerPrivate* aWorkerPrivate,
22 already_AddRefed<StrongWorkerRef> aRef)
23 : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
24 mRef(std::move(aRef)) {
25 MOZ_ASSERT(mRef);
28 bool PreDispatch(WorkerPrivate* aWorkerPrivate) override { return true; }
30 void PostDispatch(WorkerPrivate* aWorkerPrivate,
31 bool aDispatchResult) override {}
33 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
34 mRef = nullptr;
35 return true;
38 private:
39 RefPtr<StrongWorkerRef> mRef;
42 } // namespace
44 // ----------------------------------------------------------------------------
45 // WorkerRef
47 WorkerRef::WorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName,
48 bool aIsPreventingShutdown)
49 : mWorkerPrivate(aWorkerPrivate),
50 mName(aName),
51 mIsPreventingShutdown(aIsPreventingShutdown),
52 mHolding(false) {
53 MOZ_ASSERT(aWorkerPrivate);
54 MOZ_ASSERT(aName);
56 aWorkerPrivate->AssertIsOnWorkerThread();
59 WorkerRef::~WorkerRef() {
60 NS_ASSERT_OWNINGTHREAD(WorkerRef);
61 ReleaseWorker();
64 void WorkerRef::ReleaseWorker() {
65 if (mHolding) {
66 MOZ_ASSERT(mWorkerPrivate);
68 mWorkerPrivate->RemoveWorkerRef(this);
69 mWorkerPrivate = nullptr;
71 mHolding = false;
75 bool WorkerRef::HoldWorker(WorkerStatus aStatus) {
76 MOZ_ASSERT(mWorkerPrivate);
77 MOZ_ASSERT(!mHolding);
79 if (NS_WARN_IF(!mWorkerPrivate->AddWorkerRef(this, aStatus))) {
80 return false;
83 mHolding = true;
84 return true;
87 void WorkerRef::Notify() {
88 NS_ASSERT_OWNINGTHREAD(WorkerRef);
90 if (!mCallback) {
91 return;
94 MoveOnlyFunction<void()> callback = std::move(mCallback);
95 MOZ_ASSERT(!mCallback);
97 callback();
100 // ----------------------------------------------------------------------------
101 // WeakWorkerRef
103 /* static */
104 already_AddRefed<WeakWorkerRef> WeakWorkerRef::Create(
105 WorkerPrivate* aWorkerPrivate, MoveOnlyFunction<void()>&& aCallback) {
106 MOZ_ASSERT(aWorkerPrivate);
107 aWorkerPrivate->AssertIsOnWorkerThread();
109 RefPtr<WeakWorkerRef> ref = new WeakWorkerRef(aWorkerPrivate);
110 if (!ref->HoldWorker(Canceling)) {
111 return nullptr;
114 ref->mCallback = std::move(aCallback);
116 return ref.forget();
119 WeakWorkerRef::WeakWorkerRef(WorkerPrivate* aWorkerPrivate)
120 : WorkerRef(aWorkerPrivate, "WeakWorkerRef", false) {}
122 WeakWorkerRef::~WeakWorkerRef() = default;
124 void WeakWorkerRef::Notify() {
125 MOZ_ASSERT(mHolding);
126 MOZ_ASSERT(mWorkerPrivate);
128 // Notify could drop the last reference to this object. We must keep it alive
129 // in order to call ReleaseWorker() immediately after.
130 RefPtr<WeakWorkerRef> kungFuGrip = this;
132 WorkerRef::Notify();
133 ReleaseWorker();
136 WorkerPrivate* WeakWorkerRef::GetPrivate() const {
137 NS_ASSERT_OWNINGTHREAD(WeakWorkerRef);
138 return mWorkerPrivate;
141 WorkerPrivate* WeakWorkerRef::GetUnsafePrivate() const {
142 return mWorkerPrivate;
145 // ----------------------------------------------------------------------------
146 // StrongWorkerRef
148 /* static */
149 already_AddRefed<StrongWorkerRef> StrongWorkerRef::Create(
150 WorkerPrivate* const aWorkerPrivate, const char* const aName,
151 MoveOnlyFunction<void()>&& aCallback) {
152 if (RefPtr<StrongWorkerRef> ref =
153 CreateImpl(aWorkerPrivate, aName, Canceling)) {
154 ref->mCallback = std::move(aCallback);
155 return ref.forget();
157 return nullptr;
160 /* static */
161 already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateForcibly(
162 WorkerPrivate* const aWorkerPrivate, const char* const aName) {
163 return CreateImpl(aWorkerPrivate, aName, Killing);
166 /* static */
167 already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateImpl(
168 WorkerPrivate* const aWorkerPrivate, const char* const aName,
169 WorkerStatus const aFailStatus) {
170 MOZ_ASSERT(aWorkerPrivate);
171 MOZ_ASSERT(aName);
173 RefPtr<StrongWorkerRef> ref = new StrongWorkerRef(aWorkerPrivate, aName);
174 if (!ref->HoldWorker(aFailStatus)) {
175 return nullptr;
178 return ref.forget();
181 StrongWorkerRef::StrongWorkerRef(WorkerPrivate* aWorkerPrivate,
182 const char* aName)
183 : WorkerRef(aWorkerPrivate, aName, true) {}
185 StrongWorkerRef::~StrongWorkerRef() = default;
187 WorkerPrivate* StrongWorkerRef::Private() const {
188 NS_ASSERT_OWNINGTHREAD(StrongWorkerRef);
189 return mWorkerPrivate;
192 // ----------------------------------------------------------------------------
193 // ThreadSafeWorkerRef
195 ThreadSafeWorkerRef::ThreadSafeWorkerRef(StrongWorkerRef* aRef) : mRef(aRef) {
196 MOZ_ASSERT(aRef);
197 aRef->Private()->AssertIsOnWorkerThread();
200 ThreadSafeWorkerRef::~ThreadSafeWorkerRef() {
201 // Let's release the StrongWorkerRef on the correct thread.
202 if (!mRef->mWorkerPrivate->IsOnWorkerThread()) {
203 WorkerPrivate* workerPrivate = mRef->mWorkerPrivate;
204 RefPtr<ReleaseRefControlRunnable> r =
205 new ReleaseRefControlRunnable(workerPrivate, mRef.forget());
206 r->Dispatch();
207 return;
211 WorkerPrivate* ThreadSafeWorkerRef::Private() const {
212 return mRef->mWorkerPrivate;
215 // ----------------------------------------------------------------------------
216 // IPCWorkerRef
218 /* static */
219 already_AddRefed<IPCWorkerRef> IPCWorkerRef::Create(
220 WorkerPrivate* aWorkerPrivate, const char* aName,
221 MoveOnlyFunction<void()>&& aCallback) {
222 MOZ_ASSERT(aWorkerPrivate);
223 aWorkerPrivate->AssertIsOnWorkerThread();
225 RefPtr<IPCWorkerRef> ref = new IPCWorkerRef(aWorkerPrivate, aName);
226 if (!ref->HoldWorker(Canceling)) {
227 return nullptr;
230 ref->mCallback = std::move(aCallback);
232 return ref.forget();
235 IPCWorkerRef::IPCWorkerRef(WorkerPrivate* aWorkerPrivate, const char* aName)
236 : WorkerRef(aWorkerPrivate, aName, false) {}
238 IPCWorkerRef::~IPCWorkerRef() = default;
240 WorkerPrivate* IPCWorkerRef::Private() const {
241 NS_ASSERT_OWNINGTHREAD(IPCWorkerRef);
242 return mWorkerPrivate;
245 } // namespace mozilla::dom