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 "ServiceWorkerJobQueue.h"
9 #include "nsThreadUtils.h"
10 #include "ServiceWorkerJob.h"
11 #include "mozilla/dom/WorkerCommon.h"
13 namespace mozilla::dom
{
15 class ServiceWorkerJobQueue::Callback final
16 : public ServiceWorkerJob::Callback
{
17 RefPtr
<ServiceWorkerJobQueue
> mQueue
;
19 ~Callback() = default;
22 explicit Callback(ServiceWorkerJobQueue
* aQueue
) : mQueue(aQueue
) {
23 MOZ_ASSERT(NS_IsMainThread());
27 virtual void JobFinished(ServiceWorkerJob
* aJob
,
28 ErrorResult
& aStatus
) override
{
29 MOZ_ASSERT(NS_IsMainThread());
30 mQueue
->JobFinished(aJob
);
33 virtual void JobDiscarded(ErrorResult
&) override
{
34 // no-op; nothing to do.
37 NS_INLINE_DECL_REFCOUNTING(ServiceWorkerJobQueue::Callback
, override
)
40 ServiceWorkerJobQueue::~ServiceWorkerJobQueue() {
41 MOZ_ASSERT(NS_IsMainThread());
42 MOZ_ASSERT(mJobList
.IsEmpty());
45 void ServiceWorkerJobQueue::JobFinished(ServiceWorkerJob
* aJob
) {
46 MOZ_ASSERT(NS_IsMainThread());
49 // XXX There are some corner cases where jobs can double-complete. Until
50 // we track all these down we do a non-fatal assert in debug builds and
51 // a runtime check to verify the queue is in the correct state.
52 NS_ASSERTION(!mJobList
.IsEmpty(),
53 "Job queue should contain the job that just completed.");
54 NS_ASSERTION(mJobList
.SafeElementAt(0, nullptr) == aJob
,
55 "Job queue should contain the job that just completed.");
56 if (NS_WARN_IF(mJobList
.SafeElementAt(0, nullptr) != aJob
)) {
60 mJobList
.RemoveElementAt(0);
62 if (mJobList
.IsEmpty()) {
69 void ServiceWorkerJobQueue::RunJob() {
70 MOZ_ASSERT(NS_IsMainThread());
71 MOZ_ASSERT(!mJobList
.IsEmpty());
72 MOZ_ASSERT(mJobList
[0]->GetState() == ServiceWorkerJob::State::Initial
);
74 RefPtr
<Callback
> callback
= new Callback(this);
75 mJobList
[0]->Start(callback
);
78 ServiceWorkerJobQueue::ServiceWorkerJobQueue() {
79 MOZ_ASSERT(NS_IsMainThread());
82 void ServiceWorkerJobQueue::ScheduleJob(ServiceWorkerJob
* aJob
) {
83 MOZ_ASSERT(NS_IsMainThread());
85 MOZ_ASSERT(!mJobList
.Contains(aJob
));
87 if (mJobList
.IsEmpty()) {
88 mJobList
.AppendElement(aJob
);
93 MOZ_ASSERT(mJobList
[0]->GetState() == ServiceWorkerJob::State::Started
);
95 RefPtr
<ServiceWorkerJob
>& tailJob
= mJobList
[mJobList
.Length() - 1];
96 if (!tailJob
->ResultCallbacksInvoked() && aJob
->IsEquivalentTo(tailJob
)) {
97 tailJob
->StealResultCallbacksFrom(aJob
);
101 mJobList
.AppendElement(aJob
);
104 void ServiceWorkerJobQueue::CancelAll() {
105 MOZ_ASSERT(NS_IsMainThread());
107 for (RefPtr
<ServiceWorkerJob
>& job
: mJobList
) {
111 // Remove jobs that are queued but not started since they should never
112 // run after being canceled. This means throwing away all jobs except
113 // for the job at the front of the list.
114 if (!mJobList
.IsEmpty()) {
115 MOZ_ASSERT(mJobList
[0]->GetState() == ServiceWorkerJob::State::Started
);
116 mJobList
.TruncateLength(1);
120 } // namespace mozilla::dom