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" |
| 11 #include "content/browser/service_worker/service_worker_job_coordinator.h" | 11 #include "content/browser/service_worker/service_worker_job_coordinator.h" |
| 12 #include "content/browser/service_worker/service_worker_registration.h" | 12 #include "content/browser/service_worker/service_worker_registration.h" |
| 13 #include "content/browser/service_worker/service_worker_storage.h" | 13 #include "content/browser/service_worker/service_worker_storage.h" |
| 14 #include "content/browser/service_worker/service_worker_utils.h" | 14 #include "content/browser/service_worker/service_worker_utils.h" |
| 15 | 15 |
| 16 namespace content { | 16 namespace content { |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 void RunSoon(const base::Closure& closure) { | 20 void RunSoon(const base::Closure& closure) { |
| 21 base::MessageLoop::current()->PostTask(FROM_HERE, closure); | 21 base::MessageLoop::current()->PostTask(FROM_HERE, closure); |
| 22 } | 22 } |
| 23 | 23 |
| 24 } | 24 // Helper class for the [[Update]] algo. |
| 25 class DeferredActivationHelper : public ServiceWorkerVersion::Listener { | |
| 26 public: | |
| 27 explicit DeferredActivationHelper(ServiceWorkerRegistration* registration) | |
| 28 : registration_(registration), | |
| 29 active_version_(registration->active_version()), | |
| 30 waiting_version_(registration->waiting_version()) { | |
| 31 active_version_->AddListener(this); | |
| 32 } | |
| 33 | |
| 34 virtual ~DeferredActivationHelper() {} | |
| 35 | |
| 36 private: | |
| 37 virtual void OnNoControllees(ServiceWorkerVersion* version) OVERRIDE { | |
| 38 DCHECK_EQ(active_version_, version); | |
| 39 scoped_ptr<DeferredActivationHelper> self_deletor(this); | |
| 40 active_version_->RemoveListener(this); | |
| 41 if (registration_->active_version() != active_version_ || | |
| 42 registration_->waiting_version() != waiting_version_) { | |
| 43 return; // Something has changed making activation n/a. | |
| 44 } | |
| 45 registration_->ActivateWaitingVersion( | |
| 46 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | |
| 47 } | |
| 48 | |
| 49 scoped_refptr<ServiceWorkerRegistration> registration_; | |
| 50 scoped_refptr<ServiceWorkerVersion> active_version_; | |
| 51 scoped_refptr<ServiceWorkerVersion> waiting_version_; | |
| 52 DISALLOW_COPY_AND_ASSIGN(DeferredActivationHelper); | |
| 53 }; | |
| 54 | |
| 55 } // namespace | |
| 25 | 56 |
| 26 typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType; | 57 typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType; |
| 27 | 58 |
| 28 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( | 59 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( |
| 29 base::WeakPtr<ServiceWorkerContextCore> context, | 60 base::WeakPtr<ServiceWorkerContextCore> context, |
| 30 const GURL& pattern, | 61 const GURL& pattern, |
| 31 const GURL& script_url) | 62 const GURL& script_url) |
| 32 : context_(context), | 63 : context_(context), |
| 64 job_type_(REGISTRATION), | |
| 33 pattern_(pattern), | 65 pattern_(pattern), |
| 34 script_url_(script_url), | 66 script_url_(script_url), |
| 35 phase_(INITIAL), | 67 phase_(INITIAL), |
| 36 is_promise_resolved_(false), | 68 is_promise_resolved_(false), |
| 37 promise_resolved_status_(SERVICE_WORKER_OK), | 69 promise_resolved_status_(SERVICE_WORKER_OK), |
| 38 weak_factory_(this) {} | 70 weak_factory_(this) {} |
| 39 | 71 |
| 72 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( | |
| 73 base::WeakPtr<ServiceWorkerContextCore> context, | |
| 74 ServiceWorkerRegistration* registration) | |
| 75 : context_(context), | |
| 76 job_type_(UPDATE_JOB), | |
| 77 pattern_(registration->pattern()), | |
| 78 script_url_(registration->script_url()), | |
| 79 phase_(INITIAL), | |
| 80 is_promise_resolved_(false), | |
| 81 promise_resolved_status_(SERVICE_WORKER_OK), | |
| 82 weak_factory_(this) { | |
| 83 internal_.registration = registration; | |
| 84 } | |
| 85 | |
| 40 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() { | 86 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() { |
| 41 DCHECK(!context_ || | 87 DCHECK(!context_ || |
| 42 phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT) | 88 phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT) |
| 43 << "Jobs should only be interrupted during shutdown."; | 89 << "Jobs should only be interrupted during shutdown."; |
| 44 } | 90 } |
| 45 | 91 |
| 46 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, | 92 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, |
| 47 int process_id) { | 93 int process_id) { |
| 48 if (!is_promise_resolved_) { | 94 if (!is_promise_resolved_) { |
| 49 callbacks_.push_back(callback); | 95 callbacks_.push_back(callback); |
| 50 if (process_id != -1 && (phase_ < UPDATE || !new_version())) | 96 if (process_id != -1 && (phase_ < UPDATE || !new_version())) |
| 51 pending_process_ids_.push_back(process_id); | 97 pending_process_ids_.push_back(process_id); |
| 52 return; | 98 return; |
| 53 } | 99 } |
| 54 RunSoon(base::Bind( | 100 RunSoon(base::Bind( |
| 55 callback, promise_resolved_status_, | 101 callback, promise_resolved_status_, |
| 56 promise_resolved_registration_, promise_resolved_version_)); | 102 promise_resolved_registration_, promise_resolved_version_)); |
| 57 } | 103 } |
| 58 | 104 |
| 59 void ServiceWorkerRegisterJob::Start() { | 105 void ServiceWorkerRegisterJob::Start() { |
| 60 SetPhase(START); | 106 SetPhase(START); |
| 107 ServiceWorkerStorage::FindRegistrationCallback next_step; | |
| 108 if (job_type_ == REGISTRATION) { | |
| 109 next_step = base::Bind( | |
| 110 &ServiceWorkerRegisterJob::ContinueWithRegistration, | |
| 111 weak_factory_.GetWeakPtr()); | |
| 112 } else { | |
| 113 next_step = base::Bind( | |
| 114 &ServiceWorkerRegisterJob::ContinueWithUpdate, | |
| 115 weak_factory_.GetWeakPtr()); | |
| 116 } | |
| 61 context_->storage()->FindRegistrationForPattern( | 117 context_->storage()->FindRegistrationForPattern( |
| 62 pattern_, | 118 pattern_, next_step); |
|
nhiroki
2014/07/15 03:57:04
nit: Maybe you can squash this line into the previ
michaeln
2014/07/16 00:32:53
Done.
| |
| 63 base::Bind( | |
| 64 &ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue, | |
| 65 weak_factory_.GetWeakPtr())); | |
| 66 } | 119 } |
| 67 | 120 |
| 68 void ServiceWorkerRegisterJob::Abort() { | 121 void ServiceWorkerRegisterJob::Abort() { |
| 69 SetPhase(ABORT); | 122 SetPhase(ABORT); |
| 70 CompleteInternal(SERVICE_WORKER_ERROR_ABORT); | 123 CompleteInternal(SERVICE_WORKER_ERROR_ABORT); |
| 71 // Don't have to call FinishJob() because the caller takes care of removing | 124 // Don't have to call FinishJob() because the caller takes care of removing |
| 72 // the jobs from the queue. | 125 // the jobs from the queue. |
| 73 } | 126 } |
| 74 | 127 |
| 75 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) { | 128 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) { |
| 76 if (job->GetType() != GetType()) | 129 if (job->GetType() != GetType()) |
| 77 return false; | 130 return false; |
| 78 ServiceWorkerRegisterJob* register_job = | 131 ServiceWorkerRegisterJob* register_job = |
| 79 static_cast<ServiceWorkerRegisterJob*>(job); | 132 static_cast<ServiceWorkerRegisterJob*>(job); |
| 80 return register_job->pattern_ == pattern_ && | 133 return register_job->pattern_ == pattern_ && |
| 81 register_job->script_url_ == script_url_; | 134 register_job->script_url_ == script_url_; |
| 82 } | 135 } |
| 83 | 136 |
| 84 RegistrationJobType ServiceWorkerRegisterJob::GetType() { | 137 RegistrationJobType ServiceWorkerRegisterJob::GetType() { |
| 85 return REGISTRATION; | 138 return job_type_; |
| 86 } | 139 } |
| 87 | 140 |
| 88 ServiceWorkerRegisterJob::Internal::Internal() {} | 141 ServiceWorkerRegisterJob::Internal::Internal() {} |
| 89 | 142 |
| 90 ServiceWorkerRegisterJob::Internal::~Internal() {} | 143 ServiceWorkerRegisterJob::Internal::~Internal() {} |
| 91 | 144 |
| 92 void ServiceWorkerRegisterJob::set_registration( | 145 void ServiceWorkerRegisterJob::set_registration( |
| 93 ServiceWorkerRegistration* registration) { | 146 ServiceWorkerRegistration* registration) { |
| 94 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; | 147 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; |
| 95 DCHECK(!internal_.registration); | 148 DCHECK(!internal_.registration); |
| 96 internal_.registration = registration; | 149 internal_.registration = registration; |
| 97 } | 150 } |
| 98 | 151 |
| 99 ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() { | 152 ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() { |
| 100 DCHECK(phase_ >= REGISTER) << phase_; | 153 DCHECK(phase_ >= REGISTER || job_type_ == UPDATE_JOB) << phase_; |
| 101 return internal_.registration; | 154 return internal_.registration; |
| 102 } | 155 } |
| 103 | 156 |
| 104 void ServiceWorkerRegisterJob::set_new_version( | 157 void ServiceWorkerRegisterJob::set_new_version( |
| 105 ServiceWorkerVersion* version) { | 158 ServiceWorkerVersion* version) { |
| 106 DCHECK(phase_ == UPDATE) << phase_; | 159 DCHECK(phase_ == UPDATE) << phase_; |
| 107 DCHECK(!internal_.new_version); | 160 DCHECK(!internal_.new_version); |
| 108 internal_.new_version = version; | 161 internal_.new_version = version; |
| 109 } | 162 } |
| 110 | 163 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 case ABORT: | 195 case ABORT: |
| 143 break; | 196 break; |
| 144 } | 197 } |
| 145 phase_ = phase; | 198 phase_ = phase; |
| 146 } | 199 } |
| 147 | 200 |
| 148 // This function corresponds to the steps in Register following | 201 // This function corresponds to the steps in Register following |
| 149 // "Let serviceWorkerRegistration be _GetRegistration(scope)" | 202 // "Let serviceWorkerRegistration be _GetRegistration(scope)" |
| 150 // |existing_registration| corresponds to serviceWorkerRegistration. | 203 // |existing_registration| corresponds to serviceWorkerRegistration. |
| 151 // Throughout this file, comments in quotes are excerpts from the spec. | 204 // Throughout this file, comments in quotes are excerpts from the spec. |
| 152 void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue( | 205 void ServiceWorkerRegisterJob::ContinueWithRegistration( |
| 153 ServiceWorkerStatusCode status, | 206 ServiceWorkerStatusCode status, |
| 154 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) { | 207 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) { |
| 208 DCHECK_EQ(REGISTRATION, job_type_); | |
| 155 // On unexpected error, abort this registration job. | 209 // On unexpected error, abort this registration job. |
| 156 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) { | 210 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) { |
| 157 Complete(status); | 211 Complete(status); |
| 158 return; | 212 return; |
| 159 } | 213 } |
| 160 | 214 |
| 161 // "If serviceWorkerRegistration is not null and script is equal to | 215 // "If serviceWorkerRegistration is not null and script is equal to |
| 162 // serviceWorkerRegistration.scriptUrl..." resolve with the existing | 216 // serviceWorkerRegistration.scriptUrl..." resolve with the existing |
| 163 // registration and abort. | 217 // registration and abort. |
| 164 if (existing_registration.get() && | 218 if (existing_registration.get() && |
| 165 existing_registration->script_url() == script_url_) { | 219 existing_registration->script_url() == script_url_) { |
| 166 set_registration(existing_registration); | 220 set_registration(existing_registration); |
| 167 // If there's no active version, go ahead to Update (this isn't in the spec | 221 // If there's no active version, go ahead to Update (this isn't in the spec |
| 168 // but seems reasonable, and without SoftUpdate implemented we can never | 222 // but seems reasonable, and without SoftUpdate implemented we can never |
| 169 // Update otherwise). | 223 // Update otherwise). |
| 170 if (!existing_registration->active_version()) { | 224 if (!existing_registration->active_version()) { |
| 171 UpdateAndContinue(status); | 225 UpdateAndContinue(); |
| 172 return; | 226 return; |
| 173 } | 227 } |
| 174 ResolvePromise( | 228 ResolvePromise( |
| 175 status, existing_registration, existing_registration->active_version()); | 229 status, existing_registration, existing_registration->active_version()); |
| 176 Complete(SERVICE_WORKER_OK); | 230 Complete(SERVICE_WORKER_OK); |
| 177 return; | 231 return; |
| 178 } | 232 } |
| 179 | 233 |
| 180 // "If serviceWorkerRegistration is null..." create a new registration. | 234 // "If serviceWorkerRegistration is null..." create a new registration. |
| 181 if (!existing_registration.get()) { | 235 if (!existing_registration.get()) { |
| 182 RegisterAndContinue(SERVICE_WORKER_OK); | 236 RegisterAndContinue(SERVICE_WORKER_OK); |
| 183 return; | 237 return; |
| 184 } | 238 } |
| 185 | 239 |
| 186 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to | 240 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to |
| 187 // script." We accomplish this by deleting the existing registration and | 241 // script." We accomplish this by deleting the existing registration and |
| 188 // registering a new one. | 242 // registering a new one. |
| 189 // TODO(falken): Match the spec. We now throw away the active_version_ and | 243 // TODO(falken): Match the spec. We now throw away the active_version_ and |
| 190 // waiting_version_ of the existing registration, which isn't in the spec. | 244 // waiting_version_ of the existing registration, which isn't in the spec. |
| 191 // TODO(michaeln): Deactivate the live existing_registration object and | 245 // TODO(michaeln): Deactivate the live existing_registration object and |
| 192 // eventually call storage->DeleteVersionResources() | 246 // eventually call storage->DeleteVersionResources() |
| 193 // when it no longer has any controllees. | 247 // when it no longer has any controllees. |
| 194 context_->storage()->DeleteRegistration( | 248 context_->storage()->DeleteRegistration( |
| 195 existing_registration->id(), | 249 existing_registration->id(), |
| 196 existing_registration->script_url().GetOrigin(), | 250 existing_registration->script_url().GetOrigin(), |
| 197 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, | 251 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, |
| 198 weak_factory_.GetWeakPtr())); | 252 weak_factory_.GetWeakPtr())); |
| 199 } | 253 } |
| 200 | 254 |
| 255 void ServiceWorkerRegisterJob::ContinueWithUpdate( | |
| 256 ServiceWorkerStatusCode status, | |
| 257 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) { | |
| 258 DCHECK_EQ(UPDATE_JOB, job_type_); | |
| 259 if (status != SERVICE_WORKER_OK) { | |
| 260 Complete(status); | |
| 261 return; | |
| 262 } | |
| 263 | |
| 264 if (existing_registration != registration()) { | |
| 265 Complete(SERVICE_WORKER_ERROR_NOT_FOUND); | |
| 266 return; | |
| 267 } | |
| 268 | |
| 269 UpdateAndContinue(); | |
| 270 } | |
| 271 | |
| 201 // Creates a new ServiceWorkerRegistration. | 272 // Creates a new ServiceWorkerRegistration. |
| 202 void ServiceWorkerRegisterJob::RegisterAndContinue( | 273 void ServiceWorkerRegisterJob::RegisterAndContinue( |
| 203 ServiceWorkerStatusCode status) { | 274 ServiceWorkerStatusCode status) { |
| 204 SetPhase(REGISTER); | 275 SetPhase(REGISTER); |
| 205 if (status != SERVICE_WORKER_OK) { | 276 if (status != SERVICE_WORKER_OK) { |
| 206 // Abort this registration job. | 277 // Abort this registration job. |
| 207 Complete(status); | 278 Complete(status); |
| 208 return; | 279 return; |
| 209 } | 280 } |
| 210 | 281 |
| 211 set_registration(new ServiceWorkerRegistration( | 282 set_registration(new ServiceWorkerRegistration( |
| 212 pattern_, script_url_, context_->storage()->NewRegistrationId(), | 283 pattern_, script_url_, context_->storage()->NewRegistrationId(), |
| 213 context_)); | 284 context_)); |
| 214 context_->storage()->NotifyInstallingRegistration(registration()); | 285 UpdateAndContinue(); |
| 215 UpdateAndContinue(SERVICE_WORKER_OK); | |
| 216 } | 286 } |
| 217 | 287 |
| 218 // This function corresponds to the spec's _Update algorithm. | 288 // This function corresponds to the spec's _Update algorithm. |
| 219 void ServiceWorkerRegisterJob::UpdateAndContinue( | 289 void ServiceWorkerRegisterJob::UpdateAndContinue() { |
| 220 ServiceWorkerStatusCode status) { | |
| 221 SetPhase(UPDATE); | 290 SetPhase(UPDATE); |
| 222 if (status != SERVICE_WORKER_OK) { | 291 context_->storage()->NotifyInstallingRegistration(registration()); |
| 223 // Abort this registration job. | |
| 224 Complete(status); | |
| 225 return; | |
| 226 } | |
| 227 | 292 |
| 228 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." | 293 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." |
| 229 // then terminate the installing worker. It doesn't make sense to implement | 294 // 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 | 295 // yet since we always activate the worker if install completed, so there can |
| 231 // be no installing worker at this point. | 296 // be no installing worker at this point. |
| 232 | 297 |
| 233 // "Let serviceWorker be a newly-created ServiceWorker object..." and start | 298 // "Let serviceWorker be a newly-created ServiceWorker object..." and start |
| 234 // the worker. | 299 // the worker. |
| 235 set_new_version(new ServiceWorkerVersion( | 300 set_new_version(new ServiceWorkerVersion( |
| 236 registration(), context_->storage()->NewVersionId(), context_)); | 301 registration(), context_->storage()->NewVersionId(), context_)); |
| 237 | 302 |
| 238 // TODO(michaeln): Pause after downloading when performing an update. | 303 bool pause_after_download = job_type_ == UPDATE_JOB; |
| 239 bool pause_after_download = false; | |
| 240 if (pause_after_download) | 304 if (pause_after_download) |
| 241 new_version()->embedded_worker()->AddListener(this); | 305 new_version()->embedded_worker()->AddListener(this); |
| 242 new_version()->StartWorkerWithCandidateProcesses( | 306 new_version()->StartWorkerWithCandidateProcesses( |
| 243 pending_process_ids_, | 307 pending_process_ids_, |
| 244 pause_after_download, | 308 pause_after_download, |
| 245 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, | 309 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, |
| 246 weak_factory_.GetWeakPtr())); | 310 weak_factory_.GetWeakPtr())); |
| 247 } | 311 } |
| 248 | 312 |
| 249 void ServiceWorkerRegisterJob::OnStartWorkerFinished( | 313 void ServiceWorkerRegisterJob::OnStartWorkerFinished( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 weak_factory_.GetWeakPtr())); | 364 weak_factory_.GetWeakPtr())); |
| 301 } | 365 } |
| 302 | 366 |
| 303 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( | 367 void ServiceWorkerRegisterJob::OnStoreRegistrationComplete( |
| 304 ServiceWorkerStatusCode status) { | 368 ServiceWorkerStatusCode status) { |
| 305 if (status != SERVICE_WORKER_OK) { | 369 if (status != SERVICE_WORKER_OK) { |
| 306 Complete(status); | 370 Complete(status); |
| 307 return; | 371 return; |
| 308 } | 372 } |
| 309 | 373 |
| 310 // TODO(nhiroki): "9. If registration.waitingWorker is not null, then:..." | 374 // "9. If registration.waitingWorker is not null, then:..." |
| 375 if (registration()->waiting_version()) { | |
| 376 // "1. Run the [[UpdateState]] algorithm passing registration.waitingWorker | |
| 377 // and "redundant" as the arguments." | |
| 378 registration()->waiting_version()->SetStatus( | |
| 379 ServiceWorkerVersion::REDUNDANT); | |
| 380 } | |
| 311 | 381 |
| 312 // "10. Set registration.waitingWorker to registration.installingWorker." | 382 // "10. Set registration.waitingWorker to registration.installingWorker." |
| 313 // "11. Set registration.installingWorker to null." | 383 // "11. Set registration.installingWorker to null." |
| 314 DisassociateVersionFromDocuments(context_, new_version()); | 384 DisassociateVersionFromDocuments(context_, new_version()); |
| 315 registration()->SetWaitingVersion(new_version()); | 385 registration()->SetWaitingVersion(new_version()); |
| 316 AssociateWaitingVersionToDocuments(context_, new_version()); | 386 AssociateWaitingVersionToDocuments(context_, new_version()); |
| 317 | 387 |
| 318 // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker | 388 // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker |
| 319 // and "installed" as the arguments." | 389 // and "installed" as the arguments." |
| 320 new_version()->SetStatus(ServiceWorkerVersion::INSTALLED); | 390 new_version()->SetStatus(ServiceWorkerVersion::INSTALLED); |
| 321 ActivateAndContinue(); | |
| 322 } | |
| 323 | 391 |
| 324 // This function corresponds to the spec's _Activate algorithm. | 392 // TODO(michaeln): "13. If activateImmediate is true, then..." |
| 325 void ServiceWorkerRegisterJob::ActivateAndContinue() { | |
| 326 SetPhase(ACTIVATE); | |
| 327 | 393 |
| 328 // "4. If existingWorker is not null, then: wait for exitingWorker to finish | 394 // "14. Wait until no document is using registration as their |
| 329 // handling any in-progress requests." | 395 // Service Worker registration." |
| 330 // See if we already have an active_version for the scope and it has | |
| 331 // controllee documents (if so activating the new version should wait | |
| 332 // until we have no documents controlled by the version). | |
| 333 if (registration()->active_version() && | 396 if (registration()->active_version() && |
| 334 registration()->active_version()->HasControllee()) { | 397 registration()->active_version()->HasControllee()) { |
| 335 // TODO(kinuko,falken): Currently we immediately return if the existing | 398 scoped_ptr<DeferredActivationHelper> deferred_activation( |
| 336 // registration already has an active version, so we shouldn't come | 399 new DeferredActivationHelper(registration())); |
| 337 // this way. | 400 // It will delete itself when done. |
| 338 NOTREACHED(); | 401 ignore_result(deferred_activation.release()); |
| 339 // TODO(falken): Register an continuation task to wait for NoControllees | |
| 340 // notification so that we can resume activation later. | |
| 341 Complete(SERVICE_WORKER_OK); | 402 Complete(SERVICE_WORKER_OK); |
| 342 return; | 403 return; |
| 343 } | 404 } |
| 344 | 405 |
| 345 // "5. Set serviceWorkerRegistration.activeWorker to activatingWorker." | 406 SetPhase(ACTIVATE); |
| 346 // "6. Set serviceWorkerRegistration.waitingWorker to null." | 407 registration()->ActivateWaitingVersion( |
| 347 DisassociateVersionFromDocuments(context_, new_version()); | 408 base::Bind(&ServiceWorkerRegisterJob::Complete, |
| 348 registration()->SetActiveVersion(new_version()); | |
| 349 AssociateActiveVersionToDocuments(context_, new_version()); | |
| 350 | |
| 351 // "7. Run the [[UpdateState]] algorithm passing registration.activeWorker and | |
| 352 // "activating" as arguments." | |
| 353 new_version()->SetStatus(ServiceWorkerVersion::ACTIVATING); | |
| 354 | |
| 355 // TODO(nhiroki): "8. Fire a simple event named controllerchange..." | |
| 356 | |
| 357 // "9. Fire an event named activate..." | |
| 358 new_version()->DispatchActivateEvent( | |
| 359 base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished, | |
| 360 weak_factory_.GetWeakPtr())); | 409 weak_factory_.GetWeakPtr())); |
| 361 } | 410 } |
| 362 | 411 |
| 363 void ServiceWorkerRegisterJob::OnActivateFinished( | |
| 364 ServiceWorkerStatusCode status) { | |
| 365 // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is | |
| 366 // unexpectedly terminated) we may want to retry sending the event again. | |
| 367 if (status != SERVICE_WORKER_OK) { | |
| 368 // "11. If activateFailed is true, then:..." | |
| 369 Complete(status); | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 // "12. Run the [[UpdateState]] algorithm passing registration.activeWorker | |
| 374 // and "activated" as the arguments." | |
| 375 new_version()->SetStatus(ServiceWorkerVersion::ACTIVATED); | |
| 376 context_->storage()->UpdateToActiveState( | |
| 377 registration(), | |
| 378 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | |
| 379 Complete(SERVICE_WORKER_OK); | |
| 380 } | |
| 381 | |
| 382 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { | 412 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { |
| 383 CompleteInternal(status); | 413 CompleteInternal(status); |
| 384 context_->job_coordinator()->FinishJob(pattern_, this); | 414 context_->job_coordinator()->FinishJob(pattern_, this); |
| 385 } | 415 } |
| 386 | 416 |
| 387 void ServiceWorkerRegisterJob::CompleteInternal( | 417 void ServiceWorkerRegisterJob::CompleteInternal( |
| 388 ServiceWorkerStatusCode status) { | 418 ServiceWorkerStatusCode status) { |
| 389 SetPhase(COMPLETE); | 419 SetPhase(COMPLETE); |
| 390 if (status != SERVICE_WORKER_OK) { | 420 if (status != SERVICE_WORKER_OK) { |
| 391 if (registration()) { | 421 if (registration()) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 promise_resolved_version_ = version; | 454 promise_resolved_version_ = version; |
| 425 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); | 455 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); |
| 426 it != callbacks_.end(); | 456 it != callbacks_.end(); |
| 427 ++it) { | 457 ++it) { |
| 428 it->Run(status, registration, version); | 458 it->Run(status, registration, version); |
| 429 } | 459 } |
| 430 callbacks_.clear(); | 460 callbacks_.clear(); |
| 431 } | 461 } |
| 432 | 462 |
| 433 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { | 463 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { |
| 434 // TODO(michaeln): Compare the old and new script. | 464 // This happens prior to OnStartWorkerFinished time. |
| 435 // If different unpause the worker and continue with | 465 scoped_refptr<ServiceWorkerVersion> current_version = |
| 436 // the job. If the same ResolvePromise with the current | 466 registration()->active_version(); |
| 437 // version and complete the job, throwing away the new version | 467 DCHECK(current_version); |
| 438 // since there's nothing new. | 468 int64 current_script_id = |
| 439 new_version()->embedded_worker()->RemoveListener(this); | 469 current_version->script_cache_map()->Lookup(script_url_); |
| 440 new_version()->embedded_worker()->ResumeAfterDownload(); | 470 int64 new_script_id = |
| 471 new_version()->script_cache_map()->Lookup(script_url_); | |
| 472 | |
| 473 // TODO(michaeln): It would be better to compare as the new resource | |
| 474 // is being downloaded and to avoid writing it to disk until we know | |
| 475 // its needed. | |
| 476 context_->storage()->CompareScriptResources( | |
| 477 current_script_id, new_script_id, | |
| 478 base::Bind(&ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete, | |
| 479 weak_factory_.GetWeakPtr(), | |
| 480 current_version)); | |
| 441 } | 481 } |
| 442 | 482 |
| 443 bool ServiceWorkerRegisterJob::OnMessageReceived(const IPC::Message& message) { | 483 bool ServiceWorkerRegisterJob::OnMessageReceived(const IPC::Message& message) { |
| 444 return false; | 484 return false; |
| 445 } | 485 } |
| 446 | 486 |
| 487 void ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete( | |
| 488 ServiceWorkerVersion* current_version, | |
| 489 ServiceWorkerStatusCode status, | |
| 490 int compare_result) { | |
| 491 if (compare_result == 0) { | |
| 492 new_version()->embedded_worker()->Stop(); | |
| 493 ResolvePromise( | |
| 494 SERVICE_WORKER_OK, registration(), current_version); | |
| 495 Complete(SERVICE_WORKER_ERROR_EXISTS); | |
| 496 return; | |
| 497 } | |
| 498 | |
| 499 // Proceed with really starting the worker. | |
| 500 new_version()->embedded_worker()->ResumeAfterDownload(); | |
| 501 new_version()->embedded_worker()->RemoveListener(this); | |
| 502 } | |
| 503 | |
| 447 // static | 504 // static |
| 448 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( | 505 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( |
| 449 base::WeakPtr<ServiceWorkerContextCore> context, | 506 base::WeakPtr<ServiceWorkerContextCore> context, |
| 450 ServiceWorkerVersion* version) { | 507 ServiceWorkerVersion* version) { |
| 451 DCHECK(context); | 508 DCHECK(context); |
| 452 DCHECK(version); | 509 DCHECK(version); |
| 453 | 510 |
| 454 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 511 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| 455 context->GetProviderHostIterator(); | 512 context->GetProviderHostIterator(); |
| 456 !it->IsAtEnd(); it->Advance()) { | 513 !it->IsAtEnd(); it->Advance()) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 DCHECK(context); | 568 DCHECK(context); |
| 512 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 569 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
| 513 context->GetProviderHostIterator(); | 570 context->GetProviderHostIterator(); |
| 514 !it->IsAtEnd(); it->Advance()) { | 571 !it->IsAtEnd(); it->Advance()) { |
| 515 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 572 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
| 516 host->UnsetVersion(version); | 573 host->UnsetVersion(version); |
| 517 } | 574 } |
| 518 } | 575 } |
| 519 | 576 |
| 520 } // namespace content | 577 } // namespace content |
| OLD | NEW |