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

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

Issue 2027583002: service worker: Avoid starting up for activation during shutdown (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: maybe fix win Created 4 years, 6 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
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_registration.h" 5 #include "content/browser/service_worker/service_worker_registration.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_context_wrapper.h"
10 #include "content/browser/service_worker/service_worker_info.h" 11 #include "content/browser/service_worker/service_worker_info.h"
11 #include "content/browser/service_worker/service_worker_metrics.h" 12 #include "content/browser/service_worker/service_worker_metrics.h"
12 #include "content/browser/service_worker/service_worker_register_job.h" 13 #include "content/browser/service_worker/service_worker_register_job.h"
13 #include "content/common/service_worker/service_worker_messages.h" 14 #include "content/common/service_worker/service_worker_messages.h"
14 #include "content/common/service_worker/service_worker_utils.h" 15 #include "content/common/service_worker/service_worker_utils.h"
15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
16 17
17 namespace content { 18 namespace content {
18 19
19 namespace { 20 namespace {
20 21
21 ServiceWorkerVersionInfo GetVersionInfo(ServiceWorkerVersion* version) { 22 ServiceWorkerVersionInfo GetVersionInfo(ServiceWorkerVersion* version) {
22 if (!version) 23 if (!version)
23 return ServiceWorkerVersionInfo(); 24 return ServiceWorkerVersionInfo();
24 return version->GetInfo(); 25 return version->GetInfo();
25 } 26 }
26 27
28 bool GetShutdownStatusOnUIThread(
29 scoped_refptr<ServiceWorkerContextWrapper> wrapper,
30 ServiceWorkerStatusCode status) {
31 DCHECK_CURRENTLY_ON(BrowserThread::UI);
32 return wrapper->process_manager()->IsShutdown();
33 }
34
27 } // namespace 35 } // namespace
28 36
29 ServiceWorkerRegistration::ServiceWorkerRegistration( 37 ServiceWorkerRegistration::ServiceWorkerRegistration(
30 const GURL& pattern, 38 const GURL& pattern,
31 int64_t registration_id, 39 int64_t registration_id,
32 base::WeakPtr<ServiceWorkerContextCore> context) 40 base::WeakPtr<ServiceWorkerContextCore> context)
33 : pattern_(pattern), 41 : pattern_(pattern),
34 registration_id_(registration_id), 42 registration_id_(registration_id),
35 is_deleted_(false), 43 is_deleted_(false),
36 is_uninstalling_(false), 44 is_uninstalling_(false),
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 active_version_ = NULL; 177 active_version_ = NULL;
170 mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION); 178 mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION);
171 } 179 }
172 } 180 }
173 181
174 void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() { 182 void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
175 DCHECK(waiting_version()); 183 DCHECK(waiting_version());
176 should_activate_when_ready_ = true; 184 should_activate_when_ready_ = true;
177 185
178 if (!active_version() || !active_version()->HasControllee() || 186 if (!active_version() || !active_version()->HasControllee() ||
179 waiting_version()->skip_waiting()) 187 waiting_version()->skip_waiting()) {
180 ActivateWaitingVersion(); 188 ActivateWaitingVersion(false);
189 }
181 } 190 }
182 191
183 void ServiceWorkerRegistration::ClaimClients() { 192 void ServiceWorkerRegistration::ClaimClients() {
184 DCHECK(context_); 193 DCHECK(context_);
185 DCHECK(active_version()); 194 DCHECK(active_version());
186 195
187 for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = 196 for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
188 context_->GetProviderHostIterator(); 197 context_->GetProviderHostIterator();
189 !it->IsAtEnd(); it->Advance()) { 198 !it->IsAtEnd(); it->Advance()) {
190 ServiceWorkerProviderHost* host = it->GetProviderHost(); 199 ServiceWorkerProviderHost* host = it->GetProviderHost();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 most_recent_version)); 245 most_recent_version));
237 } 246 }
238 247
239 void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) { 248 void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
240 if (!context_) 249 if (!context_)
241 return; 250 return;
242 DCHECK_EQ(active_version(), version); 251 DCHECK_EQ(active_version(), version);
243 if (is_uninstalling_) 252 if (is_uninstalling_)
244 Clear(); 253 Clear();
245 else if (should_activate_when_ready_) 254 else if (should_activate_when_ready_)
246 ActivateWaitingVersion(); 255 ActivateWaitingVersion(true);
247 is_uninstalling_ = false; 256 is_uninstalling_ = false;
248 should_activate_when_ready_ = false; 257 should_activate_when_ready_ = false;
249 } 258 }
250 259
251 void ServiceWorkerRegistration::ActivateWaitingVersion() { 260 void ServiceWorkerRegistration::ActivateWaitingVersion(bool delay) {
252 DCHECK(context_); 261 DCHECK(context_);
253 DCHECK(waiting_version()); 262 DCHECK(waiting_version());
254 DCHECK(should_activate_when_ready_); 263 DCHECK(should_activate_when_ready_);
255 should_activate_when_ready_ = false; 264 should_activate_when_ready_ = false;
256 scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version(); 265 scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version();
257 scoped_refptr<ServiceWorkerVersion> exiting_version = active_version(); 266 scoped_refptr<ServiceWorkerVersion> exiting_version = active_version();
258 267
259 if (activating_version->is_redundant()) 268 if (activating_version->is_redundant())
260 return; // Activation is no longer relevant. 269 return; // Activation is no longer relevant.
261 270
(...skipping 14 matching lines...) Expand all
276 SetActiveVersion(activating_version); 285 SetActiveVersion(activating_version);
277 286
278 // "8. Run the [[UpdateState]] algorithm passing registration.activeWorker and 287 // "8. Run the [[UpdateState]] algorithm passing registration.activeWorker and
279 // "activating" as arguments." 288 // "activating" as arguments."
280 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING); 289 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING);
281 // "9. Fire a simple event named controllerchange..." 290 // "9. Fire a simple event named controllerchange..."
282 if (activating_version->skip_waiting()) 291 if (activating_version->skip_waiting())
283 FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this)); 292 FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this));
284 293
285 // "10. Queue a task to fire an event named activate..." 294 // "10. Queue a task to fire an event named activate..."
295 // The browser could be shutting down. To avoid spurious start worker
296 // failures, wait a bit before continuing.
nhiroki 2016/06/01 05:51:47 Let me add this comment just for future reference.
falken 2016/06/01 09:20:05 Acknowledged.
297 if (delay) {
298 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1),
299 base::Bind(&ServiceWorkerRegistration::ContinueActivation,
300 this, activating_version));
301 } else {
302 ContinueActivation(activating_version);
303 }
304 }
305
306 void ServiceWorkerRegistration::ContinueActivation(
307 const scoped_refptr<ServiceWorkerVersion>& activating_version) {
308 if (!context_)
309 return;
310 if (active_version() != activating_version.get())
311 return;
312 DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
286 activating_version->RunAfterStartWorker( 313 activating_version->RunAfterStartWorker(
287 ServiceWorkerMetrics::EventType::ACTIVATE, 314 ServiceWorkerMetrics::EventType::ACTIVATE,
288 base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this, 315 base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this,
289 activating_version), 316 activating_version),
290 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this, 317 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this,
291 activating_version)); 318 activating_version));
292 } 319 }
293 320
294 void ServiceWorkerRegistration::DeleteVersion( 321 void ServiceWorkerRegistration::DeleteVersion(
295 const scoped_refptr<ServiceWorkerVersion>& version) { 322 const scoped_refptr<ServiceWorkerVersion>& version) {
(...skipping 28 matching lines...) Expand all
324 } 351 }
325 } 352 }
326 353
327 void ServiceWorkerRegistration::NotifyRegistrationFinished() { 354 void ServiceWorkerRegistration::NotifyRegistrationFinished() {
328 std::vector<base::Closure> callbacks; 355 std::vector<base::Closure> callbacks;
329 callbacks.swap(registration_finished_callbacks_); 356 callbacks.swap(registration_finished_callbacks_);
330 for (const auto& callback : callbacks) 357 for (const auto& callback : callbacks)
331 callback.Run(); 358 callback.Run();
332 } 359 }
333 360
361 void ServiceWorkerRegistration::SetTimerTaskRunnerForTest(
362 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
363 timer_.SetTaskRunner(task_runner);
nhiroki 2016/06/01 05:51:47 std::move(task_runner) ?
falken 2016/06/01 09:20:05 Done.
364 }
365
334 void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback( 366 void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
335 const base::Closure& callback) { 367 const base::Closure& callback) {
336 // This should only be called if the registration is in progress. 368 // This should only be called if the registration is in progress.
337 DCHECK(!active_version() && !waiting_version() && !is_uninstalled() && 369 DCHECK(!active_version() && !waiting_version() && !is_uninstalled() &&
338 !is_uninstalling()); 370 !is_uninstalling());
339 registration_finished_callbacks_.push_back(callback); 371 registration_finished_callbacks_.push_back(callback);
340 } 372 }
341 373
342 void ServiceWorkerRegistration::DispatchActivateEvent( 374 void ServiceWorkerRegistration::DispatchActivateEvent(
343 const scoped_refptr<ServiceWorkerVersion>& activating_version) { 375 const scoped_refptr<ServiceWorkerVersion>& activating_version) {
(...skipping 10 matching lines...) Expand all
354 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this, 386 base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this,
355 activating_version)); 387 activating_version));
356 activating_version 388 activating_version
357 ->DispatchSimpleEvent<ServiceWorkerHostMsg_ActivateEventFinished>( 389 ->DispatchSimpleEvent<ServiceWorkerHostMsg_ActivateEventFinished>(
358 request_id, ServiceWorkerMsg_ActivateEvent(request_id)); 390 request_id, ServiceWorkerMsg_ActivateEvent(request_id));
359 } 391 }
360 392
361 void ServiceWorkerRegistration::OnActivateEventFinished( 393 void ServiceWorkerRegistration::OnActivateEventFinished(
362 const scoped_refptr<ServiceWorkerVersion>& activating_version, 394 const scoped_refptr<ServiceWorkerVersion>& activating_version,
363 ServiceWorkerStatusCode status) { 395 ServiceWorkerStatusCode status) {
364 if (!context_ || activating_version != active_version() || 396 ServiceWorkerMetrics::RecordActivateEventStatus(status);
365 activating_version->status() != ServiceWorkerVersion::ACTIVATING) 397
398 if (!context_)
366 return; 399 return;
367 400
368 // |status| is just for UMA. Once we've attempted to dispatch the activate 401 if (status == SERVICE_WORKER_OK) {
369 // event to an installed worker, it's committed to becoming active. 402 CompleteActivation(activating_version, status, false);
nhiroki 2016/06/01 05:51:47 Always recording OK w/ |is_shutdown = false| would
falken 2016/06/01 09:20:05 OK I went with checking the state always. I had wa
370 ServiceWorkerMetrics::RecordActivateEventStatus(status); 403 return;
404 }
405
406 // Activate is prone to failing due to shutdown, because it's triggered when
407 // tabs close. Try to detect that case.
408 BrowserThread::PostTaskAndReplyWithResult(
409 BrowserThread::UI, FROM_HERE,
410 base::Bind(&GetShutdownStatusOnUIThread,
411 make_scoped_refptr(context_->wrapper()), status),
412 base::Bind(&ServiceWorkerRegistration::CompleteActivation, this,
413 activating_version, status));
414 }
415
416 void ServiceWorkerRegistration::CompleteActivation(
417 const scoped_refptr<ServiceWorkerVersion>& activating_version,
418 ServiceWorkerStatusCode status,
419 bool is_shutdown) {
420 ServiceWorkerMetrics::RecordActivateEventStatusWithShutdownStatus(
421 status, is_shutdown);
422 if (!context_ || activating_version != active_version() ||
423 activating_version->status() != ServiceWorkerVersion::ACTIVATING) {
424 return;
425 }
426
427 if (is_shutdown) {
428 DCHECK_NE(SERVICE_WORKER_OK, status);
429 return;
430 }
371 431
372 // "Run the Update State algorithm passing registration's active worker and 432 // "Run the Update State algorithm passing registration's active worker and
373 // 'activated' as the arguments." 433 // 'activated' as the arguments."
374 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED); 434 activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
375 context_->storage()->UpdateToActiveState( 435 context_->storage()->UpdateToActiveState(
376 this, base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); 436 this, base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
377 } 437 }
378 438
379 void ServiceWorkerRegistration::OnDeleteFinished( 439 void ServiceWorkerRegistration::OnDeleteFinished(
380 ServiceWorkerStatusCode status) { 440 ServiceWorkerStatusCode status) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 if (!context_) { 488 if (!context_) {
429 callback.Run(SERVICE_WORKER_ERROR_ABORT); 489 callback.Run(SERVICE_WORKER_ERROR_ABORT);
430 return; 490 return;
431 } 491 }
432 context_->storage()->NotifyDoneInstallingRegistration( 492 context_->storage()->NotifyDoneInstallingRegistration(
433 this, version.get(), status); 493 this, version.get(), status);
434 callback.Run(status); 494 callback.Run(status);
435 } 495 }
436 496
437 } // namespace content 497 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698