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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 void ServiceWorkerRegisterJob::AddCallback( | 62 void ServiceWorkerRegisterJob::AddCallback( |
63 const RegistrationCallback& callback, | 63 const RegistrationCallback& callback, |
64 ServiceWorkerProviderHost* provider_host) { | 64 ServiceWorkerProviderHost* provider_host) { |
65 if (!is_promise_resolved_) { | 65 if (!is_promise_resolved_) { |
66 callbacks_.push_back(callback); | 66 callbacks_.push_back(callback); |
67 if (provider_host) | 67 if (provider_host) |
68 provider_host->AddScopedProcessReferenceToPattern(pattern_); | 68 provider_host->AddScopedProcessReferenceToPattern(pattern_); |
69 return; | 69 return; |
70 } | 70 } |
71 RunSoon(base::Bind( | 71 RunSoon(base::Bind( |
72 callback, promise_resolved_status_, | 72 callback, promise_resolved_status_, promise_resolved_registration_)); |
73 promise_resolved_registration_, promise_resolved_version_)); | |
74 } | 73 } |
75 | 74 |
76 void ServiceWorkerRegisterJob::Start() { | 75 void ServiceWorkerRegisterJob::Start() { |
77 SetPhase(START); | 76 SetPhase(START); |
78 ServiceWorkerStorage::FindRegistrationCallback next_step; | 77 ServiceWorkerStorage::FindRegistrationCallback next_step; |
79 if (job_type_ == REGISTRATION_JOB) { | 78 if (job_type_ == REGISTRATION_JOB) { |
80 next_step = base::Bind( | 79 next_step = base::Bind( |
81 &ServiceWorkerRegisterJob::ContinueWithRegistration, | 80 &ServiceWorkerRegisterJob::ContinueWithRegistration, |
82 weak_factory_.GetWeakPtr()); | 81 weak_factory_.GetWeakPtr()); |
83 } else { | 82 } else { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 | 284 |
286 void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl( | 285 void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl( |
287 const scoped_refptr<ServiceWorkerRegistration>& existing_registration, | 286 const scoped_refptr<ServiceWorkerRegistration>& existing_registration, |
288 ServiceWorkerStatusCode status) { | 287 ServiceWorkerStatusCode status) { |
289 if (status != SERVICE_WORKER_OK) { | 288 if (status != SERVICE_WORKER_OK) { |
290 Complete(status); | 289 Complete(status); |
291 return; | 290 return; |
292 } | 291 } |
293 set_registration(existing_registration); | 292 set_registration(existing_registration); |
294 | 293 |
295 // TODO(falken): Follow the spec: resolve the promise | 294 // "If newestWorker is not null, and scriptURL is equal to |
296 // with the newest version. | 295 // newestWorker.scriptURL, then: |
297 | 296 // Return a promise resolved with registration." |
298 if (!existing_registration->active_version()) { | 297 // We resolve only if there's an active version. If there's not, |
299 UpdateAndContinue(); | 298 // then there is either no version or only a waiting version from |
| 299 // the last browser session; it makes sense to proceed with registration in |
| 300 // either case. |
| 301 DCHECK(!existing_registration->installing_version()); |
| 302 if (existing_registration->active_version()) { |
| 303 ResolvePromise(status, existing_registration.get()); |
| 304 Complete(SERVICE_WORKER_OK); |
300 return; | 305 return; |
301 } | 306 } |
302 | 307 |
303 ResolvePromise(status, | 308 // "Return the result of running the [[Update]] algorithm, or its equivalent, |
304 existing_registration.get(), | 309 // passing registration as the argument." |
305 existing_registration->active_version()); | 310 UpdateAndContinue(); |
306 Complete(SERVICE_WORKER_OK); | |
307 } | 311 } |
308 | 312 |
309 // This function corresponds to the spec's [[Update]] algorithm. | 313 // This function corresponds to the spec's [[Update]] algorithm. |
310 void ServiceWorkerRegisterJob::UpdateAndContinue() { | 314 void ServiceWorkerRegisterJob::UpdateAndContinue() { |
311 SetPhase(UPDATE); | 315 SetPhase(UPDATE); |
312 context_->storage()->NotifyInstallingRegistration(registration()); | 316 context_->storage()->NotifyInstallingRegistration(registration()); |
313 | 317 |
314 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." | 318 // "Let worker be a new ServiceWorker object..." and start |
315 // then terminate the installing worker. It doesn't make sense to implement | |
316 // yet since we always activate the worker if install completed, so there can | |
317 // be no installing worker at this point. | |
318 | |
319 // "Let serviceWorker be a newly-created ServiceWorker object..." and start | |
320 // the worker. | 319 // the worker. |
321 set_new_version(new ServiceWorkerVersion(registration(), | 320 set_new_version(new ServiceWorkerVersion(registration(), |
322 script_url_, | 321 script_url_, |
323 context_->storage()->NewVersionId(), | 322 context_->storage()->NewVersionId(), |
324 context_)); | 323 context_)); |
325 | 324 |
326 bool pause_after_download = job_type_ == UPDATE_JOB; | 325 bool pause_after_download = job_type_ == UPDATE_JOB; |
327 if (pause_after_download) | 326 if (pause_after_download) |
328 new_version()->embedded_worker()->AddListener(this); | 327 new_version()->embedded_worker()->AddListener(this); |
329 new_version()->StartWorker( | 328 new_version()->StartWorker( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 } | 360 } |
362 } | 361 } |
363 Complete(status); | 362 Complete(status); |
364 } | 363 } |
365 | 364 |
366 // This function corresponds to the spec's [[Install]] algorithm. | 365 // This function corresponds to the spec's [[Install]] algorithm. |
367 void ServiceWorkerRegisterJob::InstallAndContinue() { | 366 void ServiceWorkerRegisterJob::InstallAndContinue() { |
368 SetPhase(INSTALL); | 367 SetPhase(INSTALL); |
369 | 368 |
370 // "2. Set registration.installingWorker to worker." | 369 // "2. Set registration.installingWorker to worker." |
| 370 DCHECK(!registration()->installing_version()); |
371 registration()->SetInstallingVersion(new_version()); | 371 registration()->SetInstallingVersion(new_version()); |
372 | 372 |
373 // "3. Resolve promise with registration." | 373 // "3. Resolve promise with registration." |
374 ResolvePromise(SERVICE_WORKER_OK, registration(), new_version()); | 374 ResolvePromise(SERVICE_WORKER_OK, registration()); |
375 | 375 |
376 // "4. Run the [[UpdateState]] algorithm passing registration.installingWorker | 376 // "4. Run the [[UpdateState]] algorithm passing registration.installingWorker |
377 // and "installing" as the arguments." | 377 // and "installing" as the arguments." |
378 new_version()->SetStatus(ServiceWorkerVersion::INSTALLING); | 378 new_version()->SetStatus(ServiceWorkerVersion::INSTALLING); |
379 | 379 |
380 // "5. Fire a simple event named updatefound..." | 380 // "5. Fire a simple event named updatefound..." |
381 registration()->NotifyUpdateFound(); | 381 registration()->NotifyUpdateFound(); |
382 | 382 |
383 // "6. Fire an event named install..." | 383 // "6. Fire an event named install..." |
384 new_version()->DispatchInstallEvent( | 384 new_version()->DispatchInstallEvent( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 if (!registration()->waiting_version() && | 455 if (!registration()->waiting_version() && |
456 !registration()->active_version()) { | 456 !registration()->active_version()) { |
457 registration()->NotifyRegistrationFailed(); | 457 registration()->NotifyRegistrationFailed(); |
458 context_->storage()->DeleteRegistration( | 458 context_->storage()->DeleteRegistration( |
459 registration()->id(), | 459 registration()->id(), |
460 registration()->pattern().GetOrigin(), | 460 registration()->pattern().GetOrigin(), |
461 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 461 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
462 } | 462 } |
463 } | 463 } |
464 if (!is_promise_resolved_) | 464 if (!is_promise_resolved_) |
465 ResolvePromise(status, NULL, NULL); | 465 ResolvePromise(status, NULL); |
466 } | 466 } |
467 DCHECK(callbacks_.empty()); | 467 DCHECK(callbacks_.empty()); |
468 if (registration()) { | 468 if (registration()) { |
469 context_->storage()->NotifyDoneInstallingRegistration( | 469 context_->storage()->NotifyDoneInstallingRegistration( |
470 registration(), new_version(), status); | 470 registration(), new_version(), status); |
471 } | 471 } |
472 if (new_version()) | 472 if (new_version()) |
473 new_version()->embedded_worker()->RemoveListener(this); | 473 new_version()->embedded_worker()->RemoveListener(this); |
474 } | 474 } |
475 | 475 |
476 void ServiceWorkerRegisterJob::ResolvePromise( | 476 void ServiceWorkerRegisterJob::ResolvePromise( |
477 ServiceWorkerStatusCode status, | 477 ServiceWorkerStatusCode status, |
478 ServiceWorkerRegistration* registration, | 478 ServiceWorkerRegistration* registration) { |
479 ServiceWorkerVersion* version) { | |
480 DCHECK(!is_promise_resolved_); | 479 DCHECK(!is_promise_resolved_); |
481 is_promise_resolved_ = true; | 480 is_promise_resolved_ = true; |
482 promise_resolved_status_ = status; | 481 promise_resolved_status_ = status; |
483 promise_resolved_registration_ = registration; | 482 promise_resolved_registration_ = registration; |
484 promise_resolved_version_ = version; | |
485 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); | 483 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); |
486 it != callbacks_.end(); | 484 it != callbacks_.end(); |
487 ++it) { | 485 ++it) { |
488 it->Run(status, registration, version); | 486 it->Run(status, registration); |
489 } | 487 } |
490 callbacks_.clear(); | 488 callbacks_.clear(); |
491 } | 489 } |
492 | 490 |
493 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { | 491 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { |
494 // This happens prior to OnStartWorkerFinished time. | 492 // This happens prior to OnStartWorkerFinished time. |
495 scoped_refptr<ServiceWorkerVersion> most_recent_version = | 493 scoped_refptr<ServiceWorkerVersion> most_recent_version = |
496 registration()->waiting_version() ? | 494 registration()->waiting_version() ? |
497 registration()->waiting_version() : | 495 registration()->waiting_version() : |
498 registration()->active_version(); | 496 registration()->active_version(); |
499 DCHECK(most_recent_version.get()); | 497 DCHECK(most_recent_version.get()); |
500 int64 most_recent_script_id = | 498 int64 most_recent_script_id = |
501 most_recent_version->script_cache_map()->Lookup(script_url_); | 499 most_recent_version->script_cache_map()->Lookup(script_url_); |
502 int64 new_script_id = | 500 int64 new_script_id = |
503 new_version()->script_cache_map()->Lookup(script_url_); | 501 new_version()->script_cache_map()->Lookup(script_url_); |
504 | 502 |
505 // TODO(michaeln): It would be better to compare as the new resource | 503 // TODO(michaeln): It would be better to compare as the new resource |
506 // is being downloaded and to avoid writing it to disk until we know | 504 // is being downloaded and to avoid writing it to disk until we know |
507 // its needed. | 505 // its needed. |
508 context_->storage()->CompareScriptResources( | 506 context_->storage()->CompareScriptResources( |
509 most_recent_script_id, new_script_id, | 507 most_recent_script_id, |
| 508 new_script_id, |
510 base::Bind(&ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete, | 509 base::Bind(&ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete, |
511 weak_factory_.GetWeakPtr(), | 510 weak_factory_.GetWeakPtr())); |
512 most_recent_version)); | |
513 } | 511 } |
514 | 512 |
515 bool ServiceWorkerRegisterJob::OnMessageReceived(const IPC::Message& message) { | 513 bool ServiceWorkerRegisterJob::OnMessageReceived(const IPC::Message& message) { |
516 return false; | 514 return false; |
517 } | 515 } |
518 | 516 |
519 void ServiceWorkerRegisterJob::OnRegistrationFinishedUninstalling( | 517 void ServiceWorkerRegisterJob::OnRegistrationFinishedUninstalling( |
520 ServiceWorkerRegistration* existing_registration) { | 518 ServiceWorkerRegistration* existing_registration) { |
521 DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL); | 519 DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL); |
522 DCHECK_EQ(existing_registration, uninstalling_registration()); | 520 DCHECK_EQ(existing_registration, uninstalling_registration()); |
523 existing_registration->RemoveListener(this); | 521 existing_registration->RemoveListener(this); |
524 set_uninstalling_registration(NULL); | 522 set_uninstalling_registration(NULL); |
525 RegisterAndContinue(SERVICE_WORKER_OK); | 523 RegisterAndContinue(SERVICE_WORKER_OK); |
526 } | 524 } |
527 | 525 |
528 void ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete( | 526 void ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete( |
529 ServiceWorkerVersion* most_recent_version, | |
530 ServiceWorkerStatusCode status, | 527 ServiceWorkerStatusCode status, |
531 bool are_equal) { | 528 bool are_equal) { |
532 if (are_equal) { | 529 if (are_equal) { |
533 // Only bump the last check time when we've bypassed the browser cache. | 530 // Only bump the last check time when we've bypassed the browser cache. |
534 base::TimeDelta time_since_last_check = | 531 base::TimeDelta time_since_last_check = |
535 base::Time::Now() - registration()->last_update_check(); | 532 base::Time::Now() - registration()->last_update_check(); |
536 if (time_since_last_check > base::TimeDelta::FromHours(24)) { | 533 if (time_since_last_check > base::TimeDelta::FromHours(24)) { |
537 registration()->set_last_update_check(base::Time::Now()); | 534 registration()->set_last_update_check(base::Time::Now()); |
538 context_->storage()->UpdateLastUpdateCheckTime(registration()); | 535 context_->storage()->UpdateLastUpdateCheckTime(registration()); |
539 } | 536 } |
540 | 537 |
541 ResolvePromise(SERVICE_WORKER_OK, registration(), most_recent_version); | 538 ResolvePromise(SERVICE_WORKER_OK, registration()); |
542 Complete(SERVICE_WORKER_ERROR_EXISTS); | 539 Complete(SERVICE_WORKER_ERROR_EXISTS); |
543 return; | 540 return; |
544 } | 541 } |
545 | 542 |
546 // Proceed with really starting the worker. | 543 // Proceed with really starting the worker. |
547 new_version()->embedded_worker()->ResumeAfterDownload(); | 544 new_version()->embedded_worker()->ResumeAfterDownload(); |
548 new_version()->embedded_worker()->RemoveListener(this); | 545 new_version()->embedded_worker()->RemoveListener(this); |
549 } | 546 } |
550 | 547 |
551 void ServiceWorkerRegisterJob::AssociateProviderHostsToRegistration( | 548 void ServiceWorkerRegisterJob::AssociateProviderHostsToRegistration( |
552 ServiceWorkerRegistration* registration) { | 549 ServiceWorkerRegistration* registration) { |
553 DCHECK(registration); | 550 DCHECK(registration); |
554 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 551 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
555 context_->GetProviderHostIterator(); | 552 context_->GetProviderHostIterator(); |
556 !it->IsAtEnd(); it->Advance()) { | 553 !it->IsAtEnd(); it->Advance()) { |
557 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 554 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
558 if (ServiceWorkerUtils::ScopeMatches(registration->pattern(), | 555 if (ServiceWorkerUtils::ScopeMatches(registration->pattern(), |
559 host->document_url())) { | 556 host->document_url())) { |
560 if (host->CanAssociateRegistration(registration)) | 557 if (host->CanAssociateRegistration(registration)) |
561 host->AssociateRegistration(registration); | 558 host->AssociateRegistration(registration); |
562 } | 559 } |
563 } | 560 } |
564 } | 561 } |
565 | 562 |
566 } // namespace content | 563 } // namespace content |
OLD | NEW |