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