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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 if (status != SERVICE_WORKER_OK) { | 222 if (status != SERVICE_WORKER_OK) { |
223 // Abort this registration job. | 223 // Abort this registration job. |
224 Complete(status); | 224 Complete(status); |
225 return; | 225 return; |
226 } | 226 } |
227 | 227 |
228 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." | 228 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." |
229 // then terminate the installing worker. It doesn't make sense to implement | 229 // then terminate the installing worker. It doesn't make sense to implement |
230 // yet since we always activate the worker if install completed, so there can | 230 // yet since we always activate the worker if install completed, so there can |
231 // be no installing worker at this point. | 231 // be no installing worker at this point. |
232 // TODO(nhiroki): Check 'installing_version()' instead when it's supported. | |
233 | 232 |
234 // "Let serviceWorker be a newly-created ServiceWorker object..." and start | 233 // "Let serviceWorker be a newly-created ServiceWorker object..." and start |
235 // the worker. | 234 // the worker. |
236 set_new_version(new ServiceWorkerVersion( | 235 set_new_version(new ServiceWorkerVersion( |
237 registration(), context_->storage()->NewVersionId(), context_)); | 236 registration(), context_->storage()->NewVersionId(), context_)); |
238 | 237 |
239 // TODO(michaeln): Pause after downloading when performing an update. | 238 // TODO(michaeln): Pause after downloading when performing an update. |
240 bool pause_after_download = false; | 239 bool pause_after_download = false; |
241 if (pause_after_download) | 240 if (pause_after_download) |
242 new_version()->embedded_worker()->AddListener(this); | 241 new_version()->embedded_worker()->AddListener(this); |
243 new_version()->StartWorkerWithCandidateProcesses( | 242 new_version()->StartWorkerWithCandidateProcesses( |
244 pending_process_ids_, | 243 pending_process_ids_, |
245 pause_after_download, | 244 pause_after_download, |
246 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, | 245 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, |
247 weak_factory_.GetWeakPtr())); | 246 weak_factory_.GetWeakPtr())); |
248 } | 247 } |
249 | 248 |
250 void ServiceWorkerRegisterJob::OnStartWorkerFinished( | 249 void ServiceWorkerRegisterJob::OnStartWorkerFinished( |
251 ServiceWorkerStatusCode status) { | 250 ServiceWorkerStatusCode status) { |
252 // "If serviceWorker fails to start up..." then reject the promise with an | 251 // "If serviceWorker fails to start up..." then reject the promise with an |
253 // error and abort. | 252 // error and abort. |
254 if (status != SERVICE_WORKER_OK) { | 253 if (status != SERVICE_WORKER_OK) { |
255 Complete(status); | 254 Complete(status); |
256 return; | 255 return; |
257 } | 256 } |
258 | 257 |
259 // "Resolve promise with serviceWorker." | 258 // "Resolve promise with serviceWorker." |
260 DCHECK(!registration()->installing_version()); | 259 DCHECK(!registration()->installing_version()); |
261 ResolvePromise(status, registration(), new_version()); | 260 ResolvePromise(status, registration(), new_version()); |
262 registration()->SetInstallingVersion(new_version()); | |
263 AssociateInstallingVersionToDocuments(context_, new_version()); | |
264 InstallAndContinue(); | 261 InstallAndContinue(); |
265 } | 262 } |
266 | 263 |
267 // This function corresponds to the spec's _Install algorithm. | 264 // This function corresponds to the spec's _Install algorithm. |
268 void ServiceWorkerRegisterJob::InstallAndContinue() { | 265 void ServiceWorkerRegisterJob::InstallAndContinue() { |
269 SetPhase(INSTALL); | 266 SetPhase(INSTALL); |
270 // "Set serviceWorkerRegistration.installingWorker._state to installing." | 267 |
271 // "Fire install event on the associated ServiceWorkerGlobalScope object." | 268 // "3. Set registration.installingWorker to worker." |
| 269 registration()->SetInstallingVersion(new_version()); |
| 270 AssociateInstallingVersionToDocuments(context_, new_version()); |
| 271 |
| 272 // "4. Run the [[UpdateState]] algorithm passing registration.installingWorker |
| 273 // and "installing" as the arguments." |
| 274 new_version()->SetStatus(ServiceWorkerVersion::INSTALLING); |
| 275 |
| 276 // TODO(nhiroki,michaeln): "5. Fire a simple event named updatefound..." |
| 277 |
| 278 // "6. Fire an event named install..." |
272 new_version()->DispatchInstallEvent( | 279 new_version()->DispatchInstallEvent( |
273 -1, | 280 -1, |
274 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, | 281 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, |
275 weak_factory_.GetWeakPtr())); | 282 weak_factory_.GetWeakPtr())); |
276 } | 283 } |
277 | 284 |
278 void ServiceWorkerRegisterJob::OnInstallFinished( | 285 void ServiceWorkerRegisterJob::OnInstallFinished( |
279 ServiceWorkerStatusCode status) { | 286 ServiceWorkerStatusCode status) { |
280 // "If any handler called waitUntil()..." and the resulting promise | |
281 // is rejected, abort. | |
282 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is | 287 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is |
283 // unexpectedly terminated) we may want to retry sending the event again. | 288 // unexpectedly terminated) we may want to retry sending the event again. |
284 if (status != SERVICE_WORKER_OK) { | 289 if (status != SERVICE_WORKER_OK) { |
| 290 // "8. If installFailed is true, then:..." |
285 Complete(status); | 291 Complete(status); |
286 return; | 292 return; |
287 } | 293 } |
288 | 294 |
289 SetPhase(STORE); | 295 SetPhase(STORE); |
290 context_->storage()->StoreRegistration( | 296 context_->storage()->StoreRegistration( |
291 registration(), | 297 registration(), |
292 new_version(), | 298 new_version(), |
293 base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete, | 299 base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete, |
294 weak_factory_.GetWeakPtr())); | 300 weak_factory_.GetWeakPtr())); |
295 } | 301 } |
296 | 302 |
297 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( | 303 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( |
298 ServiceWorkerStatusCode status) { | 304 ServiceWorkerStatusCode status) { |
299 if (status != SERVICE_WORKER_OK) { | 305 if (status != SERVICE_WORKER_OK) { |
300 Complete(status); | 306 Complete(status); |
301 return; | 307 return; |
302 } | 308 } |
| 309 |
| 310 // TODO(nhiroki): "9. If registration.waitingWorker is not null, then:..." |
| 311 |
| 312 // "10. Set registration.waitingWorker to registration.installingWorker." |
| 313 // "11. Set registration.installingWorker to null." |
| 314 DisassociateVersionFromDocuments(context_, new_version()); |
303 registration()->SetWaitingVersion(new_version()); | 315 registration()->SetWaitingVersion(new_version()); |
| 316 AssociateWaitingVersionToDocuments(context_, new_version()); |
| 317 |
| 318 // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker |
| 319 // and "installed" as the arguments." |
| 320 new_version()->SetStatus(ServiceWorkerVersion::INSTALLED); |
304 ActivateAndContinue(); | 321 ActivateAndContinue(); |
305 } | 322 } |
306 | 323 |
307 // This function corresponds to the spec's _Activate algorithm. | 324 // This function corresponds to the spec's _Activate algorithm. |
308 void ServiceWorkerRegisterJob::ActivateAndContinue() { | 325 void ServiceWorkerRegisterJob::ActivateAndContinue() { |
309 SetPhase(ACTIVATE); | 326 SetPhase(ACTIVATE); |
310 | 327 |
311 // "If existingWorker is not null, then: wait for exitingWorker to finish | 328 // "4. If existingWorker is not null, then: wait for exitingWorker to finish |
312 // handling any in-progress requests." | 329 // handling any in-progress requests." |
313 // See if we already have an active_version for the scope and it has | 330 // See if we already have an active_version for the scope and it has |
314 // controllee documents (if so activating the new version should wait | 331 // controllee documents (if so activating the new version should wait |
315 // until we have no documents controlled by the version). | 332 // until we have no documents controlled by the version). |
316 if (registration()->active_version() && | 333 if (registration()->active_version() && |
317 registration()->active_version()->HasControllee()) { | 334 registration()->active_version()->HasControllee()) { |
318 // TODO(kinuko,falken): Currently we immediately return if the existing | 335 // TODO(kinuko,falken): Currently we immediately return if the existing |
319 // registration already has an active version, so we shouldn't come | 336 // registration already has an active version, so we shouldn't come |
320 // this way. | 337 // this way. |
321 NOTREACHED(); | 338 NOTREACHED(); |
322 // TODO(falken): Register an continuation task to wait for NoControllees | 339 // TODO(falken): Register an continuation task to wait for NoControllees |
323 // notification so that we can resume activation later (see comments | 340 // notification so that we can resume activation later. |
324 // in ServiceWorkerVersion::RemoveControllee). | |
325 Complete(SERVICE_WORKER_OK); | 341 Complete(SERVICE_WORKER_OK); |
326 return; | 342 return; |
327 } | 343 } |
328 | 344 |
329 // "Set serviceWorkerRegistration.waitingWorker to null." | 345 // "5. Set serviceWorkerRegistration.activeWorker to activatingWorker." |
330 // "Set serviceWorkerRegistration.activeWorker to activatingWorker." | 346 // "6. Set serviceWorkerRegistration.waitingWorker to null." |
331 registration()->SetActiveVersion(new_version()); | 347 registration()->SetActiveVersion(new_version()); |
332 | 348 |
333 // "Set serviceWorkerRegistration.activeWorker._state to activating." | 349 // "7. Run the [[UpdateState]] algorithm passing registration.activeWorker and |
334 // "Fire activate event on the associated ServiceWorkerGlobalScope object." | 350 // "activating" as arguments." |
335 // "Set serviceWorkerRegistration.activeWorker._state to active." | 351 new_version()->SetStatus(ServiceWorkerVersion::ACTIVATING); |
| 352 |
| 353 // TODO(nhiroki): "8. Fire a simple event named controllerchange..." |
| 354 |
| 355 // "9. Fire an event named activate..." |
336 new_version()->DispatchActivateEvent( | 356 new_version()->DispatchActivateEvent( |
337 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, | 357 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, |
338 weak_factory_.GetWeakPtr())); | 358 weak_factory_.GetWeakPtr())); |
339 } | 359 } |
340 | 360 |
341 void ServiceWorkerRegisterJob::OnActivateFinished( | 361 void ServiceWorkerRegisterJob::OnActivateFinished( |
342 ServiceWorkerStatusCode status) { | 362 ServiceWorkerStatusCode status) { |
343 // "If any handler called waitUntil()..." and the resulting promise | |
344 // is rejected, abort. | |
345 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is | 363 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is |
346 // unexpectedly terminated) we may want to retry sending the event again. | 364 // unexpectedly terminated) we may want to retry sending the event again. |
347 if (status != SERVICE_WORKER_OK) { | 365 if (status != SERVICE_WORKER_OK) { |
348 registration()->SetActiveVersion(NULL); | 366 // "11. If activateFailed is true, then:..." |
349 Complete(status); | 367 Complete(status); |
350 return; | 368 return; |
351 } | 369 } |
| 370 |
| 371 // "12. Run the [[UpdateState]] algorithm passing registration.activeWorker |
| 372 // and "activated" as the arguments." |
| 373 new_version()->SetStatus(ServiceWorkerVersion::ACTIVATED); |
352 context_->storage()->UpdateToActiveState( | 374 context_->storage()->UpdateToActiveState( |
353 registration(), | 375 registration(), |
354 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 376 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
355 Complete(SERVICE_WORKER_OK); | 377 Complete(SERVICE_WORKER_OK); |
356 } | 378 } |
357 | 379 |
358 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { | 380 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { |
359 CompleteInternal(status); | 381 CompleteInternal(status); |
360 context_->job_coordinator()->FinishJob(pattern_, this); | 382 context_->job_coordinator()->FinishJob(pattern_, this); |
361 } | 383 } |
362 | 384 |
363 void ServiceWorkerRegisterJob::CompleteInternal( | 385 void ServiceWorkerRegisterJob::CompleteInternal( |
364 ServiceWorkerStatusCode status) { | 386 ServiceWorkerStatusCode status) { |
365 SetPhase(COMPLETE); | 387 SetPhase(COMPLETE); |
366 if (status != SERVICE_WORKER_OK) { | 388 if (status != SERVICE_WORKER_OK) { |
367 if (registration()) { | 389 if (registration()) { |
368 if (new_version()) { | 390 if (new_version()) { |
| 391 new_version()->SetStatus(ServiceWorkerVersion::REDUNDANT); |
369 DisassociateVersionFromDocuments(context_, new_version()); | 392 DisassociateVersionFromDocuments(context_, new_version()); |
370 registration()->UnsetVersion(new_version()); | 393 registration()->UnsetVersion(new_version()); |
371 } | 394 } |
372 if (!registration()->active_version()) { | 395 if (!registration()->active_version()) { |
373 context_->storage()->DeleteRegistration( | 396 context_->storage()->DeleteRegistration( |
374 registration()->id(), | 397 registration()->id(), |
375 registration()->script_url().GetOrigin(), | 398 registration()->script_url().GetOrigin(), |
376 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 399 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
377 } | 400 } |
378 } | 401 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 | 444 |
422 // static | 445 // static |
423 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( | 446 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( |
424 base::WeakPtr<ServiceWorkerContextCore> context, | 447 base::WeakPtr<ServiceWorkerContextCore> context, |
425 ServiceWorkerVersion* version) { | 448 ServiceWorkerVersion* version) { |
426 DCHECK(context); | 449 DCHECK(context); |
427 DCHECK(version); | 450 DCHECK(version); |
428 | 451 |
429 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 452 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
430 context->GetProviderHostIterator(); | 453 context->GetProviderHostIterator(); |
431 !it->IsAtEnd(); it->Advance()) { | 454 !it->IsAtEnd(); it->Advance()) { |
432 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 455 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
433 if (ServiceWorkerUtils::ScopeMatches(version->scope(), | 456 if (ServiceWorkerUtils::ScopeMatches(version->scope(), |
434 host->document_url())) { | 457 host->document_url())) { |
435 if (!host->CanAssociateVersion(version)) | 458 if (!host->CanAssociateVersion(version)) |
436 continue; | 459 continue; |
437 host->SetInstallingVersion(version); | 460 host->SetInstallingVersion(version); |
438 } | 461 } |
439 } | 462 } |
440 } | 463 } |
441 | 464 |
442 // static | 465 // static |
| 466 void ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments( |
| 467 base::WeakPtr<ServiceWorkerContextCore> context, |
| 468 ServiceWorkerVersion* version) { |
| 469 DCHECK(context); |
| 470 DCHECK(version); |
| 471 |
| 472 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| 473 context->GetProviderHostIterator(); |
| 474 !it->IsAtEnd(); it->Advance()) { |
| 475 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
| 476 if (ServiceWorkerUtils::ScopeMatches(version->scope(), |
| 477 host->document_url())) { |
| 478 if (!host->CanAssociateVersion(version)) |
| 479 continue; |
| 480 host->SetWaitingVersion(version); |
| 481 } |
| 482 } |
| 483 } |
| 484 |
| 485 // static |
443 void ServiceWorkerRegisterJob::DisassociateVersionFromDocuments( | 486 void ServiceWorkerRegisterJob::DisassociateVersionFromDocuments( |
444 base::WeakPtr<ServiceWorkerContextCore> context, | 487 base::WeakPtr<ServiceWorkerContextCore> context, |
445 ServiceWorkerVersion* version) { | 488 ServiceWorkerVersion* version) { |
446 DCHECK(context); | 489 DCHECK(context); |
447 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 490 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
448 context->GetProviderHostIterator(); | 491 context->GetProviderHostIterator(); |
449 !it->IsAtEnd(); it->Advance()) { | 492 !it->IsAtEnd(); it->Advance()) { |
450 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 493 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
451 host->UnsetVersion(version); | 494 host->UnsetVersion(version); |
452 } | 495 } |
453 } | 496 } |
454 | 497 |
455 } // namespace content | 498 } // namespace content |
OLD | NEW |