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 |