Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: content/browser/service_worker/service_worker_register_job.cc

Issue 229403004: Assert about ServiceWorkerRegisterJob internal state in terms of phases (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more assert Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "content/browser/service_worker/service_worker_context_core.h" 9 #include "content/browser/service_worker/service_worker_context_core.h"
10 #include "content/browser/service_worker/service_worker_job_coordinator.h" 10 #include "content/browser/service_worker/service_worker_job_coordinator.h"
11 #include "content/browser/service_worker/service_worker_registration.h" 11 #include "content/browser/service_worker/service_worker_registration.h"
12 #include "content/browser/service_worker/service_worker_storage.h" 12 #include "content/browser/service_worker/service_worker_storage.h"
13 13
14 namespace content { 14 namespace content {
15 15
16 typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType; 16 typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType;
17 17
18 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( 18 ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
19 base::WeakPtr<ServiceWorkerContextCore> context, 19 base::WeakPtr<ServiceWorkerContextCore> context,
20 const GURL& pattern, 20 const GURL& pattern,
21 const GURL& script_url) 21 const GURL& script_url)
22 : context_(context), 22 : context_(context),
23 pattern_(pattern), 23 pattern_(pattern),
24 script_url_(script_url), 24 script_url_(script_url),
25 phase_(INITIAL),
25 weak_factory_(this) {} 26 weak_factory_(this) {}
26 27
27 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {} 28 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {}
28 29
29 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback, 30 void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback,
30 int process_id) { 31 int process_id) {
31 // If we've created a pending version, associate source_provider it with that, 32 // If we've created a pending version, associate source_provider it with that,
32 // otherwise queue it up. 33 // otherwise queue it up.
33 callbacks_.push_back(callback); 34 callbacks_.push_back(callback);
34 DCHECK_NE(-1, process_id); 35 DCHECK_NE(-1, process_id);
35 if (pending_version_) { 36 if (phase_ >= UPDATE && pending_version()) {
36 pending_version_->AddProcessToWorker(process_id); 37 pending_version()->AddProcessToWorker(process_id);
37 } else { 38 } else {
38 pending_process_ids_.push_back(process_id); 39 pending_process_ids_.push_back(process_id);
39 } 40 }
40 } 41 }
41 42
42 void ServiceWorkerRegisterJob::Start() { 43 void ServiceWorkerRegisterJob::Start() {
44 phase_ = START;
dominicc (has gone to gerrit) 2014/04/09 00:09:58 It would be nice to have SetPhase which DCHECKs th
falken 2014/04/09 01:33:20 Done.
43 context_->storage()->FindRegistrationForPattern( 45 context_->storage()->FindRegistrationForPattern(
44 pattern_, 46 pattern_,
45 base::Bind( 47 base::Bind(
46 &ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue, 48 &ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue,
47 weak_factory_.GetWeakPtr())); 49 weak_factory_.GetWeakPtr()));
48 } 50 }
49 51
50 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) { 52 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) {
51 if (job->GetType() != GetType()) 53 if (job->GetType() != GetType())
52 return false; 54 return false;
53 ServiceWorkerRegisterJob* register_job = 55 ServiceWorkerRegisterJob* register_job =
54 static_cast<ServiceWorkerRegisterJob*>(job); 56 static_cast<ServiceWorkerRegisterJob*>(job);
55 return register_job->pattern_ == pattern_ && 57 return register_job->pattern_ == pattern_ &&
56 register_job->script_url_ == script_url_; 58 register_job->script_url_ == script_url_;
57 } 59 }
58 60
59 RegistrationJobType ServiceWorkerRegisterJob::GetType() { 61 RegistrationJobType ServiceWorkerRegisterJob::GetType() {
60 return REGISTER; 62 return REGISTRATION;
63 }
64
65 void ServiceWorkerRegisterJob::set_registration(
66 ServiceWorkerRegistration* registration) {
67 DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
68 DCHECK(!internal_.registration_);
69 internal_.registration_ = registration;
70 }
71
72 ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
73 DCHECK(phase_ >= REGISTER) << phase_;
74 DCHECK(internal_.registration_);
75 return internal_.registration_;
76 }
77
78 void ServiceWorkerRegisterJob::set_pending_version(
79 ServiceWorkerVersion* version) {
80 DCHECK(phase_ == UPDATE || phase_ == ACTIVATE) << phase_;
81 DCHECK(!internal_.pending_version_ || !version);
82 internal_.pending_version_ = version;
83 }
84
85 ServiceWorkerVersion* ServiceWorkerRegisterJob::pending_version() {
86 DCHECK(phase_ >= UPDATE) << phase_;
87 return internal_.pending_version_;
61 } 88 }
62 89
63 // This function corresponds to the steps in Register following 90 // This function corresponds to the steps in Register following
64 // "Let serviceWorkerRegistration be _GetRegistration(scope)" 91 // "Let serviceWorkerRegistration be _GetRegistration(scope)"
65 // |registration| corresponds to serviceWorkerRegistration. 92 // |existing_registration| corresponds to serviceWorkerRegistration.
66 // Throughout this file, comments in quotes are excerpts from the spec. 93 // Throughout this file, comments in quotes are excerpts from the spec.
67 void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue( 94 void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue(
68 ServiceWorkerStatusCode status, 95 ServiceWorkerStatusCode status,
69 const scoped_refptr<ServiceWorkerRegistration>& registration) { 96 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
70 // On unexpected error, abort this registration job. 97 // On unexpected error, abort this registration job.
71 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) { 98 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) {
72 Complete(status); 99 Complete(status);
73 return; 100 return;
74 } 101 }
75 102
76 // "If serviceWorkerRegistration is not null and script is equal to 103 // "If serviceWorkerRegistration is not null and script is equal to
77 // serviceWorkerRegistration.scriptUrl..." resolve with the existing 104 // serviceWorkerRegistration.scriptUrl..." resolve with the existing
78 // registration and abort. 105 // registration and abort.
79 if (registration.get() && registration->script_url() == script_url_) { 106 if (existing_registration.get() &&
80 registration_ = registration; 107 existing_registration->script_url() == script_url_) {
108 set_registration(existing_registration);
81 // If there's no active version, go ahead to Update (this isn't in the spec 109 // If there's no active version, go ahead to Update (this isn't in the spec
82 // but seems reasonable, and without SoftUpdate implemented we can never 110 // but seems reasonable, and without SoftUpdate implemented we can never
83 // Update otherwise). 111 // Update otherwise).
84 if (!registration_->active_version()) { 112 if (!existing_registration->active_version()) {
85 UpdateAndContinue(status); 113 UpdateAndContinue(status);
86 return; 114 return;
87 } 115 }
88 RunCallbacks(status, registration_->active_version()); 116 RunCallbacks(status, existing_registration->active_version());
89 Complete(SERVICE_WORKER_OK); 117 Complete(SERVICE_WORKER_OK);
90 return; 118 return;
91 } 119 }
92 120
93 // "If serviceWorkerRegistration is null..." create a new registration. 121 // "If serviceWorkerRegistration is null..." create a new registration.
94 if (!registration.get()) { 122 if (!existing_registration.get()) {
95 RegisterAndContinue(SERVICE_WORKER_OK); 123 RegisterAndContinue(SERVICE_WORKER_OK);
96 return; 124 return;
97 } 125 }
98 126
99 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to 127 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to
100 // script." We accomplish this by deleting the existing registration and 128 // script." We accomplish this by deleting the existing registration and
101 // registering a new one. 129 // registering a new one.
102 // TODO(falken): Match the spec. We now throw away the active_version_ and 130 // TODO(falken): Match the spec. We now throw away the active_version_ and
103 // pending_version_ of the existing registration, which isn't in the spec. 131 // pending_version_ of the existing registration, which isn't in the spec.
104 registration->Shutdown(); 132 existing_registration->Shutdown();
105 context_->storage()->DeleteRegistration( 133 context_->storage()->DeleteRegistration(
106 pattern_, 134 pattern_,
107 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, 135 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue,
108 weak_factory_.GetWeakPtr())); 136 weak_factory_.GetWeakPtr()));
109 } 137 }
110 138
111 // Registers a new ServiceWorkerRegistration. 139 // Registers a new ServiceWorkerRegistration.
112 void ServiceWorkerRegisterJob::RegisterAndContinue( 140 void ServiceWorkerRegisterJob::RegisterAndContinue(
113 ServiceWorkerStatusCode status) { 141 ServiceWorkerStatusCode status) {
114 DCHECK(!registration_); 142 phase_ = REGISTER;
115 if (status != SERVICE_WORKER_OK) { 143 if (status != SERVICE_WORKER_OK) {
116 // Abort this registration job. 144 // Abort this registration job.
117 Complete(status); 145 Complete(status);
118 return; 146 return;
119 } 147 }
120 148
121 registration_ = new ServiceWorkerRegistration( 149 set_registration(new ServiceWorkerRegistration(
122 pattern_, script_url_, context_->storage()->NewRegistrationId(), 150 pattern_, script_url_, context_->storage()->NewRegistrationId(),
123 context_); 151 context_));
124 context_->storage()->StoreRegistration( 152 context_->storage()->StoreRegistration(
125 registration_.get(), 153 registration(),
126 base::Bind(&ServiceWorkerRegisterJob::UpdateAndContinue, 154 base::Bind(&ServiceWorkerRegisterJob::UpdateAndContinue,
127 weak_factory_.GetWeakPtr())); 155 weak_factory_.GetWeakPtr()));
128 } 156 }
129 157
130 // This function corresponds to the spec's _Update algorithm. 158 // This function corresponds to the spec's _Update algorithm.
131 void ServiceWorkerRegisterJob::UpdateAndContinue( 159 void ServiceWorkerRegisterJob::UpdateAndContinue(
132 ServiceWorkerStatusCode status) { 160 ServiceWorkerStatusCode status) {
133 DCHECK(registration_); 161 phase_ = UPDATE;
134 if (status != SERVICE_WORKER_OK) { 162 if (status != SERVICE_WORKER_OK) {
135 // Abort this registration job. 163 // Abort this registration job.
136 Complete(status); 164 Complete(status);
137 return; 165 return;
138 } 166 }
139 167
140 // TODO: "If serviceWorkerRegistration.pendingWorker is not null..." then 168 // TODO: "If serviceWorkerRegistration.pendingWorker is not null..." then
141 // terminate the pending worker. It doesn't make sense to implement yet since 169 // terminate the pending worker. It doesn't make sense to implement yet since
142 // we always activate the worker if install completed, so there can be no 170 // we always activate the worker if install completed, so there can be no
143 // pending worker at this point. 171 // pending worker at this point.
144 DCHECK(!registration_->pending_version()); 172 DCHECK(!registration()->pending_version());
145 173
146 // TODO: Script fetching and comparing the old and new script belongs here. 174 // TODO: Script fetching and comparing the old and new script belongs here.
147 175
148 // "Let serviceWorker be a newly-created ServiceWorker object..." and start 176 // "Let serviceWorker be a newly-created ServiceWorker object..." and start
149 // the worker. 177 // the worker.
150 pending_version_ = new ServiceWorkerVersion( 178 set_pending_version(new ServiceWorkerVersion(
151 registration_, context_->storage()->NewVersionId(), context_); 179 registration(), context_->storage()->NewVersionId(), context_));
152 for (std::vector<int>::const_iterator it = pending_process_ids_.begin(); 180 for (std::vector<int>::const_iterator it = pending_process_ids_.begin();
153 it != pending_process_ids_.end(); 181 it != pending_process_ids_.end();
154 ++it) 182 ++it)
155 pending_version_->AddProcessToWorker(*it); 183 pending_version()->AddProcessToWorker(*it);
156 184
157 pending_version_->StartWorker( 185 pending_version()->StartWorker(
158 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, 186 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished,
159 weak_factory_.GetWeakPtr())); 187 weak_factory_.GetWeakPtr()));
160 } 188 }
161 189
162 void ServiceWorkerRegisterJob::OnStartWorkerFinished( 190 void ServiceWorkerRegisterJob::OnStartWorkerFinished(
163 ServiceWorkerStatusCode status) { 191 ServiceWorkerStatusCode status) {
164 // "If serviceWorker fails to start up..." then reject the promise with an 192 // "If serviceWorker fails to start up..." then reject the promise with an
165 // error and abort. 193 // error and abort.
166 if (status != SERVICE_WORKER_OK) { 194 if (status != SERVICE_WORKER_OK) {
167 Complete(status); 195 Complete(status);
168 return; 196 return;
169 } 197 }
170 198
171 // "Resolve promise with serviceWorker." 199 // "Resolve promise with serviceWorker."
172 // Although the spec doesn't set pendingWorker until after resolving the 200 // Although the spec doesn't set pendingWorker until after resolving the
173 // promise, our system's resolving works by passing ServiceWorkerRegistration 201 // promise, our system's resolving works by passing ServiceWorkerRegistration
174 // to the callbacks, so pendingWorker must be set first. 202 // to the callbacks, so pendingWorker must be set first.
175 DCHECK(!registration_->pending_version()); 203 DCHECK(!registration()->pending_version());
176 registration_->set_pending_version(pending_version_); 204 registration()->set_pending_version(pending_version());
177 RunCallbacks(status, pending_version_.get()); 205 RunCallbacks(status, pending_version());
178 206
179 InstallAndContinue(); 207 InstallAndContinue();
180 } 208 }
181 209
182 // This function corresponds to the spec's _Install algorithm. 210 // This function corresponds to the spec's _Install algorithm.
183 void ServiceWorkerRegisterJob::InstallAndContinue() { 211 void ServiceWorkerRegisterJob::InstallAndContinue() {
212 phase_ = INSTALL;
184 // "Set serviceWorkerRegistration.pendingWorker._state to installing." 213 // "Set serviceWorkerRegistration.pendingWorker._state to installing."
185 // "Fire install event on the associated ServiceWorkerGlobalScope object." 214 // "Fire install event on the associated ServiceWorkerGlobalScope object."
186 pending_version_->DispatchInstallEvent( 215 pending_version()->DispatchInstallEvent(
187 -1, 216 -1,
188 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, 217 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
189 weak_factory_.GetWeakPtr())); 218 weak_factory_.GetWeakPtr()));
190 } 219 }
191 220
192 void ServiceWorkerRegisterJob::OnInstallFinished( 221 void ServiceWorkerRegisterJob::OnInstallFinished(
193 ServiceWorkerStatusCode status) { 222 ServiceWorkerStatusCode status) {
194 // "If any handler called waitUntil()..." and the resulting promise 223 // "If any handler called waitUntil()..." and the resulting promise
195 // is rejected, abort. 224 // is rejected, abort.
196 if (status != SERVICE_WORKER_OK) { 225 if (status != SERVICE_WORKER_OK) {
197 registration_->set_pending_version(NULL); 226 registration()->set_pending_version(NULL);
198 Complete(status); 227 Complete(status);
199 return; 228 return;
200 } 229 }
201 230
202 // TODO: Per spec, only activate if no document is using the registration. 231 // TODO: Per spec, only activate if no document is using the registration.
203 ActivateAndContinue(); 232 ActivateAndContinue();
204 } 233 }
205 234
206 // This function corresponds to the spec's _Activate algorithm. 235 // This function corresponds to the spec's _Activate algorithm.
207 void ServiceWorkerRegisterJob::ActivateAndContinue() { 236 void ServiceWorkerRegisterJob::ActivateAndContinue() {
237 phase_ = ACTIVATE;
208 // "Set serviceWorkerRegistration.pendingWorker to null." 238 // "Set serviceWorkerRegistration.pendingWorker to null."
209 registration_->set_pending_version(NULL); 239 registration()->set_pending_version(NULL);
210 240
211 // TODO: Dispatch the activate event. 241 // TODO: Dispatch the activate event.
212 // TODO(michaeln): Persist the newly ACTIVE version. 242 // TODO(michaeln): Persist the newly ACTIVE version.
213 pending_version_->SetStatus(ServiceWorkerVersion::ACTIVE); 243 pending_version()->SetStatus(ServiceWorkerVersion::ACTIVE);
214 DCHECK(!registration_->active_version()); 244 DCHECK(!registration()->active_version());
215 registration_->set_active_version(pending_version_); 245 registration()->set_active_version(pending_version());
216 pending_version_ = NULL; 246 set_pending_version(NULL);
217 Complete(SERVICE_WORKER_OK); 247 Complete(SERVICE_WORKER_OK);
218 } 248 }
219 249
220 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { 250 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
251 phase_ = COMPLETE;
221 // In success case the callbacks must have been dispatched already 252 // In success case the callbacks must have been dispatched already
222 // (so this is no-op), otherwise we must have come here for abort case, 253 // (so this is no-op), otherwise we must have come here for abort case,
223 // so dispatch callbacks with NULL. 254 // so dispatch callbacks with NULL.
224 DCHECK(callbacks_.empty() || status != SERVICE_WORKER_OK); 255 DCHECK(callbacks_.empty() || status != SERVICE_WORKER_OK);
225 RunCallbacks(status, NULL); 256 RunCallbacks(status, NULL);
226 257
227 // If |pending_version_| exists, it was not activated, so we are the sole 258 // If |pending_version| exists, it was not activated, so we are the sole
228 // owner of it, so it will be destroyed when this job ends, so Shutdown here. 259 // owner of it, so it will be destroyed when this job ends, so Shutdown here.
229 // We should be able to remove this code later, when something else holds a 260 // We should be able to remove this code later, when something else holds a
230 // reference to |pending_version_|. 261 // reference to |pending_version_|.
231 // TODO(kinuko): Fix these ownership and shutdown semantics. 262 // TODO(kinuko): Fix these ownership and shutdown semantics.
232 if (pending_version_) { 263 if (pending_version()) {
233 DCHECK(!registration_->pending_version()); 264 DCHECK(status != SERVICE_WORKER_OK);
234 DCHECK(!registration_->active_version()); 265 DCHECK(!registration()->pending_version());
235 pending_version_->Shutdown(); 266 DCHECK(!registration()->active_version());
267 pending_version()->Shutdown();
236 } 268 }
237 269
238 context_->job_coordinator()->FinishJob(pattern_, this); 270 context_->job_coordinator()->FinishJob(pattern_, this);
239 } 271 }
240 272
241 void ServiceWorkerRegisterJob::RunCallbacks(ServiceWorkerStatusCode status, 273 void ServiceWorkerRegisterJob::RunCallbacks(ServiceWorkerStatusCode status,
242 ServiceWorkerVersion* version) { 274 ServiceWorkerVersion* version) {
243 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); 275 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
244 it != callbacks_.end(); 276 it != callbacks_.end();
245 ++it) { 277 ++it) {
246 it->Run(status, version); 278 it->Run(status, version);
247 } 279 }
248 callbacks_.clear(); 280 callbacks_.clear();
249 } 281 }
250 282
251 } // namespace content 283 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698