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 #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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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 |
OLD | NEW |