/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 |