Source code

Revision control

Other Tools

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