1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_register_job.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/message_loop/message_loop.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/browser/service_worker/service_worker_context_core.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_job_coordinator.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h"
13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/browser/service_worker/service_worker_storage.h"
140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/service_worker/service_worker_utils.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/net_errors.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace content {
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace {
200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid RunSoon(const base::Closure& closure) {
220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::MessageLoop::current()->PostTask(FROM_HERE, closure);
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochtypedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType;
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::WeakPtr<ServiceWorkerContextCore> context,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const GURL& pattern,
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const GURL& script_url)
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : context_(context),
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      job_type_(REGISTRATION_JOB),
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pattern_(pattern),
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      script_url_(script_url),
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      phase_(INITIAL),
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      is_promise_resolved_(false),
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      promise_resolved_status_(SERVICE_WORKER_OK),
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      weak_factory_(this) {}
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::WeakPtr<ServiceWorkerContextCore> context,
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceWorkerRegistration* registration)
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : context_(context),
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      job_type_(UPDATE_JOB),
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      pattern_(registration->pattern()),
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      script_url_(registration->GetNewestVersion()->script_url()),
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      phase_(INITIAL),
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      is_promise_resolved_(false),
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      promise_resolved_status_(SERVICE_WORKER_OK),
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      weak_factory_(this) {
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  internal_.registration = registration;
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
560529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {
576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  DCHECK(!context_ ||
586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)         phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      << "Jobs should only be interrupted during shutdown.";
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerRegisterJob::AddCallback(
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const RegistrationCallback& callback,
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerProviderHost* provider_host) {
650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!is_promise_resolved_) {
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    callbacks_.push_back(callback);
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (provider_host)
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      provider_host->AddScopedProcessReferenceToPattern(pattern_);
690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  RunSoon(base::Bind(
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      callback, promise_resolved_status_,
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      promise_resolved_registration_, promise_resolved_version_));
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ServiceWorkerRegisterJob::Start() {
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPhase(START);
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ServiceWorkerStorage::FindRegistrationCallback next_step;
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (job_type_ == REGISTRATION_JOB) {
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    next_step = base::Bind(
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        &ServiceWorkerRegisterJob::ContinueWithRegistration,
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        weak_factory_.GetWeakPtr());
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    next_step = base::Bind(
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        &ServiceWorkerRegisterJob::ContinueWithUpdate,
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        weak_factory_.GetWeakPtr());
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<ServiceWorkerRegistration> registration =
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      context_->storage()->GetUninstallingRegistration(pattern_);
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (registration.get())
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    RunSoon(base::Bind(next_step, SERVICE_WORKER_OK, registration));
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  else
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    context_->storage()->FindRegistrationForPattern(pattern_, next_step);
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void ServiceWorkerRegisterJob::Abort() {
986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SetPhase(ABORT);
996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  CompleteInternal(SERVICE_WORKER_ERROR_ABORT);
1006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Don't have to call FinishJob() because the caller takes care of removing
1016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // the jobs from the queue.
1026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) {
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (job->GetType() != GetType())
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ServiceWorkerRegisterJob* register_job =
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      static_cast<ServiceWorkerRegisterJob*>(job);
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return register_job->pattern_ == pattern_ &&
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch         register_job->script_url_ == script_url_;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochRegistrationJobType ServiceWorkerRegisterJob::GetType() {
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return job_type_;
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochServiceWorkerRegisterJob::Internal::Internal() {}
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochServiceWorkerRegisterJob::Internal::~Internal() {}
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerRegisterJob::set_registration(
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<ServiceWorkerRegistration>& registration) {
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!internal_.registration.get());
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  internal_.registration = registration;
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(phase_ >= REGISTER || job_type_ == UPDATE_JOB) << phase_;
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return internal_.registration.get();
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceWorkerRegisterJob::set_new_version(
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ServiceWorkerVersion* version) {
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(phase_ == UPDATE) << phase_;
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!internal_.new_version.get());
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  internal_.new_version = version;
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
140116680a4aac90f2aa7413d9095a592090648e557Ben MurdochServiceWorkerVersion* ServiceWorkerRegisterJob::new_version() {
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(phase_ >= UPDATE) << phase_;
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return internal_.new_version.get();
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerRegisterJob::set_uninstalling_registration(
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<ServiceWorkerRegistration>& registration) {
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL);
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  internal_.uninstalling_registration = registration;
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciServiceWorkerRegistration*
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciServiceWorkerRegisterJob::uninstalling_registration() {
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL);
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return internal_.uninstalling_registration.get();
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerRegisterJob::SetPhase(Phase phase) {
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (phase) {
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case INITIAL:
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NOTREACHED();
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case START:
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(phase_ == INITIAL) << phase_;
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case WAIT_FOR_UNINSTALL:
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(phase_ == START) << phase_;
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case REGISTER:
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DCHECK(phase_ == START || phase_ == WAIT_FOR_UNINSTALL) << phase_;
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case UPDATE:
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case INSTALL:
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(phase_ == UPDATE) << phase_;
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case STORE:
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(phase_ == INSTALL) << phase_;
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case COMPLETE:
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      DCHECK(phase_ != INITIAL && phase_ != COMPLETE) << phase_;
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case ABORT:
1846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  phase_ = phase;
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This function corresponds to the steps in [[Register]] following
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// "Let registration be the result of running the [[GetRegistration]] algorithm.
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Throughout this file, comments in quotes are excerpts from the spec.
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerRegisterJob::ContinueWithRegistration(
193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ServiceWorkerStatusCode status,
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(REGISTRATION_JOB, job_type_);
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) {
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Complete(status);
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!existing_registration.get() || existing_registration->is_uninstalled()) {
2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    RegisterAndContinue(SERVICE_WORKER_OK);
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return;
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(existing_registration->GetNewestVersion());
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // "If scriptURL is equal to registration.[[ScriptURL]], then:"
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (existing_registration->GetNewestVersion()->script_url() == script_url_) {
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // "Set registration.[[Uninstalling]] to false."
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    existing_registration->AbortPendingClear(base::Bind(
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        &ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl,
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        weak_factory_.GetWeakPtr(),
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        existing_registration));
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (existing_registration->is_uninstalling()) {
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // "Wait until the Record {[[key]], [[value]]} entry of its
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // [[ScopeToRegistrationMap]] where registation.scope matches entry.[[key]]
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // is deleted."
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    WaitForUninstall(existing_registration);
222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // "Set registration.[[Uninstalling]] to false."
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!existing_registration->is_uninstalling());
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // "Return the result of running the [[Update]] algorithm, or its equivalent,
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // passing registration as the argument."
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_registration(existing_registration);
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UpdateAndContinue();
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerRegisterJob::ContinueWithUpdate(
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceWorkerStatusCode status,
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(UPDATE_JOB, job_type_);
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != SERVICE_WORKER_OK) {
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Complete(status);
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (existing_registration.get() != registration()) {
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // A previous job may have unregistered or installed a new version to this
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // registration.
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (registration()->is_uninstalling() ||
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      registration()->GetNewestVersion()->script_url() != script_url_) {
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // TODO(michaeln): If the last update check was less than 24 hours
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // ago, depending on the freshness of the cached worker script we
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // may be able to complete the update job right here.
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateAndContinue();
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Creates a new ServiceWorkerRegistration.
264e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid ServiceWorkerRegisterJob::RegisterAndContinue(
265e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ServiceWorkerStatusCode status) {
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPhase(REGISTER);
267e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (status != SERVICE_WORKER_OK) {
268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Abort this registration job.
269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    Complete(status);
270e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  set_registration(new ServiceWorkerRegistration(
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      pattern_, context_->storage()->NewRegistrationId(), context_));
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  AssociateProviderHostsToRegistration(registration());
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateAndContinue();
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerRegisterJob::WaitForUninstall(
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SetPhase(WAIT_FOR_UNINSTALL);
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_uninstalling_registration(existing_registration);
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  uninstalling_registration()->AddListener(this);
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl(
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<ServiceWorkerRegistration>& existing_registration,
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerStatusCode status) {
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (status != SERVICE_WORKER_OK) {
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Complete(status);
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_registration(existing_registration);
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(falken): Follow the spec: resolve the promise
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // with the newest version.
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!existing_registration->active_version()) {
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    UpdateAndContinue();
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResolvePromise(status,
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 existing_registration.get(),
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 existing_registration->active_version());
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Complete(SERVICE_WORKER_OK);
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// This function corresponds to the spec's [[Update]] algorithm.
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerRegisterJob::UpdateAndContinue() {
311c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPhase(UPDATE);
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  context_->storage()->NotifyInstallingRegistration(registration());
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.."
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // then terminate the installing worker. It doesn't make sense to implement
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // yet since we always activate the worker if install completed, so there can
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // be no installing worker at this point.
318c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
319c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // "Let serviceWorker be a newly-created ServiceWorker object..." and start
320c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // the worker.
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_new_version(new ServiceWorkerVersion(registration(),
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           script_url_,
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           context_->storage()->NewVersionId(),
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           context_));
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool pause_after_download = job_type_ == UPDATE_JOB;
327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (pause_after_download)
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    new_version()->embedded_worker()->AddListener(this);
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_version()->StartWorker(
330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pause_after_download,
331c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished,
332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 weak_factory_.GetWeakPtr()));
333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
334c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerRegisterJob::OnStartWorkerFinished(
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ServiceWorkerStatusCode status) {
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (status == SERVICE_WORKER_OK) {
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    InstallAndContinue();
339c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // "If serviceWorker fails to start up..." then reject the promise with an
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // error and abort. When there is a main script network error, the status will
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // be updated to a more specific one.
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const net::URLRequestStatus& main_script_status =
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new_version()->script_cache_map()->main_script_status();
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (main_script_status.status() != net::URLRequestStatus::SUCCESS) {
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    switch (main_script_status.error()) {
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case net::ERR_INSECURE_RESPONSE:
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case net::ERR_UNSAFE_REDIRECT:
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        status = SERVICE_WORKER_ERROR_SECURITY;
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case net::ERR_ABORTED:
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        status = SERVICE_WORKER_ERROR_ABORT;
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      case net::ERR_FAILED:
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        status = SERVICE_WORKER_ERROR_NETWORK;
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      default:
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        NOTREACHED();
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Complete(status);
364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This function corresponds to the spec's [[Install]] algorithm.
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerRegisterJob::InstallAndContinue() {
368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPhase(INSTALL);
369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // "2. Set registration.installingWorker to worker."
371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  registration()->SetInstallingVersion(new_version());
372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // "3. Resolve promise with registration."
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResolvePromise(SERVICE_WORKER_OK, registration(), new_version());
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // "4. Run the [[UpdateState]] algorithm passing registration.installingWorker
377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // and "installing" as the arguments."
378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  new_version()->SetStatus(ServiceWorkerVersion::INSTALLING);
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // "5. Fire a simple event named updatefound..."
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  registration()->NotifyUpdateFound();
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // "6. Fire an event named install..."
384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  new_version()->DispatchInstallEvent(
385c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      -1,
386c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
387c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 weak_factory_.GetWeakPtr()));
388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ServiceWorkerRegisterJob::OnInstallFinished(
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ServiceWorkerStatusCode status) {
392a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is
393a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // unexpectedly terminated) we may want to retry sending the event again.
394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (status != SERVICE_WORKER_OK) {
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // "8. If installFailed is true, then:..."
3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Complete(status);
3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  SetPhase(STORE);
4016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  registration()->set_last_update_check(base::Time::Now());
4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  context_->storage()->StoreRegistration(
4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      registration(),
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new_version(),
4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete,
4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                 weak_factory_.GetWeakPtr()));
4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ServiceWorkerStatusCode status) {
4110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (status != SERVICE_WORKER_OK) {
412c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Complete(status);
413c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
414c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // "9. If registration.waitingWorker is not null, then:..."
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (registration()->waiting_version()) {
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // "1. Run the [[UpdateState]] algorithm passing registration.waitingWorker
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // and "redundant" as the arguments."
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    registration()->waiting_version()->SetStatus(
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ServiceWorkerVersion::REDUNDANT);
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // "10. Set registration.waitingWorker to registration.installingWorker."
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // "11. Set registration.installingWorker to null."
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  registration()->SetWaitingVersion(new_version());
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // and "installed" as the arguments."
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  new_version()->SetStatus(ServiceWorkerVersion::INSTALLED);
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(michaeln): "13. If activateImmediate is true, then..."
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // "14. Wait until no document is using registration as their
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Service Worker registration."
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registration()->ActivateWaitingVersionWhenReady();
437a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
438c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Complete(SERVICE_WORKER_OK);
439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
4426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  CompleteInternal(status);
4436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  context_->job_coordinator()->FinishJob(pattern_, this);
4446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
4456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void ServiceWorkerRegisterJob::CompleteInternal(
4476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    ServiceWorkerStatusCode status) {
448c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetPhase(COMPLETE);
4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (status != SERVICE_WORKER_OK) {
450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (registration()) {
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (new_version()) {
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        registration()->UnsetVersion(new_version());
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        new_version()->Doom();
454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
4556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (!registration()->waiting_version() &&
4566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          !registration()->active_version()) {
4576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        registration()->NotifyRegistrationFailed();
458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        context_->storage()->DeleteRegistration(
459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            registration()->id(),
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            registration()->pattern().GetOrigin(),
461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
4640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!is_promise_resolved_)
4650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ResolvePromise(status, NULL, NULL);
4660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
4670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(callbacks_.empty());
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (registration()) {
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    context_->storage()->NotifyDoneInstallingRegistration(
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        registration(), new_version(), status);
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (new_version())
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    new_version()->embedded_worker()->RemoveListener(this);
474c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
475c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ServiceWorkerRegisterJob::ResolvePromise(
477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ServiceWorkerStatusCode status,
478c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ServiceWorkerRegistration* registration,
479c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ServiceWorkerVersion* version) {
4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(!is_promise_resolved_);
4810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  is_promise_resolved_ = true;
4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  promise_resolved_status_ = status;
4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  promise_resolved_registration_ = registration;
4840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  promise_resolved_version_ = version;
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != callbacks_.end();
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++it) {
488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    it->Run(status, registration, version);
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  callbacks_.clear();
491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
493116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ServiceWorkerRegisterJob::OnPausedAfterDownload() {
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // This happens prior to OnStartWorkerFinished time.
4956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_refptr<ServiceWorkerVersion> most_recent_version =
4966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      registration()->waiting_version() ?
4976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          registration()->waiting_version() :
4986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          registration()->active_version();
4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(most_recent_version.get());
5006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int64 most_recent_script_id =
5016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      most_recent_version->script_cache_map()->Lookup(script_url_);
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int64 new_script_id =
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new_version()->script_cache_map()->Lookup(script_url_);
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(michaeln): It would be better to compare as the new resource
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // is being downloaded and to avoid writing it to disk until we know
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // its needed.
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  context_->storage()->CompareScriptResources(
5096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      most_recent_script_id, new_script_id,
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete,
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
5126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 most_recent_version));
513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ServiceWorkerRegisterJob::OnMessageReceived(const IPC::Message& message) {
516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return false;
517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerRegisterJob::OnRegistrationFinishedUninstalling(
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerRegistration* existing_registration) {
5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL);
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(existing_registration, uninstalling_registration());
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  existing_registration->RemoveListener(this);
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_uninstalling_registration(NULL);
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RegisterAndContinue(SERVICE_WORKER_OK);
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete(
5296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ServiceWorkerVersion* most_recent_version,
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ServiceWorkerStatusCode status,
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool are_equal) {
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (are_equal) {
5336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Only bump the last check time when we've bypassed the browser cache.
5346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::TimeDelta time_since_last_check =
5356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::Time::Now() - registration()->last_update_check();
5366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (time_since_last_check > base::TimeDelta::FromHours(24)) {
5376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      registration()->set_last_update_check(base::Time::Now());
5386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      context_->storage()->UpdateLastUpdateCheckTime(registration());
5396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
5406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ResolvePromise(SERVICE_WORKER_OK, registration(), most_recent_version);
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Complete(SERVICE_WORKER_ERROR_EXISTS);
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Proceed with really starting the worker.
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  new_version()->embedded_worker()->ResumeAfterDownload();
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  new_version()->embedded_worker()->RemoveListener(this);
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ServiceWorkerRegisterJob::AssociateProviderHostsToRegistration(
5526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ServiceWorkerRegistration* registration) {
5536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(registration);
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
5556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           context_->GetProviderHostIterator();
556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       !it->IsAtEnd(); it->Advance()) {
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ServiceWorkerProviderHost* host = it->GetProviderHost();
5586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (ServiceWorkerUtils::ScopeMatches(registration->pattern(),
559116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                         host->document_url())) {
5606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (host->CanAssociateRegistration(registration))
5616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        host->AssociateRegistration(registration);
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
566a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace content
567