Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/service_worker/service_worker_register_job.h" | 5 #include "content/browser/service_worker/service_worker_register_job.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "content/browser/service_worker/service_worker_context_core.h" | 10 #include "content/browser/service_worker/service_worker_context_core.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 | 23 |
| 24 } | 24 } |
| 25 | 25 |
| 26 typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType; | 26 typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType; |
| 27 | 27 |
| 28 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( | 28 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( |
| 29 base::WeakPtr<ServiceWorkerContextCore> context, | 29 base::WeakPtr<ServiceWorkerContextCore> context, |
| 30 const GURL& pattern, | 30 const GURL& pattern, |
| 31 const GURL& script_url) | 31 const GURL& script_url) |
| 32 : context_(context), | 32 : context_(context), |
| 33 job_type_(REGISTRATION), | |
| 33 pattern_(pattern), | 34 pattern_(pattern), |
| 34 script_url_(script_url), | 35 script_url_(script_url), |
| 35 phase_(INITIAL), | 36 phase_(INITIAL), |
| 36 is_promise_resolved_(false), | 37 is_promise_resolved_(false), |
| 37 promise_resolved_status_(SERVICE_WORKER_OK), | 38 promise_resolved_status_(SERVICE_WORKER_OK), |
| 38 weak_factory_(this) {} | 39 weak_factory_(this) {} |
| 39 | 40 |
| 41 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( | |
| 42 base::WeakPtr<ServiceWorkerContextCore> context, | |
| 43 ServiceWorkerRegistration* registration) | |
| 44 : context_(context), | |
| 45 job_type_(UPDATE_JOB), | |
| 46 pattern_(registration->pattern()), | |
| 47 script_url_(registration->script_url()), | |
| 48 phase_(INITIAL), | |
| 49 is_promise_resolved_(false), | |
| 50 promise_resolved_status_(SERVICE_WORKER_OK), | |
| 51 weak_factory_(this) { | |
| 52 internal_.registration = registration; | |
| 53 } | |
| 54 | |
| 40 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() { | 55 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() { |
| 41 DCHECK(!context_ || | 56 DCHECK(!context_ || |
| 42 phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT) | 57 phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT) |
| 43 << "Jobs should only be interrupted during shutdown."; | 58 << "Jobs should only be interrupted during shutdown."; |
| 44 } | 59 } |
| 45 | 60 |
| 46 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, | 61 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, |
| 47 int process_id) { | 62 int process_id) { |
| 48 if (!is_promise_resolved_) { | 63 if (!is_promise_resolved_) { |
| 49 callbacks_.push_back(callback); | 64 callbacks_.push_back(callback); |
| 50 if (process_id != -1 && (phase_ < UPDATE || !new_version())) | 65 if (process_id != -1 && (phase_ < UPDATE || !new_version())) |
| 51 pending_process_ids_.push_back(process_id); | 66 pending_process_ids_.push_back(process_id); |
| 52 return; | 67 return; |
| 53 } | 68 } |
| 54 RunSoon(base::Bind( | 69 RunSoon(base::Bind( |
| 55 callback, promise_resolved_status_, | 70 callback, promise_resolved_status_, |
| 56 promise_resolved_registration_, promise_resolved_version_)); | 71 promise_resolved_registration_, promise_resolved_version_)); |
| 57 } | 72 } |
| 58 | 73 |
| 59 void ServiceWorkerRegisterJob::Start() { | 74 void ServiceWorkerRegisterJob::Start() { |
| 60 SetPhase(START); | 75 SetPhase(START); |
| 76 ServiceWorkerStorage::FindRegistrationCallback next_step; | |
| 77 if (job_type_ == REGISTRATION) { | |
| 78 next_step = base::Bind( | |
| 79 &ServiceWorkerRegisterJob::ContinueWithRegistration, | |
| 80 weak_factory_.GetWeakPtr()); | |
| 81 } else { | |
|
nhiroki
2014/07/10 09:14:14
You may want to add "DCHECK_EQ(UPDATE_JOB, job_typ
| |
| 82 next_step = base::Bind( | |
| 83 &ServiceWorkerRegisterJob::ContinueWithUpdate, | |
| 84 weak_factory_.GetWeakPtr()); | |
| 85 } | |
| 61 context_->storage()->FindRegistrationForPattern( | 86 context_->storage()->FindRegistrationForPattern( |
| 62 pattern_, | 87 pattern_, next_step); |
| 63 base::Bind( | |
| 64 &ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue, | |
| 65 weak_factory_.GetWeakPtr())); | |
| 66 } | 88 } |
| 67 | 89 |
| 68 void ServiceWorkerRegisterJob::Abort() { | 90 void ServiceWorkerRegisterJob::Abort() { |
| 69 SetPhase(ABORT); | 91 SetPhase(ABORT); |
| 70 CompleteInternal(SERVICE_WORKER_ERROR_ABORT); | 92 CompleteInternal(SERVICE_WORKER_ERROR_ABORT); |
| 71 // Don't have to call FinishJob() because the caller takes care of removing | 93 // Don't have to call FinishJob() because the caller takes care of removing |
| 72 // the jobs from the queue. | 94 // the jobs from the queue. |
| 73 } | 95 } |
| 74 | 96 |
| 75 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) { | 97 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) { |
| 76 if (job->GetType() != GetType()) | 98 if (job->GetType() != GetType()) |
| 77 return false; | 99 return false; |
| 78 ServiceWorkerRegisterJob* register_job = | 100 ServiceWorkerRegisterJob* register_job = |
| 79 static_cast<ServiceWorkerRegisterJob*>(job); | 101 static_cast<ServiceWorkerRegisterJob*>(job); |
| 80 return register_job->pattern_ == pattern_ && | 102 return register_job->pattern_ == pattern_ && |
| 81 register_job->script_url_ == script_url_; | 103 register_job->script_url_ == script_url_; |
| 82 } | 104 } |
| 83 | 105 |
| 84 RegistrationJobType ServiceWorkerRegisterJob::GetType() { | 106 RegistrationJobType ServiceWorkerRegisterJob::GetType() { |
| 85 return REGISTRATION; | 107 return job_type_; |
| 86 } | 108 } |
| 87 | 109 |
| 88 ServiceWorkerRegisterJob::Internal::Internal() {} | 110 ServiceWorkerRegisterJob::Internal::Internal() {} |
| 89 | 111 |
| 90 ServiceWorkerRegisterJob::Internal::~Internal() {} | 112 ServiceWorkerRegisterJob::Internal::~Internal() {} |
| 91 | 113 |
| 92 void ServiceWorkerRegisterJob::set_registration( | 114 void ServiceWorkerRegisterJob::set_registration( |
| 93 ServiceWorkerRegistration* registration) { | 115 ServiceWorkerRegistration* registration) { |
| 94 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; | 116 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; |
| 95 DCHECK(!internal_.registration); | 117 DCHECK(!internal_.registration); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 case ABORT: | 164 case ABORT: |
| 143 break; | 165 break; |
| 144 } | 166 } |
| 145 phase_ = phase; | 167 phase_ = phase; |
| 146 } | 168 } |
| 147 | 169 |
| 148 // This function corresponds to the steps in Register following | 170 // This function corresponds to the steps in Register following |
| 149 // "Let serviceWorkerRegistration be _GetRegistration(scope)" | 171 // "Let serviceWorkerRegistration be _GetRegistration(scope)" |
| 150 // |existing_registration| corresponds to serviceWorkerRegistration. | 172 // |existing_registration| corresponds to serviceWorkerRegistration. |
| 151 // Throughout this file, comments in quotes are excerpts from the spec. | 173 // Throughout this file, comments in quotes are excerpts from the spec. |
| 152 void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue( | 174 void ServiceWorkerRegisterJob::ContinueWithRegistration( |
| 153 ServiceWorkerStatusCode status, | 175 ServiceWorkerStatusCode status, |
| 154 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) { | 176 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) { |
| 177 DCHECK_EQ(REGISTRATION, job_type_); | |
| 155 // On unexpected error, abort this registration job. | 178 // On unexpected error, abort this registration job. |
| 156 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) { | 179 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) { |
| 157 Complete(status); | 180 Complete(status); |
| 158 return; | 181 return; |
| 159 } | 182 } |
| 160 | 183 |
| 161 // "If serviceWorkerRegistration is not null and script is equal to | 184 // "If serviceWorkerRegistration is not null and script is equal to |
| 162 // serviceWorkerRegistration.scriptUrl..." resolve with the existing | 185 // serviceWorkerRegistration.scriptUrl..." resolve with the existing |
| 163 // registration and abort. | 186 // registration and abort. |
| 164 if (existing_registration.get() && | 187 if (existing_registration.get() && |
| 165 existing_registration->script_url() == script_url_) { | 188 existing_registration->script_url() == script_url_) { |
| 166 set_registration(existing_registration); | 189 set_registration(existing_registration); |
| 167 // 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 | |
| 169 // Update otherwise). | |
| 170 if (!existing_registration->active_version()) { | |
| 171 UpdateAndContinue(status); | |
| 172 return; | |
| 173 } | |
| 174 ResolvePromise( | 190 ResolvePromise( |
| 175 status, existing_registration, existing_registration->active_version()); | 191 status, existing_registration, existing_registration->active_version()); |
| 176 Complete(SERVICE_WORKER_OK); | 192 Complete(SERVICE_WORKER_OK); |
| 177 return; | 193 return; |
| 178 } | 194 } |
| 179 | 195 |
| 180 // "If serviceWorkerRegistration is null..." create a new registration. | 196 // "If serviceWorkerRegistration is null..." create a new registration. |
| 181 if (!existing_registration.get()) { | 197 if (!existing_registration.get()) { |
| 182 RegisterAndContinue(SERVICE_WORKER_OK); | 198 RegisterAndContinue(SERVICE_WORKER_OK); |
| 183 return; | 199 return; |
| 184 } | 200 } |
| 185 | 201 |
| 186 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to | 202 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to |
| 187 // script." We accomplish this by deleting the existing registration and | 203 // script." We accomplish this by deleting the existing registration and |
| 188 // registering a new one. | 204 // registering a new one. |
| 189 // TODO(falken): Match the spec. We now throw away the active_version_ and | 205 // 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. | 206 // waiting_version_ of the existing registration, which isn't in the spec. |
| 191 // TODO(michaeln): Deactivate the live existing_registration object and | 207 // TODO(michaeln): Deactivate the live existing_registration object and |
| 192 // eventually call storage->DeleteVersionResources() | 208 // eventually call storage->DeleteVersionResources() |
| 193 // when it no longer has any controllees. | 209 // when it no longer has any controllees. |
| 194 context_->storage()->DeleteRegistration( | 210 context_->storage()->DeleteRegistration( |
| 195 existing_registration->id(), | 211 existing_registration->id(), |
| 196 existing_registration->script_url().GetOrigin(), | 212 existing_registration->script_url().GetOrigin(), |
| 197 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, | 213 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, |
| 198 weak_factory_.GetWeakPtr())); | 214 weak_factory_.GetWeakPtr())); |
| 199 } | 215 } |
| 200 | 216 |
| 217 void ServiceWorkerRegisterJob::ContinueWithUpdate( | |
| 218 ServiceWorkerStatusCode status, | |
| 219 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) { | |
| 220 DCHECK_EQ(UPDATE, job_type_); | |
| 221 if (status != SERVICE_WORKER_OK) { | |
| 222 Complete(status); | |
| 223 return; | |
| 224 } | |
| 225 | |
| 226 if (existing_registration != registration()) { | |
| 227 Complete(SERVICE_WORKER_ERROR_NOT_FOUND); | |
| 228 return; | |
| 229 } | |
| 230 | |
| 231 DCHECK(registration()->active_version()); | |
| 232 UpdateAndContinue(status); | |
| 233 } | |
| 234 | |
| 201 // Creates a new ServiceWorkerRegistration. | 235 // Creates a new ServiceWorkerRegistration. |
| 202 void ServiceWorkerRegisterJob::RegisterAndContinue( | 236 void ServiceWorkerRegisterJob::RegisterAndContinue( |
| 203 ServiceWorkerStatusCode status) { | 237 ServiceWorkerStatusCode status) { |
| 204 SetPhase(REGISTER); | 238 SetPhase(REGISTER); |
| 205 if (status != SERVICE_WORKER_OK) { | 239 if (status != SERVICE_WORKER_OK) { |
| 206 // Abort this registration job. | 240 // Abort this registration job. |
| 207 Complete(status); | 241 Complete(status); |
| 208 return; | 242 return; |
| 209 } | 243 } |
| 210 | 244 |
| 211 set_registration(new ServiceWorkerRegistration( | 245 set_registration(new ServiceWorkerRegistration( |
| 212 pattern_, script_url_, context_->storage()->NewRegistrationId(), | 246 pattern_, script_url_, context_->storage()->NewRegistrationId(), |
| 213 context_)); | 247 context_)); |
| 214 context_->storage()->NotifyInstallingRegistration(registration()); | |
| 215 UpdateAndContinue(SERVICE_WORKER_OK); | 248 UpdateAndContinue(SERVICE_WORKER_OK); |
| 216 } | 249 } |
| 217 | 250 |
| 218 // This function corresponds to the spec's _Update algorithm. | 251 // This function corresponds to the spec's _Update algorithm. |
| 219 void ServiceWorkerRegisterJob::UpdateAndContinue( | 252 void ServiceWorkerRegisterJob::UpdateAndContinue( |
| 220 ServiceWorkerStatusCode status) { | 253 ServiceWorkerStatusCode status) { |
|
nhiroki
2014/07/10 09:14:14
This may not have to receive |status| since the ca
michaeln
2014/07/14 23:02:30
Done.
| |
| 221 SetPhase(UPDATE); | 254 SetPhase(UPDATE); |
| 222 if (status != SERVICE_WORKER_OK) { | 255 if (status != SERVICE_WORKER_OK) { |
| 223 // Abort this registration job. | 256 // Abort this registration job. |
| 224 Complete(status); | 257 Complete(status); |
| 225 return; | 258 return; |
| 226 } | 259 } |
| 260 context_->storage()->NotifyInstallingRegistration(registration()); | |
| 227 | 261 |
| 228 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." | 262 // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.." |
| 229 // then terminate the installing worker. It doesn't make sense to implement | 263 // 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 | 264 // yet since we always activate the worker if install completed, so there can |
| 231 // be no installing worker at this point. | 265 // be no installing worker at this point. |
| 232 | 266 |
| 233 // "Let serviceWorker be a newly-created ServiceWorker object..." and start | 267 // "Let serviceWorker be a newly-created ServiceWorker object..." and start |
| 234 // the worker. | 268 // the worker. |
| 235 set_new_version(new ServiceWorkerVersion( | 269 set_new_version(new ServiceWorkerVersion( |
| 236 registration(), context_->storage()->NewVersionId(), context_)); | 270 registration(), context_->storage()->NewVersionId(), context_)); |
| 237 | 271 |
| 238 // TODO(michaeln): Pause after downloading when performing an update. | 272 bool pause_after_download = job_type_ == UPDATE_JOB; |
| 239 bool pause_after_download = false; | |
| 240 if (pause_after_download) | 273 if (pause_after_download) |
| 241 new_version()->embedded_worker()->AddListener(this); | 274 new_version()->embedded_worker()->AddListener(this); |
| 242 new_version()->StartWorkerWithCandidateProcesses( | 275 new_version()->StartWorkerWithCandidateProcesses( |
| 243 pending_process_ids_, | 276 pending_process_ids_, |
| 244 pause_after_download, | 277 pause_after_download, |
| 245 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, | 278 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, |
| 246 weak_factory_.GetWeakPtr())); | 279 weak_factory_.GetWeakPtr())); |
| 247 } | 280 } |
| 248 | 281 |
| 249 void ServiceWorkerRegisterJob::OnStartWorkerFinished( | 282 void ServiceWorkerRegisterJob::OnStartWorkerFinished( |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 promise_resolved_version_ = version; | 457 promise_resolved_version_ = version; |
| 425 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); | 458 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); |
| 426 it != callbacks_.end(); | 459 it != callbacks_.end(); |
| 427 ++it) { | 460 ++it) { |
| 428 it->Run(status, registration, version); | 461 it->Run(status, registration, version); |
| 429 } | 462 } |
| 430 callbacks_.clear(); | 463 callbacks_.clear(); |
| 431 } | 464 } |
| 432 | 465 |
| 433 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { | 466 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { |
| 434 // TODO(michaeln): Compare the old and new script. | 467 // This happens prior to OnStartWorkerFinished time. |
| 435 // If different unpause the worker and continue with | 468 scoped_refptr<ServiceWorkerVersion> current_version = |
| 436 // the job. If the same ResolvePromise with the current | 469 registration()->active_version(); |
| 437 // version and complete the job, throwing away the new version | 470 DCHECK(current_version); |
| 438 // since there's nothing new. | 471 int64 current_script_id = |
| 439 new_version()->embedded_worker()->RemoveListener(this); | 472 current_version->script_cache_map()->Lookup(script_url_); |
| 440 new_version()->embedded_worker()->ResumeAfterDownload(); | 473 int64 new_script_id = |
| 474 new_version()->script_cache_map()->Lookup(script_url_); | |
| 475 | |
| 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 |