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

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: fix ctor/dtor style error and bad merge 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 SetPhase(START);
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 ServiceWorkerRegisterJob::Internal::Internal() {}
66
67 ServiceWorkerRegisterJob::Internal::~Internal() {}
68
69 void ServiceWorkerRegisterJob::set_registration(
70 ServiceWorkerRegistration* registration) {
71 DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
72 DCHECK(!internal_.registration);
73 internal_.registration = registration;
74 }
75
76 ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
77 DCHECK(phase_ >= REGISTER) << phase_;
78 DCHECK(internal_.registration);
79 return internal_.registration;
80 }
81
82 void ServiceWorkerRegisterJob::set_pending_version(
83 ServiceWorkerVersion* version) {
84 DCHECK(phase_ == UPDATE || phase_ == ACTIVATE) << phase_;
85 DCHECK(!internal_.pending_version || !version);
86 internal_.pending_version = version;
87 }
88
89 ServiceWorkerVersion* ServiceWorkerRegisterJob::pending_version() {
90 DCHECK(phase_ >= UPDATE) << phase_;
91 return internal_.pending_version;
92 }
93
94 void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
95 switch (phase) {
96 case INITIAL:
97 NOTREACHED();
98 break;
99 case START:
100 DCHECK(phase_ == INITIAL) << phase_;
101 break;
102 case REGISTER:
103 DCHECK(phase_ == START) << phase_;
104 break;
105 case UPDATE:
106 DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
107 break;
108 case INSTALL:
109 DCHECK(phase_ == UPDATE) << phase_;
110 break;
111 case ACTIVATE:
112 DCHECK(phase_ == INSTALL) << phase_;
113 break;
114 case COMPLETE:
115 DCHECK(phase_ != INITIAL && phase_ != COMPLETE) << phase_;
116 break;
117 }
118 phase_ = phase;
61 } 119 }
62 120
63 // This function corresponds to the steps in Register following 121 // This function corresponds to the steps in Register following
64 // "Let serviceWorkerRegistration be _GetRegistration(scope)" 122 // "Let serviceWorkerRegistration be _GetRegistration(scope)"
65 // |registration| corresponds to serviceWorkerRegistration. 123 // |existing_registration| corresponds to serviceWorkerRegistration.
66 // Throughout this file, comments in quotes are excerpts from the spec. 124 // Throughout this file, comments in quotes are excerpts from the spec.
67 void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue( 125 void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue(
68 ServiceWorkerStatusCode status, 126 ServiceWorkerStatusCode status,
69 const scoped_refptr<ServiceWorkerRegistration>& registration) { 127 const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
70 // On unexpected error, abort this registration job. 128 // On unexpected error, abort this registration job.
71 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) { 129 if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) {
72 Complete(status); 130 Complete(status);
73 return; 131 return;
74 } 132 }
75 133
76 // "If serviceWorkerRegistration is not null and script is equal to 134 // "If serviceWorkerRegistration is not null and script is equal to
77 // serviceWorkerRegistration.scriptUrl..." resolve with the existing 135 // serviceWorkerRegistration.scriptUrl..." resolve with the existing
78 // registration and abort. 136 // registration and abort.
79 if (registration.get() && registration->script_url() == script_url_) { 137 if (existing_registration.get() &&
80 registration_ = registration; 138 existing_registration->script_url() == script_url_) {
139 set_registration(existing_registration);
81 // If there's no active version, go ahead to Update (this isn't in the spec 140 // 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 141 // but seems reasonable, and without SoftUpdate implemented we can never
83 // Update otherwise). 142 // Update otherwise).
84 if (!registration_->active_version()) { 143 if (!existing_registration->active_version()) {
85 UpdateAndContinue(status); 144 UpdateAndContinue(status);
86 return; 145 return;
87 } 146 }
88 RunCallbacks(status, registration_, registration_->active_version()); 147 RunCallbacks(
148 status, existing_registration, existing_registration->active_version());
89 Complete(SERVICE_WORKER_OK); 149 Complete(SERVICE_WORKER_OK);
90 return; 150 return;
91 } 151 }
92 152
93 // "If serviceWorkerRegistration is null..." create a new registration. 153 // "If serviceWorkerRegistration is null..." create a new registration.
94 if (!registration.get()) { 154 if (!existing_registration.get()) {
95 RegisterAndContinue(SERVICE_WORKER_OK); 155 RegisterAndContinue(SERVICE_WORKER_OK);
96 return; 156 return;
97 } 157 }
98 158
99 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to 159 // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to
100 // script." We accomplish this by deleting the existing registration and 160 // script." We accomplish this by deleting the existing registration and
101 // registering a new one. 161 // registering a new one.
102 // TODO(falken): Match the spec. We now throw away the active_version_ and 162 // 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. 163 // pending_version_ of the existing registration, which isn't in the spec.
104 context_->storage()->DeleteRegistration( 164 context_->storage()->DeleteRegistration(
105 pattern_, 165 pattern_,
106 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue, 166 base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue,
107 weak_factory_.GetWeakPtr())); 167 weak_factory_.GetWeakPtr()));
108 } 168 }
109 169
110 // Registers a new ServiceWorkerRegistration. 170 // Registers a new ServiceWorkerRegistration.
111 void ServiceWorkerRegisterJob::RegisterAndContinue( 171 void ServiceWorkerRegisterJob::RegisterAndContinue(
112 ServiceWorkerStatusCode status) { 172 ServiceWorkerStatusCode status) {
113 DCHECK(!registration_); 173 SetPhase(REGISTER);
114 if (status != SERVICE_WORKER_OK) { 174 if (status != SERVICE_WORKER_OK) {
115 // Abort this registration job. 175 // Abort this registration job.
116 Complete(status); 176 Complete(status);
117 return; 177 return;
118 } 178 }
119 179
120 registration_ = new ServiceWorkerRegistration( 180 set_registration(new ServiceWorkerRegistration(
121 pattern_, script_url_, context_->storage()->NewRegistrationId(), 181 pattern_, script_url_, context_->storage()->NewRegistrationId(),
122 context_); 182 context_));
123 context_->storage()->StoreRegistration( 183 context_->storage()->StoreRegistration(
124 registration_.get(), 184 registration(),
125 base::Bind(&ServiceWorkerRegisterJob::UpdateAndContinue, 185 base::Bind(&ServiceWorkerRegisterJob::UpdateAndContinue,
126 weak_factory_.GetWeakPtr())); 186 weak_factory_.GetWeakPtr()));
127 } 187 }
128 188
129 // This function corresponds to the spec's _Update algorithm. 189 // This function corresponds to the spec's _Update algorithm.
130 void ServiceWorkerRegisterJob::UpdateAndContinue( 190 void ServiceWorkerRegisterJob::UpdateAndContinue(
131 ServiceWorkerStatusCode status) { 191 ServiceWorkerStatusCode status) {
132 DCHECK(registration_); 192 SetPhase(UPDATE);
133 if (status != SERVICE_WORKER_OK) { 193 if (status != SERVICE_WORKER_OK) {
134 // Abort this registration job. 194 // Abort this registration job.
135 Complete(status); 195 Complete(status);
136 return; 196 return;
137 } 197 }
138 198
139 // TODO: "If serviceWorkerRegistration.pendingWorker is not null..." then 199 // TODO: "If serviceWorkerRegistration.pendingWorker is not null..." then
140 // terminate the pending worker. It doesn't make sense to implement yet since 200 // terminate the pending worker. It doesn't make sense to implement yet since
141 // we always activate the worker if install completed, so there can be no 201 // we always activate the worker if install completed, so there can be no
142 // pending worker at this point. 202 // pending worker at this point.
143 DCHECK(!registration_->pending_version()); 203 DCHECK(!registration()->pending_version());
144 204
145 // TODO: Script fetching and comparing the old and new script belongs here. 205 // TODO: Script fetching and comparing the old and new script belongs here.
146 206
147 // "Let serviceWorker be a newly-created ServiceWorker object..." and start 207 // "Let serviceWorker be a newly-created ServiceWorker object..." and start
148 // the worker. 208 // the worker.
149 pending_version_ = new ServiceWorkerVersion( 209 set_pending_version(new ServiceWorkerVersion(
150 registration_, context_->storage()->NewVersionId(), context_); 210 registration(), context_->storage()->NewVersionId(), context_));
151 for (std::vector<int>::const_iterator it = pending_process_ids_.begin(); 211 for (std::vector<int>::const_iterator it = pending_process_ids_.begin();
152 it != pending_process_ids_.end(); 212 it != pending_process_ids_.end();
153 ++it) 213 ++it)
154 pending_version_->AddProcessToWorker(*it); 214 pending_version()->AddProcessToWorker(*it);
155 215
156 pending_version_->StartWorker( 216 pending_version()->StartWorker(
157 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished, 217 base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished,
158 weak_factory_.GetWeakPtr())); 218 weak_factory_.GetWeakPtr()));
159 } 219 }
160 220
161 void ServiceWorkerRegisterJob::OnStartWorkerFinished( 221 void ServiceWorkerRegisterJob::OnStartWorkerFinished(
162 ServiceWorkerStatusCode status) { 222 ServiceWorkerStatusCode status) {
163 // "If serviceWorker fails to start up..." then reject the promise with an 223 // "If serviceWorker fails to start up..." then reject the promise with an
164 // error and abort. 224 // error and abort.
165 if (status != SERVICE_WORKER_OK) { 225 if (status != SERVICE_WORKER_OK) {
166 Complete(status); 226 Complete(status);
167 return; 227 return;
168 } 228 }
169 229
170 // "Resolve promise with serviceWorker." 230 // "Resolve promise with serviceWorker."
171 // Although the spec doesn't set pendingWorker until after resolving the 231 // Although the spec doesn't set pendingWorker until after resolving the
172 // promise, our system's resolving works by passing ServiceWorkerRegistration 232 // promise, our system's resolving works by passing ServiceWorkerRegistration
173 // to the callbacks, so pendingWorker must be set first. 233 // to the callbacks, so pendingWorker must be set first.
174 DCHECK(!registration_->pending_version()); 234 DCHECK(!registration()->pending_version());
175 registration_->set_pending_version(pending_version_); 235 registration()->set_pending_version(pending_version());
176 RunCallbacks(status, registration_, pending_version_.get()); 236 RunCallbacks(status, registration(), pending_version());
177 237
178 // TODO(kinuko): Iterate over all provider hosts and call SetPendingVersion() 238 // TODO(kinuko): Iterate over all provider hosts and call SetPendingVersion()
179 // for documents that are in-scope. 239 // for documents that are in-scope.
180 240
181 InstallAndContinue(); 241 InstallAndContinue();
182 } 242 }
183 243
184 // This function corresponds to the spec's _Install algorithm. 244 // This function corresponds to the spec's _Install algorithm.
185 void ServiceWorkerRegisterJob::InstallAndContinue() { 245 void ServiceWorkerRegisterJob::InstallAndContinue() {
246 SetPhase(INSTALL);
186 // "Set serviceWorkerRegistration.pendingWorker._state to installing." 247 // "Set serviceWorkerRegistration.pendingWorker._state to installing."
187 // "Fire install event on the associated ServiceWorkerGlobalScope object." 248 // "Fire install event on the associated ServiceWorkerGlobalScope object."
188 pending_version_->DispatchInstallEvent( 249 pending_version()->DispatchInstallEvent(
189 -1, 250 -1,
190 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, 251 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
191 weak_factory_.GetWeakPtr())); 252 weak_factory_.GetWeakPtr()));
192 } 253 }
193 254
194 void ServiceWorkerRegisterJob::OnInstallFinished( 255 void ServiceWorkerRegisterJob::OnInstallFinished(
195 ServiceWorkerStatusCode status) { 256 ServiceWorkerStatusCode status) {
196 // "If any handler called waitUntil()..." and the resulting promise 257 // "If any handler called waitUntil()..." and the resulting promise
197 // is rejected, abort. 258 // is rejected, abort.
198 if (status != SERVICE_WORKER_OK) { 259 if (status != SERVICE_WORKER_OK) {
199 registration_->set_pending_version(NULL); 260 registration()->set_pending_version(NULL);
200 Complete(status); 261 Complete(status);
201 return; 262 return;
202 } 263 }
203 264
204 // TODO: Per spec, only activate if no document is using the registration. 265 // TODO: Per spec, only activate if no document is using the registration.
205 ActivateAndContinue(); 266 ActivateAndContinue();
206 } 267 }
207 268
208 // This function corresponds to the spec's _Activate algorithm. 269 // This function corresponds to the spec's _Activate algorithm.
209 void ServiceWorkerRegisterJob::ActivateAndContinue() { 270 void ServiceWorkerRegisterJob::ActivateAndContinue() {
271 SetPhase(ACTIVATE);
210 // "Set serviceWorkerRegistration.pendingWorker to null." 272 // "Set serviceWorkerRegistration.pendingWorker to null."
211 registration_->set_pending_version(NULL); 273 registration()->set_pending_version(NULL);
212 274
213 // TODO: Dispatch the activate event. 275 // TODO: Dispatch the activate event.
214 // TODO(michaeln): Persist the newly ACTIVE version. 276 // TODO(michaeln): Persist the newly ACTIVE version.
215 pending_version_->SetStatus(ServiceWorkerVersion::ACTIVE); 277 pending_version()->SetStatus(ServiceWorkerVersion::ACTIVE);
216 DCHECK(!registration_->active_version()); 278 DCHECK(!registration()->active_version());
217 registration_->set_active_version(pending_version_); 279 registration()->set_active_version(pending_version());
218 pending_version_ = NULL; 280 set_pending_version(NULL);
219 Complete(SERVICE_WORKER_OK); 281 Complete(SERVICE_WORKER_OK);
220 } 282 }
221 283
222 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { 284 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
285 SetPhase(COMPLETE);
223 // In success case the callbacks must have been dispatched already 286 // In success case the callbacks must have been dispatched already
224 // (so this is no-op), otherwise we must have come here for abort case, 287 // (so this is no-op), otherwise we must have come here for abort case,
225 // so dispatch callbacks with NULL. 288 // so dispatch callbacks with NULL.
226 DCHECK(callbacks_.empty() || status != SERVICE_WORKER_OK); 289 DCHECK(callbacks_.empty() || status != SERVICE_WORKER_OK);
227 RunCallbacks(status, NULL, NULL); 290 RunCallbacks(status, NULL, NULL);
228 291
229 context_->job_coordinator()->FinishJob(pattern_, this); 292 context_->job_coordinator()->FinishJob(pattern_, this);
230 } 293 }
231 294
232 void ServiceWorkerRegisterJob::RunCallbacks( 295 void ServiceWorkerRegisterJob::RunCallbacks(
233 ServiceWorkerStatusCode status, 296 ServiceWorkerStatusCode status,
234 ServiceWorkerRegistration* registration, 297 ServiceWorkerRegistration* registration,
235 ServiceWorkerVersion* version) { 298 ServiceWorkerVersion* version) {
236 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); 299 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
237 it != callbacks_.end(); 300 it != callbacks_.end();
238 ++it) { 301 ++it) {
239 it->Run(status, registration, version); 302 it->Run(status, registration, version);
240 } 303 }
241 callbacks_.clear(); 304 callbacks_.clear();
242 } 305 }
243 306
244 } // namespace content 307 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698