Chromium Code Reviews

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

Issue 845313004: Service Worker: Improve error messages from register(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git-cl format Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 "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 #include "content/common/service_worker/service_worker_types.h"
15 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
16 17
17 namespace content { 18 namespace content {
18 19
19 namespace { 20 namespace {
20 21
21 void RunSoon(const base::Closure& closure) { 22 void RunSoon(const base::Closure& closure) {
22 base::MessageLoop::current()->PostTask(FROM_HERE, closure); 23 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
23 } 24 }
24 25
(...skipping 39 matching lines...)
64 65
65 void ServiceWorkerRegisterJob::AddCallback( 66 void ServiceWorkerRegisterJob::AddCallback(
66 const RegistrationCallback& callback, 67 const RegistrationCallback& callback,
67 ServiceWorkerProviderHost* provider_host) { 68 ServiceWorkerProviderHost* provider_host) {
68 if (!is_promise_resolved_) { 69 if (!is_promise_resolved_) {
69 callbacks_.push_back(callback); 70 callbacks_.push_back(callback);
70 if (provider_host) 71 if (provider_host)
71 provider_host->AddScopedProcessReferenceToPattern(pattern_); 72 provider_host->AddScopedProcessReferenceToPattern(pattern_);
72 return; 73 return;
73 } 74 }
74 RunSoon(base::Bind( 75 RunSoon(base::Bind(callback, promise_resolved_status_,
75 callback, promise_resolved_status_, promise_resolved_registration_)); 76 promise_resolved_status_message_,
77 promise_resolved_registration_));
76 } 78 }
77 79
78 void ServiceWorkerRegisterJob::Start() { 80 void ServiceWorkerRegisterJob::Start() {
79 SetPhase(START); 81 SetPhase(START);
80 ServiceWorkerStorage::FindRegistrationCallback next_step; 82 ServiceWorkerStorage::FindRegistrationCallback next_step;
81 if (job_type_ == REGISTRATION_JOB) { 83 if (job_type_ == REGISTRATION_JOB) {
82 next_step = base::Bind( 84 next_step = base::Bind(
83 &ServiceWorkerRegisterJob::ContinueWithRegistration, 85 &ServiceWorkerRegisterJob::ContinueWithRegistration,
84 weak_factory_.GetWeakPtr()); 86 weak_factory_.GetWeakPtr());
85 } else { 87 } else {
86 next_step = base::Bind( 88 next_step = base::Bind(
87 &ServiceWorkerRegisterJob::ContinueWithUpdate, 89 &ServiceWorkerRegisterJob::ContinueWithUpdate,
88 weak_factory_.GetWeakPtr()); 90 weak_factory_.GetWeakPtr());
89 } 91 }
90 92
91 scoped_refptr<ServiceWorkerRegistration> registration = 93 scoped_refptr<ServiceWorkerRegistration> registration =
92 context_->storage()->GetUninstallingRegistration(pattern_); 94 context_->storage()->GetUninstallingRegistration(pattern_);
93 if (registration.get()) 95 if (registration.get())
94 RunSoon(base::Bind(next_step, SERVICE_WORKER_OK, registration)); 96 RunSoon(base::Bind(next_step, SERVICE_WORKER_OK, registration));
95 else 97 else
96 context_->storage()->FindRegistrationForPattern(pattern_, next_step); 98 context_->storage()->FindRegistrationForPattern(pattern_, next_step);
97 } 99 }
98 100
99 void ServiceWorkerRegisterJob::Abort() { 101 void ServiceWorkerRegisterJob::Abort() {
100 SetPhase(ABORT); 102 SetPhase(ABORT);
101 CompleteInternal(SERVICE_WORKER_ERROR_ABORT); 103 CompleteInternal(SERVICE_WORKER_ERROR_ABORT, std::string());
102 // Don't have to call FinishJob() because the caller takes care of removing 104 // Don't have to call FinishJob() because the caller takes care of removing
103 // the jobs from the queue. 105 // the jobs from the queue.
104 } 106 }
105 107
106 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) const { 108 bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) const {
107 if (job->GetType() != GetType()) 109 if (job->GetType() != GetType())
108 return false; 110 return false;
109 ServiceWorkerRegisterJob* register_job = 111 ServiceWorkerRegisterJob* register_job =
110 static_cast<ServiceWorkerRegisterJob*>(job); 112 static_cast<ServiceWorkerRegisterJob*>(job);
111 return register_job->pattern_ == pattern_ && 113 return register_job->pattern_ == pattern_ &&
112 register_job->script_url_ == script_url_; 114 register_job->script_url_ == script_url_;
113 } 115 }
114 116
115 RegistrationJobType ServiceWorkerRegisterJob::GetType() const { 117 RegistrationJobType ServiceWorkerRegisterJob::GetType() const {
116 return job_type_; 118 return job_type_;
117 } 119 }
118 120
119 void ServiceWorkerRegisterJob::DoomInstallingWorker() { 121 void ServiceWorkerRegisterJob::DoomInstallingWorker() {
120 doom_installing_worker_ = true; 122 doom_installing_worker_ = true;
121 if (phase_ == INSTALL) 123 if (phase_ == INSTALL)
122 Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED); 124 Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, std::string());
123 } 125 }
124 126
125 ServiceWorkerRegisterJob::Internal::Internal() {} 127 ServiceWorkerRegisterJob::Internal::Internal() {}
126 128
127 ServiceWorkerRegisterJob::Internal::~Internal() {} 129 ServiceWorkerRegisterJob::Internal::~Internal() {}
128 130
129 void ServiceWorkerRegisterJob::set_registration( 131 void ServiceWorkerRegisterJob::set_registration(
130 const scoped_refptr<ServiceWorkerRegistration>& registration) { 132 const scoped_refptr<ServiceWorkerRegistration>& registration) {
131 DCHECK(phase_ == START || phase_ == REGISTER) << phase_; 133 DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
132 DCHECK(!internal_.registration.get()); 134 DCHECK(!internal_.registration.get());
(...skipping 133 matching lines...)
266 // may be able to complete the update job right here. 268 // may be able to complete the update job right here.
267 269
268 UpdateAndContinue(); 270 UpdateAndContinue();
269 } 271 }
270 272
271 // Creates a new ServiceWorkerRegistration. 273 // Creates a new ServiceWorkerRegistration.
272 void ServiceWorkerRegisterJob::RegisterAndContinue( 274 void ServiceWorkerRegisterJob::RegisterAndContinue(
273 ServiceWorkerStatusCode status) { 275 ServiceWorkerStatusCode status) {
274 SetPhase(REGISTER); 276 SetPhase(REGISTER);
275 if (status != SERVICE_WORKER_OK) { 277 if (status != SERVICE_WORKER_OK) {
276 // Abort this registration job.
277 Complete(status); 278 Complete(status);
278 return; 279 return;
279 } 280 }
280 281
281 set_registration(new ServiceWorkerRegistration( 282 set_registration(new ServiceWorkerRegistration(
282 pattern_, context_->storage()->NewRegistrationId(), context_)); 283 pattern_, context_->storage()->NewRegistrationId(), context_));
283 AssociateProviderHostsToRegistration(registration()); 284 AssociateProviderHostsToRegistration(registration());
284 UpdateAndContinue(); 285 UpdateAndContinue();
285 } 286 }
286 287
(...skipping 15 matching lines...)
302 303
303 // "If newestWorker is not null, and scriptURL is equal to 304 // "If newestWorker is not null, and scriptURL is equal to
304 // newestWorker.scriptURL, then: 305 // newestWorker.scriptURL, then:
305 // Return a promise resolved with registration." 306 // Return a promise resolved with registration."
306 // We resolve only if there's an active version. If there's not, 307 // We resolve only if there's an active version. If there's not,
307 // then there is either no version or only a waiting version from 308 // then there is either no version or only a waiting version from
308 // the last browser session; it makes sense to proceed with registration in 309 // the last browser session; it makes sense to proceed with registration in
309 // either case. 310 // either case.
310 DCHECK(!existing_registration->installing_version()); 311 DCHECK(!existing_registration->installing_version());
311 if (existing_registration->active_version()) { 312 if (existing_registration->active_version()) {
312 ResolvePromise(status, existing_registration.get()); 313 ResolvePromise(status, std::string(), existing_registration.get());
313 Complete(SERVICE_WORKER_OK); 314 Complete(SERVICE_WORKER_OK);
314 return; 315 return;
315 } 316 }
316 317
317 // "Return the result of running the [[Update]] algorithm, or its equivalent, 318 // "Return the result of running the [[Update]] algorithm, or its equivalent,
318 // passing registration as the argument." 319 // passing registration as the argument."
319 UpdateAndContinue(); 320 UpdateAndContinue();
320 } 321 }
321 322
322 // This function corresponds to the spec's [[Update]] algorithm. 323 // This function corresponds to the spec's [[Update]] algorithm.
(...skipping 22 matching lines...)
345 if (status == SERVICE_WORKER_OK) { 346 if (status == SERVICE_WORKER_OK) {
346 InstallAndContinue(); 347 InstallAndContinue();
347 return; 348 return;
348 } 349 }
349 350
350 // "If serviceWorker fails to start up..." then reject the promise with an 351 // "If serviceWorker fails to start up..." then reject the promise with an
351 // error and abort. When there is a main script network error, the status will 352 // error and abort. When there is a main script network error, the status will
352 // be updated to a more specific one. 353 // be updated to a more specific one.
353 const net::URLRequestStatus& main_script_status = 354 const net::URLRequestStatus& main_script_status =
354 new_version()->script_cache_map()->main_script_status(); 355 new_version()->script_cache_map()->main_script_status();
356 std::string message;
355 if (main_script_status.status() != net::URLRequestStatus::SUCCESS) { 357 if (main_script_status.status() != net::URLRequestStatus::SUCCESS) {
356 switch (main_script_status.error()) { 358 switch (main_script_status.error()) {
357 case net::ERR_INSECURE_RESPONSE: 359 case net::ERR_INSECURE_RESPONSE:
358 case net::ERR_UNSAFE_REDIRECT: 360 case net::ERR_UNSAFE_REDIRECT:
359 status = SERVICE_WORKER_ERROR_SECURITY; 361 status = SERVICE_WORKER_ERROR_SECURITY;
360 break; 362 break;
361 case net::ERR_ABORTED: 363 case net::ERR_ABORTED:
362 status = SERVICE_WORKER_ERROR_ABORT; 364 status = SERVICE_WORKER_ERROR_ABORT;
363 break; 365 break;
364 default: 366 default:
365 status = SERVICE_WORKER_ERROR_NETWORK; 367 status = SERVICE_WORKER_ERROR_NETWORK;
366 } 368 }
369 message = new_version()->script_cache_map()->main_script_status_message();
370 if (message.empty())
371 message = kFetchScriptError;
367 } 372 }
368 Complete(status); 373 Complete(status, message);
369 } 374 }
370 375
371 // This function corresponds to the spec's [[Install]] algorithm. 376 // This function corresponds to the spec's [[Install]] algorithm.
372 void ServiceWorkerRegisterJob::InstallAndContinue() { 377 void ServiceWorkerRegisterJob::InstallAndContinue() {
373 SetPhase(INSTALL); 378 SetPhase(INSTALL);
374 379
375 // "Set registration.installingWorker to worker." 380 // "Set registration.installingWorker to worker."
376 DCHECK(!registration()->installing_version()); 381 DCHECK(!registration()->installing_version());
377 registration()->SetInstallingVersion(new_version()); 382 registration()->SetInstallingVersion(new_version());
378 383
379 // "Run the Update State algorithm passing registration's installing worker 384 // "Run the Update State algorithm passing registration's installing worker
380 // and installing as the arguments." 385 // and installing as the arguments."
381 new_version()->SetStatus(ServiceWorkerVersion::INSTALLING); 386 new_version()->SetStatus(ServiceWorkerVersion::INSTALLING);
382 387
383 // "Resolve registrationPromise with registration." 388 // "Resolve registrationPromise with registration."
384 ResolvePromise(SERVICE_WORKER_OK, registration()); 389 ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());
385 390
386 // "Fire a simple event named updatefound..." 391 // "Fire a simple event named updatefound..."
387 registration()->NotifyUpdateFound(); 392 registration()->NotifyUpdateFound();
388 393
389 // "Fire an event named install..." 394 // "Fire an event named install..."
390 new_version()->DispatchInstallEvent( 395 new_version()->DispatchInstallEvent(
391 -1, 396 -1,
392 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished, 397 base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
393 weak_factory_.GetWeakPtr())); 398 weak_factory_.GetWeakPtr()));
394 399
(...skipping 48 matching lines...)
443 448
444 // "If registration's waiting worker's skip waiting flag is set:" then 449 // "If registration's waiting worker's skip waiting flag is set:" then
445 // activate the worker immediately otherwise "wait until no service worker 450 // activate the worker immediately otherwise "wait until no service worker
446 // client is using registration as their service worker registration." 451 // client is using registration as their service worker registration."
447 registration()->ActivateWaitingVersionWhenReady(); 452 registration()->ActivateWaitingVersionWhenReady();
448 453
449 Complete(SERVICE_WORKER_OK); 454 Complete(SERVICE_WORKER_OK);
450 } 455 }
451 456
452 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) { 457 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
453 CompleteInternal(status); 458 Complete(status, std::string());
459 }
460
461 void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status,
462 const std::string& status_message) {
463 CompleteInternal(status, status_message);
454 context_->job_coordinator()->FinishJob(pattern_, this); 464 context_->job_coordinator()->FinishJob(pattern_, this);
455 } 465 }
456 466
457 void ServiceWorkerRegisterJob::CompleteInternal( 467 void ServiceWorkerRegisterJob::CompleteInternal(
458 ServiceWorkerStatusCode status) { 468 ServiceWorkerStatusCode status,
469 const std::string& status_message) {
459 SetPhase(COMPLETE); 470 SetPhase(COMPLETE);
460 if (status != SERVICE_WORKER_OK) { 471 if (status != SERVICE_WORKER_OK) {
461 if (registration()) { 472 if (registration()) {
462 if (new_version()) { 473 if (new_version()) {
463 registration()->UnsetVersion(new_version()); 474 registration()->UnsetVersion(new_version());
464 new_version()->Doom(); 475 new_version()->Doom();
465 } 476 }
466 if (!registration()->waiting_version() && 477 if (!registration()->waiting_version() &&
467 !registration()->active_version()) { 478 !registration()->active_version()) {
468 registration()->NotifyRegistrationFailed(); 479 registration()->NotifyRegistrationFailed();
469 context_->storage()->DeleteRegistration( 480 context_->storage()->DeleteRegistration(
470 registration()->id(), 481 registration()->id(),
471 registration()->pattern().GetOrigin(), 482 registration()->pattern().GetOrigin(),
472 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); 483 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
473 } 484 }
474 } 485 }
475 if (!is_promise_resolved_) 486 if (!is_promise_resolved_)
476 ResolvePromise(status, NULL); 487 ResolvePromise(status, status_message, NULL);
477 } 488 }
478 DCHECK(callbacks_.empty()); 489 DCHECK(callbacks_.empty());
479 if (registration()) { 490 if (registration()) {
480 context_->storage()->NotifyDoneInstallingRegistration( 491 context_->storage()->NotifyDoneInstallingRegistration(
481 registration(), new_version(), status); 492 registration(), new_version(), status);
482 } 493 }
483 if (new_version()) 494 if (new_version())
484 new_version()->embedded_worker()->RemoveListener(this); 495 new_version()->embedded_worker()->RemoveListener(this);
485 } 496 }
486 497
487 void ServiceWorkerRegisterJob::ResolvePromise( 498 void ServiceWorkerRegisterJob::ResolvePromise(
488 ServiceWorkerStatusCode status, 499 ServiceWorkerStatusCode status,
500 const std::string& status_message,
489 ServiceWorkerRegistration* registration) { 501 ServiceWorkerRegistration* registration) {
490 DCHECK(!is_promise_resolved_); 502 DCHECK(!is_promise_resolved_);
491 503
492 is_promise_resolved_ = true; 504 is_promise_resolved_ = true;
493 promise_resolved_status_ = status; 505 promise_resolved_status_ = status;
506 promise_resolved_status_message_ = status_message,
494 promise_resolved_registration_ = registration; 507 promise_resolved_registration_ = registration;
495 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin(); 508 for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
496 it != callbacks_.end(); 509 it != callbacks_.end();
497 ++it) { 510 ++it) {
498 it->Run(status, registration); 511 it->Run(status, status_message, registration);
499 } 512 }
500 callbacks_.clear(); 513 callbacks_.clear();
501 } 514 }
502 515
503 void ServiceWorkerRegisterJob::OnPausedAfterDownload() { 516 void ServiceWorkerRegisterJob::OnPausedAfterDownload() {
504 // This happens prior to OnStartWorkerFinished time. 517 // This happens prior to OnStartWorkerFinished time.
505 scoped_refptr<ServiceWorkerVersion> most_recent_version = 518 scoped_refptr<ServiceWorkerVersion> most_recent_version =
506 registration()->waiting_version() ? 519 registration()->waiting_version() ?
507 registration()->waiting_version() : 520 registration()->waiting_version() :
508 registration()->active_version(); 521 registration()->active_version();
(...skipping 31 matching lines...)
540 bool are_equal) { 553 bool are_equal) {
541 if (are_equal) { 554 if (are_equal) {
542 // Only bump the last check time when we've bypassed the browser cache. 555 // Only bump the last check time when we've bypassed the browser cache.
543 base::TimeDelta time_since_last_check = 556 base::TimeDelta time_since_last_check =
544 base::Time::Now() - registration()->last_update_check(); 557 base::Time::Now() - registration()->last_update_check();
545 if (time_since_last_check > base::TimeDelta::FromHours(24)) { 558 if (time_since_last_check > base::TimeDelta::FromHours(24)) {
546 registration()->set_last_update_check(base::Time::Now()); 559 registration()->set_last_update_check(base::Time::Now());
547 context_->storage()->UpdateLastUpdateCheckTime(registration()); 560 context_->storage()->UpdateLastUpdateCheckTime(registration());
548 } 561 }
549 562
550 ResolvePromise(SERVICE_WORKER_OK, registration()); 563 ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());
551 Complete(SERVICE_WORKER_ERROR_EXISTS); 564 Complete(SERVICE_WORKER_ERROR_EXISTS);
552 return; 565 return;
553 } 566 }
554 567
555 // Proceed with really starting the worker. 568 // Proceed with really starting the worker.
556 new_version()->embedded_worker()->ResumeAfterDownload(); 569 new_version()->embedded_worker()->ResumeAfterDownload();
557 new_version()->embedded_worker()->RemoveListener(this); 570 new_version()->embedded_worker()->RemoveListener(this);
558 } 571 }
559 572
560 void ServiceWorkerRegisterJob::AssociateProviderHostsToRegistration( 573 void ServiceWorkerRegisterJob::AssociateProviderHostsToRegistration(
561 ServiceWorkerRegistration* registration) { 574 ServiceWorkerRegistration* registration) {
562 DCHECK(registration); 575 DCHECK(registration);
563 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it = 576 for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
564 context_->GetProviderHostIterator(); 577 context_->GetProviderHostIterator();
565 !it->IsAtEnd(); it->Advance()) { 578 !it->IsAtEnd(); it->Advance()) {
566 ServiceWorkerProviderHost* host = it->GetProviderHost(); 579 ServiceWorkerProviderHost* host = it->GetProviderHost();
567 if (ServiceWorkerUtils::ScopeMatches(registration->pattern(), 580 if (ServiceWorkerUtils::ScopeMatches(registration->pattern(),
568 host->document_url())) { 581 host->document_url())) {
569 if (host->CanAssociateRegistration(registration)) 582 if (host->CanAssociateRegistration(registration))
570 host->AssociateRegistration(registration); 583 host->AssociateRegistration(registration);
571 } 584 }
572 } 585 }
573 } 586 }
574 587
575 } // namespace content 588 } // namespace content
OLDNEW

Powered by Google App Engine