OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_register_job.h" | 5 #include "content/browser/service_worker/service_worker_register_job.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "content/browser/service_worker/service_worker_context_core.h" | 10 #include "content/browser/service_worker/service_worker_context_core.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 weak_factory_(this) {} | 38 weak_factory_(this) {} |
39 | 39 |
40 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() { | 40 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() { |
41 DCHECK(phase_ == INITIAL || phase_ == COMPLETE); | 41 DCHECK(phase_ == INITIAL || phase_ == COMPLETE); |
42 } | 42 } |
43 | 43 |
44 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, | 44 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, |
45 int process_id) { | 45 int process_id) { |
46 if (!is_promise_resolved_) { | 46 if (!is_promise_resolved_) { |
47 callbacks_.push_back(callback); | 47 callbacks_.push_back(callback); |
48 if (process_id != -1 && (phase_ < UPDATE || !pending_version())) | 48 if (process_id != -1 && (phase_ < UPDATE || !waiting_version())) |
49 pending_process_ids_.push_back(process_id); | 49 pending_process_ids_.push_back(process_id); |
50 return; | 50 return; |
51 } | 51 } |
52 RunSoon(base::Bind( | 52 RunSoon(base::Bind( |
53 callback, promise_resolved_status_, | 53 callback, promise_resolved_status_, |
54 promise_resolved_registration_, promise_resolved_version_)); | 54 promise_resolved_registration_, promise_resolved_version_)); |
55 } | 55 } |
56 | 56 |
57 void ServiceWorkerRegisterJob::Start() { | 57 void ServiceWorkerRegisterJob::Start() { |
58 SetPhase(START); | 58 SetPhase(START); |
(...skipping 26 matching lines...) Expand all Loading... | |
85 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; | 85 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; |
86 DCHECK(!internal_.registration); | 86 DCHECK(!internal_.registration); |
87 internal_.registration = registration; | 87 internal_.registration = registration; |
88 } | 88 } |
89 | 89 |
90 ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() { | 90 ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() { |
91 DCHECK(phase_ >= REGISTER) << phase_; | 91 DCHECK(phase_ >= REGISTER) << phase_; |
92 return internal_.registration; | 92 return internal_.registration; |
93 } | 93 } |
94 | 94 |
95 void ServiceWorkerRegisterJob::set_pending_version( | 95 void ServiceWorkerRegisterJob::set_waiting_version( |
96 ServiceWorkerVersion* version) { | 96 ServiceWorkerVersion* version) { |
97 DCHECK(phase_ == UPDATE) << phase_; | 97 DCHECK(phase_ == UPDATE) << phase_; |
98 DCHECK(!internal_.pending_version); | 98 DCHECK(!internal_.waiting_version); |
99 internal_.pending_version = version; | 99 internal_.waiting_version = version; |
100 } | 100 } |
101 | 101 |
102 ServiceWorkerVersion* ServiceWorkerRegisterJob::pending_version() { | 102 ServiceWorkerVersion* ServiceWorkerRegisterJob::waiting_version() { |
103 DCHECK(phase_ >= UPDATE) << phase_; | 103 DCHECK(phase_ >= UPDATE) << phase_; |
104 return internal_.pending_version; | 104 return internal_.waiting_version; |
105 } | 105 } |
106 | 106 |
107 void ServiceWorkerRegisterJob::SetPhase(Phase phase) { | 107 void ServiceWorkerRegisterJob::SetPhase(Phase phase) { |
108 switch (phase) { | 108 switch (phase) { |
109 case INITIAL: | 109 case INITIAL: |
110 NOTREACHED(); | 110 NOTREACHED(); |
111 break; | 111 break; |
112 case START: | 112 case START: |
113 DCHECK(phase_ == INITIAL) << phase_; | 113 DCHECK(phase_ == INITIAL) << phase_; |
114 break; | 114 break; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 // "If serviceWorkerRegistration is null..." create a new registration. | 169 // "If serviceWorkerRegistration is null..." create a new registration. |
170 if (!existing_registration.get()) { | 170 if (!existing_registration.get()) { |
171 RegisterAndContinue(SERVICE_WORKER_OK); | 171 RegisterAndContinue(SERVICE_WORKER_OK); |
172 return; | 172 return; |
173 } | 173 } |
174 | 174 |
175 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to | 175 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to |
176 // script." We accomplish this by deleting the existing registration and | 176 // script." We accomplish this by deleting the existing registration and |
177 // registering a new one. | 177 // registering a new one. |
178 // TODO(falken): Match the spec. We now throw away the active_version_ and | 178 // TODO(falken): Match the spec. We now throw away the active_version_ and |
179 // pending_version_ of the existing registration, which isn't in the spec. | 179 // waiting_version_ of the existing registration, which isn't in the spec. |
180 // TODO(michaeln): Deactivate the live existing_registration object and | 180 // TODO(michaeln): Deactivate the live existing_registration object and |
181 // eventually call storage->DeleteVersionResources() | 181 // eventually call storage->DeleteVersionResources() |
182 // when it no longer has any controllees. | 182 // when it no longer has any controllees. |
183 context_->storage()->DeleteRegistration( | 183 context_->storage()->DeleteRegistration( |
184 existing_registration->id(), | 184 existing_registration->id(), |
185 existing_registration->script_url().GetOrigin(), | 185 existing_registration->script_url().GetOrigin(), |
186 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, | 186 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, |
187 weak_factory_.GetWeakPtr())); | 187 weak_factory_.GetWeakPtr())); |
188 } | 188 } |
189 | 189 |
(...skipping 17 matching lines...) Expand all Loading... | |
207 // This function corresponds to the spec's _Update algorithm. | 207 // This function corresponds to the spec's _Update algorithm. |
208 void ServiceWorkerRegisterJob::UpdateAndContinue( | 208 void ServiceWorkerRegisterJob::UpdateAndContinue( |
209 ServiceWorkerStatusCode status) { | 209 ServiceWorkerStatusCode status) { |
210 SetPhase(UPDATE); | 210 SetPhase(UPDATE); |
211 if (status != SERVICE_WORKER_OK) { | 211 if (status != SERVICE_WORKER_OK) { |
212 // Abort this registration job. | 212 // Abort this registration job. |
213 Complete(status); | 213 Complete(status); |
214 return; | 214 return; |
215 } | 215 } |
216 | 216 |
217 // TODO(falken): "If serviceWorkerRegistration.pendingWorker is not null..." | 217 // TODO(falken): "If serviceWorkerRegistration.waitingWorker is not null..." |
falken
2014/05/29 07:23:34
this is "installingWorker" in the spec
nhiroki
2014/05/30 00:38:20
Done.
| |
218 // then terminate the pending worker. It doesn't make sense to implement yet | 218 // then terminate the waiting worker. It doesn't make sense to implement yet |
219 // since we always activate the worker if install completed, so there can be | 219 // since we always activate the worker if install completed, so there can be |
220 // no pending worker at this point. | 220 // no waiting worker at this point. |
221 DCHECK(!registration()->pending_version()); | 221 DCHECK(!registration()->waiting_version()); |
222 | 222 |
223 // "Let serviceWorker be a newly-created ServiceWorker object..." and start | 223 // "Let serviceWorker be a newly-created ServiceWorker object..." and start |
224 // the worker. | 224 // the worker. |
225 set_pending_version(new ServiceWorkerVersion( | 225 set_waiting_version(new ServiceWorkerVersion( |
226 registration(), context_->storage()->NewVersionId(), context_)); | 226 registration(), context_->storage()->NewVersionId(), context_)); |
227 | 227 |
228 // TODO(michaeln): Start the worker into a paused state where the | 228 // TODO(michaeln): Start the worker into a paused state where the |
229 // script resource is downloaded but not yet evaluated. | 229 // script resource is downloaded but not yet evaluated. |
230 pending_version()->StartWorkerWithCandidateProcesses( | 230 waiting_version()->StartWorkerWithCandidateProcesses( |
231 pending_process_ids_, | 231 pending_process_ids_, |
232 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, | 232 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, |
233 weak_factory_.GetWeakPtr())); | 233 weak_factory_.GetWeakPtr())); |
234 } | 234 } |
235 | 235 |
236 void ServiceWorkerRegisterJob::OnStartWorkerFinished( | 236 void ServiceWorkerRegisterJob::OnStartWorkerFinished( |
237 ServiceWorkerStatusCode status) { | 237 ServiceWorkerStatusCode status) { |
238 // "If serviceWorker fails to start up..." then reject the promise with an | 238 // "If serviceWorker fails to start up..." then reject the promise with an |
239 // error and abort. | 239 // error and abort. |
240 if (status != SERVICE_WORKER_OK) { | 240 if (status != SERVICE_WORKER_OK) { |
241 Complete(status); | 241 Complete(status); |
242 return; | 242 return; |
243 } | 243 } |
244 | 244 |
245 // TODO(michaeln): Compare the old and new script. | 245 // TODO(michaeln): Compare the old and new script. |
246 // If different unpause the worker and continue with | 246 // If different unpause the worker and continue with |
247 // the job. If the same ResolvePromise with the current | 247 // the job. If the same ResolvePromise with the current |
248 // version and complete the job, throwing away the new version | 248 // version and complete the job, throwing away the new version |
249 // since there's nothing new. | 249 // since there's nothing new. |
250 | 250 |
251 // "Resolve promise with serviceWorker." | 251 // "Resolve promise with serviceWorker." |
252 // Although the spec doesn't set pendingWorker until after resolving the | 252 // Although the spec doesn't set waitingWorker until after resolving the |
253 // promise, our system's resolving works by passing ServiceWorkerRegistration | 253 // promise, our system's resolving works by passing ServiceWorkerRegistration |
254 // to the callbacks, so pendingWorker must be set first. | 254 // to the callbacks, so waitingWorker must be set first. |
255 DCHECK(!registration()->pending_version()); | 255 DCHECK(!registration()->waiting_version()); |
256 registration()->set_pending_version(pending_version()); | 256 registration()->set_waiting_version(waiting_version()); |
257 ResolvePromise(status, registration(), pending_version()); | 257 ResolvePromise(status, registration(), waiting_version()); |
258 | 258 |
259 AssociatePendingVersionToDocuments(pending_version()); | 259 AssociateWaitingVersionToDocuments(waiting_version()); |
260 | 260 |
261 InstallAndContinue(); | 261 InstallAndContinue(); |
262 } | 262 } |
263 | 263 |
264 // This function corresponds to the spec's _Install algorithm. | 264 // This function corresponds to the spec's _Install algorithm. |
265 void ServiceWorkerRegisterJob::InstallAndContinue() { | 265 void ServiceWorkerRegisterJob::InstallAndContinue() { |
266 SetPhase(INSTALL); | 266 SetPhase(INSTALL); |
267 // "Set serviceWorkerRegistration.pendingWorker._state to installing." | 267 // "Set serviceWorkerRegistration.waitingWorker._state to installing." |
falken
2014/05/29 07:23:34
the spec now reads "installingWorker.state"
nhiroki
2014/05/30 00:38:20
Done.
| |
268 // "Fire install event on the associated ServiceWorkerGlobalScope object." | 268 // "Fire install event on the associated ServiceWorkerGlobalScope object." |
269 pending_version()->DispatchInstallEvent( | 269 waiting_version()->DispatchInstallEvent( |
270 -1, | 270 -1, |
271 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, | 271 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, |
272 weak_factory_.GetWeakPtr())); | 272 weak_factory_.GetWeakPtr())); |
273 } | 273 } |
274 | 274 |
275 void ServiceWorkerRegisterJob::OnInstallFinished( | 275 void ServiceWorkerRegisterJob::OnInstallFinished( |
276 ServiceWorkerStatusCode status) { | 276 ServiceWorkerStatusCode status) { |
277 // "If any handler called waitUntil()..." and the resulting promise | 277 // "If any handler called waitUntil()..." and the resulting promise |
278 // is rejected, abort. | 278 // is rejected, abort. |
279 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is | 279 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is |
280 // unexpectedly terminated) we may want to retry sending the event again. | 280 // unexpectedly terminated) we may want to retry sending the event again. |
281 if (status != SERVICE_WORKER_OK) { | 281 if (status != SERVICE_WORKER_OK) { |
282 Complete(status); | 282 Complete(status); |
283 return; | 283 return; |
284 } | 284 } |
285 | 285 |
286 SetPhase(STORE); | 286 SetPhase(STORE); |
287 context_->storage()->StoreRegistration( | 287 context_->storage()->StoreRegistration( |
288 registration(), | 288 registration(), |
289 pending_version(), | 289 waiting_version(), |
290 base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete, | 290 base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete, |
291 weak_factory_.GetWeakPtr())); | 291 weak_factory_.GetWeakPtr())); |
292 } | 292 } |
293 | 293 |
294 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( | 294 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( |
295 ServiceWorkerStatusCode status) { | 295 ServiceWorkerStatusCode status) { |
296 if (status != SERVICE_WORKER_OK) { | 296 if (status != SERVICE_WORKER_OK) { |
297 Complete(status); | 297 Complete(status); |
298 return; | 298 return; |
299 } | 299 } |
(...skipping 16 matching lines...) Expand all Loading... | |
316 // registration already has an active version, so we shouldn't come | 316 // registration already has an active version, so we shouldn't come |
317 // this way. | 317 // this way. |
318 NOTREACHED(); | 318 NOTREACHED(); |
319 // TODO(falken): Register an continuation task to wait for NoControllees | 319 // TODO(falken): Register an continuation task to wait for NoControllees |
320 // notification so that we can resume activation later (see comments | 320 // notification so that we can resume activation later (see comments |
321 // in ServiceWorkerVersion::RemoveControllee). | 321 // in ServiceWorkerVersion::RemoveControllee). |
322 Complete(SERVICE_WORKER_OK); | 322 Complete(SERVICE_WORKER_OK); |
323 return; | 323 return; |
324 } | 324 } |
325 | 325 |
326 // "Set serviceWorkerRegistration.pendingWorker to null." | 326 // "Set serviceWorkerRegistration.waitingWorker to null." |
327 // "Set serviceWorkerRegistration.activeWorker to activatingWorker." | 327 // "Set serviceWorkerRegistration.activeWorker to activatingWorker." |
328 registration()->set_pending_version(NULL); | 328 registration()->set_waiting_version(NULL); |
329 AssociatePendingVersionToDocuments(NULL); | 329 AssociateWaitingVersionToDocuments(NULL); |
330 DCHECK(!registration()->active_version()); | 330 DCHECK(!registration()->active_version()); |
331 registration()->set_active_version(pending_version()); | 331 registration()->set_active_version(waiting_version()); |
332 | 332 |
333 // "Set serviceWorkerRegistration.activeWorker._state to activating." | 333 // "Set serviceWorkerRegistration.activeWorker._state to activating." |
334 // "Fire activate event on the associated ServiceWorkerGlobalScope object." | 334 // "Fire activate event on the associated ServiceWorkerGlobalScope object." |
335 // "Set serviceWorkerRegistration.activeWorker._state to active." | 335 // "Set serviceWorkerRegistration.activeWorker._state to active." |
336 pending_version()->DispatchActivateEvent( | 336 waiting_version()->DispatchActivateEvent( |
337 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, | 337 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, |
338 weak_factory_.GetWeakPtr())); | 338 weak_factory_.GetWeakPtr())); |
339 } | 339 } |
340 | 340 |
341 void ServiceWorkerRegisterJob::OnActivateFinished( | 341 void ServiceWorkerRegisterJob::OnActivateFinished( |
342 ServiceWorkerStatusCode status) { | 342 ServiceWorkerStatusCode status) { |
343 // "If any handler called waitUntil()..." and the resulting promise | 343 // "If any handler called waitUntil()..." and the resulting promise |
344 // is rejected, abort. | 344 // is rejected, abort. |
345 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is | 345 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is |
346 // unexpectedly terminated) we may want to retry sending the event again. | 346 // unexpectedly terminated) we may want to retry sending the event again. |
347 if (status != SERVICE_WORKER_OK) { | 347 if (status != SERVICE_WORKER_OK) { |
348 registration()->set_active_version(NULL); | 348 registration()->set_active_version(NULL); |
349 Complete(status); | 349 Complete(status); |
350 return; | 350 return; |
351 } | 351 } |
352 context_->storage()->UpdateToActiveState( | 352 context_->storage()->UpdateToActiveState( |
353 registration(), | 353 registration(), |
354 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 354 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
355 Complete(SERVICE_WORKER_OK); | 355 Complete(SERVICE_WORKER_OK); |
356 } | 356 } |
357 | 357 |
358 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { | 358 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { |
359 SetPhase(COMPLETE); | 359 SetPhase(COMPLETE); |
360 if (status != SERVICE_WORKER_OK) { | 360 if (status != SERVICE_WORKER_OK) { |
361 if (registration() && registration()->pending_version()) { | 361 if (registration() && registration()->waiting_version()) { |
362 AssociatePendingVersionToDocuments(NULL); | 362 AssociateWaitingVersionToDocuments(NULL); |
363 registration()->set_pending_version(NULL); | 363 registration()->set_waiting_version(NULL); |
364 } | 364 } |
365 if (registration() && !registration()->active_version()) { | 365 if (registration() && !registration()->active_version()) { |
366 context_->storage()->DeleteRegistration( | 366 context_->storage()->DeleteRegistration( |
367 registration()->id(), | 367 registration()->id(), |
368 registration()->script_url().GetOrigin(), | 368 registration()->script_url().GetOrigin(), |
369 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 369 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
370 } | 370 } |
371 if (!is_promise_resolved_) | 371 if (!is_promise_resolved_) |
372 ResolvePromise(status, NULL, NULL); | 372 ResolvePromise(status, NULL, NULL); |
373 } | 373 } |
374 DCHECK(callbacks_.empty()); | 374 DCHECK(callbacks_.empty()); |
375 if (registration()) { | 375 if (registration()) { |
376 context_->storage()->NotifyDoneInstallingRegistration( | 376 context_->storage()->NotifyDoneInstallingRegistration( |
377 registration(), pending_version(), status); | 377 registration(), waiting_version(), status); |
378 } | 378 } |
379 context_->job_coordinator()->FinishJob(pattern_, this); | 379 context_->job_coordinator()->FinishJob(pattern_, this); |
380 } | 380 } |
381 | 381 |
382 void ServiceWorkerRegisterJob::ResolvePromise( | 382 void ServiceWorkerRegisterJob::ResolvePromise( |
383 ServiceWorkerStatusCode status, | 383 ServiceWorkerStatusCode status, |
384 ServiceWorkerRegistration* registration, | 384 ServiceWorkerRegistration* registration, |
385 ServiceWorkerVersion* version) { | 385 ServiceWorkerVersion* version) { |
386 DCHECK(!is_promise_resolved_); | 386 DCHECK(!is_promise_resolved_); |
387 is_promise_resolved_ = true; | 387 is_promise_resolved_ = true; |
388 promise_resolved_status_ = status; | 388 promise_resolved_status_ = status; |
389 promise_resolved_registration_ = registration; | 389 promise_resolved_registration_ = registration; |
390 promise_resolved_version_ = version; | 390 promise_resolved_version_ = version; |
391 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); | 391 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); |
392 it != callbacks_.end(); | 392 it != callbacks_.end(); |
393 ++it) { | 393 ++it) { |
394 it->Run(status, registration, version); | 394 it->Run(status, registration, version); |
395 } | 395 } |
396 callbacks_.clear(); | 396 callbacks_.clear(); |
397 } | 397 } |
398 | 398 |
399 void ServiceWorkerRegisterJob::AssociatePendingVersionToDocuments( | 399 void ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments( |
400 ServiceWorkerVersion* version) { | 400 ServiceWorkerVersion* version) { |
401 // TODO(michaeln): This needs to respect the longest prefix wins | 401 // TODO(michaeln): This needs to respect the longest prefix wins |
402 // when it comes to finding a registration for a document url. | 402 // when it comes to finding a registration for a document url. |
403 // This should utilize storage->FindRegistrationForDocument(). | 403 // This should utilize storage->FindRegistrationForDocument(). |
404 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 404 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
405 context_->GetProviderHostIterator(); | 405 context_->GetProviderHostIterator(); |
406 !it->IsAtEnd(); | 406 !it->IsAtEnd(); |
407 it->Advance()) { | 407 it->Advance()) { |
408 ServiceWorkerProviderHost* provider_host = it->GetProviderHost(); | 408 ServiceWorkerProviderHost* provider_host = it->GetProviderHost(); |
409 if (ServiceWorkerUtils::ScopeMatches(pattern_, | 409 if (ServiceWorkerUtils::ScopeMatches(pattern_, |
410 provider_host->document_url())) | 410 provider_host->document_url())) |
411 provider_host->SetPendingVersion(version); | 411 provider_host->SetWaitingVersion(version); |
michaeln1
2014/05/29 21:16:52
Can you put a todo here about how this should be h
nhiroki
2014/05/30 00:38:20
Done.
| |
412 } | 412 } |
413 } | 413 } |
414 | 414 |
415 } // namespace content | 415 } // namespace content |
OLD | NEW |