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. |
falken
2014/07/17 06:33:41
Maybe add a lightweight comment about what it does
| |
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. |
falken
2014/07/17 06:33:41
nit: now it's [[Update]] algorithm
michaeln
2014/07/18 03:40:48
Done.
| |
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 int compare_result) { | |
490 if (compare_result == 0) { | |
491 new_version()->embedded_worker()->Stop(); | |
492 ResolvePromise( | |
493 SERVICE_WORKER_OK, registration(), current_version); | |
falken
2014/07/17 06:33:41
this can fit on one line
michaeln
2014/07/18 03:40:48
Done.
| |
494 Complete(SERVICE_WORKER_ERROR_EXISTS); | |
495 return; | |
496 } | |
497 | |
498 // Proceed with really starting the worker. | |
499 new_version()->embedded_worker()->ResumeAfterDownload(); | |
500 new_version()->embedded_worker()->RemoveListener(this); | |
501 } | |
502 | |
447 // static | 503 // static |
448 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( | 504 void ServiceWorkerRegisterJob::AssociateInstallingVersionToDocuments( |
449 base::WeakPtr<ServiceWorkerContextCore> context, | 505 base::WeakPtr<ServiceWorkerContextCore> context, |
450 ServiceWorkerVersion* version) { | 506 ServiceWorkerVersion* version) { |
451 DCHECK(context); | 507 DCHECK(context); |
452 DCHECK(version); | 508 DCHECK(version); |
453 | 509 |
454 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 510 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
455 context->GetProviderHostIterator(); | 511 context->GetProviderHostIterator(); |
456 !it->IsAtEnd(); it->Advance()) { | 512 !it->IsAtEnd(); it->Advance()) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
511 DCHECK(context); | 567 DCHECK(context); |
512 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = | 568 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = |
513 context->GetProviderHostIterator(); | 569 context->GetProviderHostIterator(); |
514 !it->IsAtEnd(); it->Advance()) { | 570 !it->IsAtEnd(); it->Advance()) { |
515 ServiceWorkerProviderHost* host = it->GetProviderHost(); | 571 ServiceWorkerProviderHost* host = it->GetProviderHost(); |
516 host->UnsetVersion(version); | 572 host->UnsetVersion(version); |
517 } | 573 } |
518 } | 574 } |
519 | 575 |
520 } // namespace content | 576 } // namespace content |
OLD | NEW |