Chromium Code Reviews| 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:..." | |
| 291 new_version()->SetStatus(ServiceWorkerVersion::REDUNDANT); | |
| 292 registration()->SetInstallingVersion(NULL); | |
|
michaeln
2014/07/07 21:56:37
the call to SetInstallingVersion is not needed her
nhiroki
2014/07/07 23:07:40
Done.
| |
| 285 Complete(status); | 293 Complete(status); |
| 286 return; | 294 return; |
| 287 } | 295 } |
| 288 | 296 |
| 289 SetPhase(STORE); | 297 SetPhase(STORE); |
| 290 context_->storage()->StoreRegistration( | 298 context_->storage()->StoreRegistration( |
| 291 registration(), | 299 registration(), |
| 292 new_version(), | 300 new_version(), |
| 293 base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete, | 301 base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete, |
| 294 weak_factory_.GetWeakPtr())); | 302 weak_factory_.GetWeakPtr())); |
| 295 } | 303 } |
| 296 | 304 |
| 297 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( | 305 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( |
| 298 ServiceWorkerStatusCode status) { | 306 ServiceWorkerStatusCode status) { |
| 299 if (status != SERVICE_WORKER_OK) { | 307 if (status != SERVICE_WORKER_OK) { |
| 308 new_version()->SetStatus(ServiceWorkerVersion::REDUNDANT); | |
| 309 registration()->SetInstallingVersion(NULL); | |
|
michaeln
2014/07/07 21:56:37
ditto
nhiroki
2014/07/07 23:07:40
Done.
| |
| 300 Complete(status); | 310 Complete(status); |
| 301 return; | 311 return; |
| 302 } | 312 } |
| 313 | |
| 314 // TODO(nhiroki): "9. If registration.waitingWorker is not null, then:..." | |
| 315 | |
| 316 // "10. Set registration.waitingWorker to registration.installingWorker." | |
| 317 // "11. Set registration.installingWorker to null." | |
| 318 DisassociateVersionFromDocuments(context_, new_version()); | |
| 303 registration()->SetWaitingVersion(new_version()); | 319 registration()->SetWaitingVersion(new_version()); |
| 320 AssociateWaitingVersionToDocuments(context_, new_version()); | |
| 321 | |
| 322 // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker | |
| 323 // and "installed" as the arguments." | |
| 324 new_version()->SetStatus(ServiceWorkerVersion::INSTALLED); | |
| 304 ActivateAndContinue(); | 325 ActivateAndContinue(); |
| 305 } | 326 } |
| 306 | 327 |
| 307 // This function corresponds to the spec's _Activate algorithm. | 328 // This function corresponds to the spec's _Activate algorithm. |
| 308 void ServiceWorkerRegisterJob::ActivateAndContinue() { | 329 void ServiceWorkerRegisterJob::ActivateAndContinue() { |
| 309 SetPhase(ACTIVATE); | 330 SetPhase(ACTIVATE); |
| 310 | 331 |
| 311 // "If existingWorker is not null, then: wait for exitingWorker to finish | 332 // "4. If existingWorker is not null, then: wait for exitingWorker to finish |
| 312 // handling any in-progress requests." | 333 // handling any in-progress requests." |
| 313 // See if we already have an active_version for the scope and it has | 334 // 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 | 335 // controllee documents (if so activating the new version should wait |
| 315 // until we have no documents controlled by the version). | 336 // until we have no documents controlled by the version). |
| 316 if (registration()->active_version() && | 337 if (registration()->active_version() && |
| 317 registration()->active_version()->HasControllee()) { | 338 registration()->active_version()->HasControllee()) { |
| 318 // TODO(kinuko,falken): Currently we immediately return if the existing | 339 // TODO(kinuko,falken): Currently we immediately return if the existing |
| 319 // registration already has an active version, so we shouldn't come | 340 // registration already has an active version, so we shouldn't come |
| 320 // this way. | 341 // this way. |
| 321 NOTREACHED(); | 342 NOTREACHED(); |
| 322 // TODO(falken): Register an continuation task to wait for NoControllees | 343 // TODO(falken): Register an continuation task to wait for NoControllees |
| 323 // notification so that we can resume activation later (see comments | 344 // notification so that we can resume activation later. |
| 324 // in ServiceWorkerVersion::RemoveControllee). | |
| 325 Complete(SERVICE_WORKER_OK); | 345 Complete(SERVICE_WORKER_OK); |
| 326 return; | 346 return; |
| 327 } | 347 } |
| 328 | 348 |
| 329 // "Set serviceWorkerRegistration.waitingWorker to null." | 349 // "5. Set serviceWorkerRegistration.activeWorker to activatingWorker." |
| 330 // "Set serviceWorkerRegistration.activeWorker to activatingWorker." | 350 // "6. Set serviceWorkerRegistration.waitingWorker to null." |
| 331 registration()->SetActiveVersion(new_version()); | 351 registration()->SetActiveVersion(new_version()); |
| 332 | 352 |
| 333 // "Set serviceWorkerRegistration.activeWorker._state to activating." | 353 // "7. Run the [[UpdateState]] algorithm passing registration.activeWorker and |
| 334 // "Fire activate event on the associated ServiceWorkerGlobalScope object." | 354 // "activating" as arguments." |
| 335 // "Set serviceWorkerRegistration.activeWorker._state to active." | 355 new_version()->SetStatus(ServiceWorkerVersion::ACTIVATING); |
| 356 | |
| 357 // TODO(nhiroki): "8. Fire a simple event named controllerchange..." | |
| 358 | |
| 359 // "9. Fire an event named activate..." | |
| 336 new_version()->DispatchActivateEvent( | 360 new_version()->DispatchActivateEvent( |
| 337 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, | 361 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, |
| 338 weak_factory_.GetWeakPtr())); | 362 weak_factory_.GetWeakPtr())); |
| 339 } | 363 } |
| 340 | 364 |
| 341 void ServiceWorkerRegisterJob::OnActivateFinished( | 365 void ServiceWorkerRegisterJob::OnActivateFinished( |
| 342 ServiceWorkerStatusCode status) { | 366 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 | 367 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is |
| 346 // unexpectedly terminated) we may want to retry sending the event again. | 368 // unexpectedly terminated) we may want to retry sending the event again. |
| 347 if (status != SERVICE_WORKER_OK) { | 369 if (status != SERVICE_WORKER_OK) { |
| 370 // "11. If activateFailed is true, then:..." | |
| 371 new_version()->SetStatus(ServiceWorkerVersion::REDUNDANT); | |
| 348 registration()->SetActiveVersion(NULL); | 372 registration()->SetActiveVersion(NULL); |
|
michaeln
2014/07/07 21:56:37
ditto
nhiroki
2014/07/07 23:07:40
Done.
| |
| 349 Complete(status); | 373 Complete(status); |
| 350 return; | 374 return; |
| 351 } | 375 } |
| 376 | |
| 377 // "12. Run the [[UpdateState]] algorithm passing registration.activeWorker | |
| 378 // and "activated" as the arguments." | |
| 379 new_version()->SetStatus(ServiceWorkerVersion::ACTIVE); | |
| 352 context_->storage()->UpdateToActiveState( | 380 context_->storage()->UpdateToActiveState( |
| 353 registration(), | 381 registration(), |
| 354 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 382 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
| 355 Complete(SERVICE_WORKER_OK); | 383 Complete(SERVICE_WORKER_OK); |
| 356 } | 384 } |
| 357 | 385 |
| 358 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { | 386 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { |
| 359 CompleteInternal(status); | 387 CompleteInternal(status); |
| 360 context_->job_coordinator()->FinishJob(pattern_, this); | 388 context_->job_coordinator()->FinishJob(pattern_, this); |
| 361 } | 389 } |
| 362 | 390 |
| 363 void ServiceWorkerRegisterJob::CompleteInternal( | 391 void ServiceWorkerRegisterJob::CompleteInternal( |
| 364 ServiceWorkerStatusCode status) { | 392 ServiceWorkerStatusCode status) { |
| 365 SetPhase(COMPLETE); | 393 SetPhase(COMPLETE); |
| 366 if (status != SERVICE_WORKER_OK) { | 394 if (status != SERVICE_WORKER_OK) { |
| 367 if (registration()) { | 395 if (registration()) { |
| 368 if (new_version()) { | 396 if (new_version()) { |
|
michaeln
2014/07/07 21:56:37
right here
new_version()->SetStatus(ServiceWorkerV
nhiroki
2014/07/07 23:07:40
Done.
| |
| 369 DisassociateVersionFromDocuments(context_, new_version()); | 397 DisassociateVersionFromDocuments(context_, new_version()); |
| 370 registration()->UnsetVersion(new_version()); | 398 registration()->UnsetVersion(new_version()); |
| 371 } | 399 } |
| 372 if (!registration()->active_version()) { | 400 if (!registration()->active_version()) { |
| 373 context_->storage()->DeleteRegistration( | 401 context_->storage()->DeleteRegistration( |
| 374 registration()->id(), | 402 registration()->id(), |
| 375 registration()->script_url().GetOrigin(), | 403 registration()->script_url().GetOrigin(), |
| 376 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 404 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
| 377 } | 405 } |
| 378 } | 406 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 | 449 |
| 422 // static | 450 // static |
| 423 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( | 451 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( |
| 424 base::WeakPtr<ServiceWorkerContextCore> context, | 452 base::WeakPtr<ServiceWorkerContextCore> context, |
| 425 ServiceWorkerVersion* version) { | 453 ServiceWorkerVersion* version) { |
| 426 DCHECK(context); | 454 DCHECK(context); |
| 427 DCHECK(version); | 455 DCHECK(version); |
| 428 | 456 |
| 429 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 457 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| 430 context->GetProviderHostIterator(); | 458 context->GetProviderHostIterator(); |
| 431 !it->IsAtEnd(); it->Advance()) { | 459 !it->IsAtEnd(); it->Advance()) { |
| 432 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 460 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
| 433 if (ServiceWorkerUtils::ScopeMatches(version->scope(), | 461 if (ServiceWorkerUtils::ScopeMatches(version->scope(), |
| 434 host->document_url())) { | 462 host->document_url())) { |
| 435 if (!host->CanAssociateVersion(version)) | 463 if (!host->CanAssociateVersion(version)) |
| 436 continue; | 464 continue; |
| 437 host->SetInstallingVersion(version); | 465 host->SetInstallingVersion(version); |
| 438 } | 466 } |
| 439 } | 467 } |
| 440 } | 468 } |
| 441 | 469 |
| 442 // static | 470 // static |
| 471 void ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments( | |
| 472 base::WeakPtr<ServiceWorkerContextCore> context, | |
| 473 ServiceWorkerVersion* version) { | |
| 474 DCHECK(context); | |
| 475 DCHECK(version); | |
| 476 | |
| 477 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | |
| 478 context->GetProviderHostIterator(); | |
| 479 !it->IsAtEnd(); it->Advance()) { | |
| 480 ServiceWorkerProviderHost* host = it->GetProviderHost(); | |
| 481 if (ServiceWorkerUtils::ScopeMatches(version->scope(), | |
| 482 host->document_url())) { | |
| 483 if (!host->CanAssociateVersion(version)) | |
| 484 continue; | |
| 485 host->SetWaitingVersion(version); | |
| 486 } | |
| 487 } | |
| 488 } | |
| 489 | |
| 490 // static | |
| 443 void ServiceWorkerRegisterJob::DisassociateVersionFromDocuments( | 491 void ServiceWorkerRegisterJob::DisassociateVersionFromDocuments( |
| 444 base::WeakPtr<ServiceWorkerContextCore> context, | 492 base::WeakPtr<ServiceWorkerContextCore> context, |
| 445 ServiceWorkerVersion* version) { | 493 ServiceWorkerVersion* version) { |
| 446 DCHECK(context); | 494 DCHECK(context); |
| 447 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 495 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| 448 context->GetProviderHostIterator(); | 496 context->GetProviderHostIterator(); |
| 449 !it->IsAtEnd(); it->Advance()) { | 497 !it->IsAtEnd(); it->Advance()) { |
| 450 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 498 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
| 451 host->UnsetVersion(version); | 499 host->UnsetVersion(version); |
| 452 } | 500 } |
| 453 } | 501 } |
| 454 | 502 |
| 455 } // namespace content | 503 } // namespace content |
| OLD | NEW |