Coverage Report

Created: 2018-09-25 14:53

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