Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/serviceworkers/ServiceWorkerInfo.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 "ServiceWorkerInfo.h"
8
9
#include "ServiceWorkerScriptCache.h"
10
11
namespace mozilla {
12
namespace dom {
13
14
using mozilla::ipc::PrincipalInfo;
15
16
static_assert(nsIServiceWorkerInfo::STATE_PARSED == static_cast<uint16_t>(ServiceWorkerState::Parsed),
17
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
18
static_assert(nsIServiceWorkerInfo::STATE_INSTALLING == static_cast<uint16_t>(ServiceWorkerState::Installing),
19
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
20
static_assert(nsIServiceWorkerInfo::STATE_INSTALLED == static_cast<uint16_t>(ServiceWorkerState::Installed),
21
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
22
static_assert(nsIServiceWorkerInfo::STATE_ACTIVATING == static_cast<uint16_t>(ServiceWorkerState::Activating),
23
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
24
static_assert(nsIServiceWorkerInfo::STATE_ACTIVATED == static_cast<uint16_t>(ServiceWorkerState::Activated),
25
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
26
static_assert(nsIServiceWorkerInfo::STATE_REDUNDANT == static_cast<uint16_t>(ServiceWorkerState::Redundant),
27
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
28
static_assert(nsIServiceWorkerInfo::STATE_UNKNOWN == static_cast<uint16_t>(ServiceWorkerState::EndGuard_),
29
              "ServiceWorkerState enumeration value should match state values from nsIServiceWorkerInfo.");
30
31
NS_IMPL_ISUPPORTS(ServiceWorkerInfo, nsIServiceWorkerInfo)
32
33
NS_IMETHODIMP
34
ServiceWorkerInfo::GetScriptSpec(nsAString& aScriptSpec)
35
0
{
36
0
  MOZ_ASSERT(NS_IsMainThread());
37
0
  CopyUTF8toUTF16(mDescriptor.ScriptURL(), aScriptSpec);
38
0
  return NS_OK;
39
0
}
40
41
NS_IMETHODIMP
42
ServiceWorkerInfo::GetCacheName(nsAString& aCacheName)
43
0
{
44
0
  MOZ_ASSERT(NS_IsMainThread());
45
0
  aCacheName = mCacheName;
46
0
  return NS_OK;
47
0
}
48
49
NS_IMETHODIMP
50
ServiceWorkerInfo::GetState(uint16_t* aState)
51
0
{
52
0
  MOZ_ASSERT(aState);
53
0
  MOZ_ASSERT(NS_IsMainThread());
54
0
  *aState = static_cast<uint16_t>(State());
55
0
  return NS_OK;
56
0
}
57
58
NS_IMETHODIMP
59
ServiceWorkerInfo::GetDebugger(nsIWorkerDebugger** aResult)
60
0
{
61
0
  if (NS_WARN_IF(!aResult)) {
62
0
    return NS_ERROR_FAILURE;
63
0
  }
64
0
65
0
  return mServiceWorkerPrivate->GetDebugger(aResult);
66
0
}
67
68
NS_IMETHODIMP
69
ServiceWorkerInfo::GetHandlesFetchEvents(bool* aValue)
70
0
{
71
0
  MOZ_ASSERT(aValue);
72
0
  MOZ_ASSERT(NS_IsMainThread());
73
0
  *aValue = HandlesFetch();
74
0
  return NS_OK;
75
0
}
76
77
NS_IMETHODIMP
78
ServiceWorkerInfo::GetInstalledTime(PRTime* _retval)
79
0
{
80
0
  MOZ_ASSERT(NS_IsMainThread());
81
0
  MOZ_ASSERT(_retval);
82
0
  *_retval = mInstalledTime;
83
0
  return NS_OK;
84
0
}
85
86
NS_IMETHODIMP
87
ServiceWorkerInfo::GetActivatedTime(PRTime* _retval)
88
0
{
89
0
  MOZ_ASSERT(NS_IsMainThread());
90
0
  MOZ_ASSERT(_retval);
91
0
  *_retval = mActivatedTime;
92
0
  return NS_OK;
93
0
}
94
95
NS_IMETHODIMP
96
ServiceWorkerInfo::GetRedundantTime(PRTime* _retval)
97
0
{
98
0
  MOZ_ASSERT(NS_IsMainThread());
99
0
  MOZ_ASSERT(_retval);
100
0
  *_retval = mRedundantTime;
101
0
  return NS_OK;
102
0
}
103
104
NS_IMETHODIMP
105
ServiceWorkerInfo::AttachDebugger()
106
0
{
107
0
  return mServiceWorkerPrivate->AttachDebugger();
108
0
}
109
110
NS_IMETHODIMP
111
ServiceWorkerInfo::DetachDebugger()
112
0
{
113
0
  return mServiceWorkerPrivate->DetachDebugger();
114
0
}
115
116
void
117
ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
118
0
{
119
0
  MOZ_ASSERT(NS_IsMainThread());
120
#ifdef DEBUG
121
  // Any state can directly transition to redundant, but everything else is
122
  // ordered.
123
  if (aState != ServiceWorkerState::Redundant) {
124
    MOZ_ASSERT_IF(State() == ServiceWorkerState::EndGuard_,
125
                  aState == ServiceWorkerState::Installing);
126
    MOZ_ASSERT_IF(State() == ServiceWorkerState::Installing,
127
                  aState == ServiceWorkerState::Installed);
128
    MOZ_ASSERT_IF(State() == ServiceWorkerState::Installed,
129
                  aState == ServiceWorkerState::Activating);
130
    MOZ_ASSERT_IF(State() == ServiceWorkerState::Activating,
131
                  aState == ServiceWorkerState::Activated);
132
  }
133
  // Activated can only go to redundant.
134
  MOZ_ASSERT_IF(State() == ServiceWorkerState::Activated,
135
                aState == ServiceWorkerState::Redundant);
136
#endif
137
  // Flush any pending functional events to the worker when it transitions to the
138
0
  // activated state.
139
0
  // TODO: Do we care that these events will race with the propagation of the
140
0
  //       state change?
141
0
  if (State() != aState) {
142
0
    mServiceWorkerPrivate->UpdateState(aState);
143
0
  }
144
0
  mDescriptor.SetState(aState);
145
0
  if (State() == ServiceWorkerState::Redundant) {
146
0
    serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName);
147
0
  }
148
0
}
149
150
ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
151
                                     const nsACString& aScope,
152
                                     uint64_t aRegistrationId,
153
                                     uint64_t aRegistrationVersion,
154
                                     const nsACString& aScriptSpec,
155
                                     const nsAString& aCacheName,
156
                                     nsLoadFlags aImportsLoadFlags)
157
  : mPrincipal(aPrincipal)
158
  , mDescriptor(GetNextID(), aRegistrationId, aRegistrationVersion, aPrincipal,
159
                aScope, aScriptSpec, ServiceWorkerState::Parsed)
160
  , mCacheName(aCacheName)
161
  , mImportsLoadFlags(aImportsLoadFlags)
162
  , mCreationTime(PR_Now())
163
  , mCreationTimeStamp(TimeStamp::Now())
164
  , mInstalledTime(0)
165
  , mActivatedTime(0)
166
  , mRedundantTime(0)
167
  , mServiceWorkerPrivate(new ServiceWorkerPrivate(this))
168
  , mSkipWaitingFlag(false)
169
  , mHandlesFetch(Unknown)
170
0
{
171
0
  MOZ_ASSERT_IF(ServiceWorkerParentInterceptEnabled(),
172
0
                XRE_GetProcessType() == GeckoProcessType_Default);
173
0
  MOZ_ASSERT(mPrincipal);
174
0
  // cache origin attributes so we can use them off main thread
175
0
  mOriginAttributes = mPrincipal->OriginAttributesRef();
176
0
  MOZ_ASSERT(!mDescriptor.ScriptURL().IsEmpty());
177
0
  MOZ_ASSERT(!mCacheName.IsEmpty());
178
0
179
0
  // Scripts of a service worker should always be loaded bypass service workers.
180
0
  // Otherwise, we might not be able to update a service worker correctly, if
181
0
  // there is a service worker generating the script.
182
0
  MOZ_DIAGNOSTIC_ASSERT(mImportsLoadFlags & nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
183
0
}
184
185
ServiceWorkerInfo::~ServiceWorkerInfo()
186
0
{
187
0
  MOZ_ASSERT(mServiceWorkerPrivate);
188
0
  mServiceWorkerPrivate->NoteDeadServiceWorkerInfo();
189
0
}
190
191
static uint64_t gServiceWorkerInfoCurrentID = 0;
192
193
uint64_t
194
ServiceWorkerInfo::GetNextID() const
195
0
{
196
0
  return ++gServiceWorkerInfoCurrentID;
197
0
}
198
199
void
200
ServiceWorkerInfo::PostMessage(RefPtr<ServiceWorkerCloneData>&& aData,
201
                               const ClientInfo& aClientInfo,
202
                               const ClientState& aClientState)
203
0
{
204
0
  mServiceWorkerPrivate->SendMessageEvent(std::move(aData),
205
0
                                          ClientInfoAndState(aClientInfo.ToIPC(),
206
0
                                                             aClientState.ToIPC()));
207
0
}
208
209
void
210
ServiceWorkerInfo::UpdateInstalledTime()
211
0
{
212
0
  MOZ_ASSERT(State() == ServiceWorkerState::Installed);
213
0
  MOZ_ASSERT(mInstalledTime == 0);
214
0
215
0
  mInstalledTime =
216
0
    mCreationTime + static_cast<PRTime>((TimeStamp::Now() -
217
0
                                         mCreationTimeStamp).ToMicroseconds());
218
0
}
219
220
void
221
ServiceWorkerInfo::UpdateActivatedTime()
222
0
{
223
0
  MOZ_ASSERT(State() == ServiceWorkerState::Activated);
224
0
  MOZ_ASSERT(mActivatedTime == 0);
225
0
226
0
  mActivatedTime =
227
0
    mCreationTime + static_cast<PRTime>((TimeStamp::Now() -
228
0
                                         mCreationTimeStamp).ToMicroseconds());
229
0
}
230
231
void
232
ServiceWorkerInfo::UpdateRedundantTime()
233
0
{
234
0
  MOZ_ASSERT(State() == ServiceWorkerState::Redundant);
235
0
  MOZ_ASSERT(mRedundantTime == 0);
236
0
237
0
  mRedundantTime =
238
0
    mCreationTime + static_cast<PRTime>((TimeStamp::Now() -
239
0
                                         mCreationTimeStamp).ToMicroseconds());
240
0
}
241
242
void
243
ServiceWorkerInfo::SetRegistrationVersion(uint64_t aVersion)
244
0
{
245
0
  mDescriptor.SetRegistrationVersion(aVersion);
246
0
}
247
248
} // namespace dom
249
} // namespace mozilla