Line data Source code
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/. */
6 :
7 : #include "ServiceWorkerJobQueue.h"
8 :
9 : #include "ServiceWorkerJob.h"
10 : #include "Workers.h"
11 :
12 : namespace mozilla {
13 : namespace dom {
14 : namespace workers {
15 :
16 : class ServiceWorkerJobQueue::Callback final : public ServiceWorkerJob::Callback
17 : {
18 : RefPtr<ServiceWorkerJobQueue> mQueue;
19 :
20 0 : ~Callback()
21 0 : {
22 0 : }
23 :
24 : public:
25 0 : explicit Callback(ServiceWorkerJobQueue* aQueue)
26 0 : : mQueue(aQueue)
27 : {
28 0 : AssertIsOnMainThread();
29 0 : MOZ_ASSERT(mQueue);
30 0 : }
31 :
32 : virtual void
33 0 : JobFinished(ServiceWorkerJob* aJob, ErrorResult& aStatus) override
34 : {
35 0 : AssertIsOnMainThread();
36 0 : mQueue->JobFinished(aJob);
37 0 : }
38 :
39 0 : NS_INLINE_DECL_REFCOUNTING(ServiceWorkerJobQueue::Callback, override)
40 : };
41 :
42 0 : ServiceWorkerJobQueue::~ServiceWorkerJobQueue()
43 : {
44 0 : AssertIsOnMainThread();
45 0 : MOZ_ASSERT(mJobList.IsEmpty());
46 0 : }
47 :
48 : void
49 0 : ServiceWorkerJobQueue::JobFinished(ServiceWorkerJob* aJob)
50 : {
51 0 : AssertIsOnMainThread();
52 0 : MOZ_ASSERT(aJob);
53 :
54 : // XXX There are some corner cases where jobs can double-complete. Until
55 : // we track all these down we do a non-fatal assert in debug builds and
56 : // a runtime check to verify the queue is in the correct state.
57 0 : NS_ASSERTION(!mJobList.IsEmpty(),
58 : "Job queue should contain the job that just completed.");
59 0 : NS_ASSERTION(mJobList.SafeElementAt(0, nullptr) == aJob,
60 : "Job queue should contain the job that just completed.");
61 0 : if (NS_WARN_IF(mJobList.SafeElementAt(0, nullptr) != aJob)) {
62 0 : return;
63 : }
64 :
65 0 : mJobList.RemoveElementAt(0);
66 :
67 0 : if (mJobList.IsEmpty()) {
68 0 : return;
69 : }
70 :
71 0 : RunJob();
72 : }
73 :
74 : void
75 0 : ServiceWorkerJobQueue::RunJob()
76 : {
77 0 : AssertIsOnMainThread();
78 0 : MOZ_ASSERT(!mJobList.IsEmpty());
79 0 : MOZ_ASSERT(mJobList[0]->GetState() == ServiceWorkerJob::State::Initial);
80 :
81 0 : RefPtr<Callback> callback = new Callback(this);
82 0 : mJobList[0]->Start(callback);
83 0 : }
84 :
85 0 : ServiceWorkerJobQueue::ServiceWorkerJobQueue()
86 : {
87 0 : AssertIsOnMainThread();
88 0 : }
89 :
90 : void
91 0 : ServiceWorkerJobQueue::ScheduleJob(ServiceWorkerJob* aJob)
92 : {
93 0 : AssertIsOnMainThread();
94 0 : MOZ_ASSERT(aJob);
95 0 : MOZ_ASSERT(!mJobList.Contains(aJob));
96 :
97 0 : if (mJobList.IsEmpty()) {
98 0 : mJobList.AppendElement(aJob);
99 0 : RunJob();
100 0 : return;
101 : }
102 :
103 0 : MOZ_ASSERT(mJobList[0]->GetState() == ServiceWorkerJob::State::Started);
104 :
105 0 : RefPtr<ServiceWorkerJob>& tailJob = mJobList[mJobList.Length() - 1];
106 0 : if (!tailJob->ResultCallbacksInvoked() && aJob->IsEquivalentTo(tailJob)) {
107 0 : tailJob->StealResultCallbacksFrom(aJob);
108 0 : return;
109 : }
110 :
111 0 : mJobList.AppendElement(aJob);
112 : }
113 :
114 : void
115 0 : ServiceWorkerJobQueue::CancelAll()
116 : {
117 0 : AssertIsOnMainThread();
118 :
119 0 : for (RefPtr<ServiceWorkerJob>& job : mJobList) {
120 0 : job->Cancel();
121 : }
122 :
123 : // Remove jobs that are queued but not started since they should never
124 : // run after being canceled. This means throwing away all jobs except
125 : // for the job at the front of the list.
126 0 : if (!mJobList.IsEmpty()) {
127 0 : MOZ_ASSERT(mJobList[0]->GetState() == ServiceWorkerJob::State::Started);
128 0 : mJobList.TruncateLength(1);
129 : }
130 0 : }
131 :
132 : } // namespace workers
133 : } // namespace dom
134 : } // namespace mozilla
|