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/embedded_worker_instance.h" | 5 #include "content/browser/service_worker/embedded_worker_instance.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "content/common/service_worker/embedded_worker_setup.mojom.h" | 22 #include "content/common/service_worker/embedded_worker_setup.mojom.h" |
23 #include "content/common/service_worker/embedded_worker_start_params.h" | 23 #include "content/common/service_worker/embedded_worker_start_params.h" |
24 #include "content/common/service_worker/service_worker_types.h" | 24 #include "content/common/service_worker/service_worker_types.h" |
25 #include "content/common/service_worker/service_worker_utils.h" | 25 #include "content/common/service_worker/service_worker_utils.h" |
26 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
27 #include "content/public/browser/content_browser_client.h" | 27 #include "content/public/browser/content_browser_client.h" |
28 #include "content/public/browser/render_process_host.h" | 28 #include "content/public/browser/render_process_host.h" |
29 #include "content/public/common/child_process_host.h" | 29 #include "content/public/common/child_process_host.h" |
30 #include "content/public/common/content_switches.h" | 30 #include "content/public/common/content_switches.h" |
31 #include "ipc/ipc_message.h" | 31 #include "ipc/ipc_message.h" |
32 #include "services/service_manager/public/cpp/interface_provider.h" | |
33 #include "services/service_manager/public/cpp/interface_registry.h" | |
34 #include "url/gurl.h" | 32 #include "url/gurl.h" |
35 | 33 |
36 namespace content { | 34 namespace content { |
37 | 35 |
38 namespace { | 36 namespace { |
39 | 37 |
40 // When a service worker version's failure count exceeds | 38 // When a service worker version's failure count exceeds |
41 // |kMaxSameProcessFailureCount|, the embedded worker is forced to start in a | 39 // |kMaxSameProcessFailureCount|, the embedded worker is forced to start in a |
42 // new process. | 40 // new process. |
43 const int kMaxSameProcessFailureCount = 2; | 41 const int kMaxSameProcessFailureCount = 2; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 is_installed); | 96 is_installed); |
99 if (request.is_pending()) | 97 if (request.is_pending()) |
100 rph->GetRemoteInterfaces()->GetInterface(std::move(request)); | 98 rph->GetRemoteInterfaces()->GetInterface(std::move(request)); |
101 } | 99 } |
102 BrowserThread::PostTask( | 100 BrowserThread::PostTask( |
103 BrowserThread::IO, | 101 BrowserThread::IO, |
104 FROM_HERE, | 102 FROM_HERE, |
105 base::Bind(callback, worker_devtools_agent_route_id, wait_for_debugger)); | 103 base::Bind(callback, worker_devtools_agent_route_id, wait_for_debugger)); |
106 } | 104 } |
107 | 105 |
108 void SetupMojoOnUIThread( | 106 void SetupEventDispatcherOnUIThread( |
109 int process_id, | 107 int process_id, |
110 int thread_id, | 108 int thread_id, |
111 service_manager::mojom::InterfaceProviderRequest remote_interfaces, | 109 mojom::ServiceWorkerEventDispatcherRequest request) { |
112 service_manager::mojom::InterfaceProviderPtrInfo exposed_interfaces) { | 110 DCHECK(!ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()); |
113 RenderProcessHost* rph = RenderProcessHost::FromID(process_id); | 111 RenderProcessHost* rph = RenderProcessHost::FromID(process_id); |
114 // |rph| or its InterfaceProvider may be NULL in unit tests. | 112 // |rph| or its InterfaceProvider may be NULL in unit tests. |
115 if (!rph || !rph->GetRemoteInterfaces()) | 113 if (!rph || !rph->GetRemoteInterfaces()) |
116 return; | 114 return; |
117 mojom::EmbeddedWorkerSetupPtr setup; | 115 mojom::EmbeddedWorkerSetupPtr setup; |
118 rph->GetRemoteInterfaces()->GetInterface(&setup); | 116 rph->GetRemoteInterfaces()->GetInterface(&setup); |
119 setup->ExchangeInterfaceProviders( | 117 setup->AttachServiceWorkerEventDispatcher(thread_id, std::move(request)); |
120 thread_id, std::move(remote_interfaces), | |
121 mojo::MakeProxy(std::move(exposed_interfaces))); | |
122 } | 118 } |
123 | 119 |
124 void CallDetach(EmbeddedWorkerInstance* instance) { | 120 void CallDetach(EmbeddedWorkerInstance* instance) { |
125 // This could be called on the UI thread if |client_| still be valid when the | 121 // This could be called on the UI thread if |client_| still be valid when the |
126 // message loop on the UI thread gets destructed. | 122 // message loop on the UI thread gets destructed. |
127 // TODO(shimazu): Remove this after https://crbug.com/604762 is fixed | 123 // TODO(shimazu): Remove this after https://crbug.com/604762 is fixed |
128 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | 124 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
129 DCHECK(ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()); | 125 DCHECK(ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()); |
130 return; | 126 return; |
131 } | 127 } |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 status_ == EmbeddedWorkerStatus::STOPPED) | 448 status_ == EmbeddedWorkerStatus::STOPPED) |
453 << static_cast<int>(status_); | 449 << static_cast<int>(status_); |
454 devtools_proxy_.reset(); | 450 devtools_proxy_.reset(); |
455 if (registry_->GetWorker(embedded_worker_id_)) | 451 if (registry_->GetWorker(embedded_worker_id_)) |
456 registry_->RemoveWorker(process_id(), embedded_worker_id_); | 452 registry_->RemoveWorker(process_id(), embedded_worker_id_); |
457 process_handle_.reset(); | 453 process_handle_.reset(); |
458 } | 454 } |
459 | 455 |
460 void EmbeddedWorkerInstance::Start( | 456 void EmbeddedWorkerInstance::Start( |
461 std::unique_ptr<EmbeddedWorkerStartParams> params, | 457 std::unique_ptr<EmbeddedWorkerStartParams> params, |
| 458 mojom::ServiceWorkerEventDispatcherRequest dispatcher_request, |
462 const StatusCallback& callback) { | 459 const StatusCallback& callback) { |
463 if (!context_) { | 460 if (!context_) { |
464 callback.Run(SERVICE_WORKER_ERROR_ABORT); | 461 callback.Run(SERVICE_WORKER_ERROR_ABORT); |
465 // |this| may be destroyed by the callback. | 462 // |this| may be destroyed by the callback. |
466 return; | 463 return; |
467 } | 464 } |
468 DCHECK(status_ == EmbeddedWorkerStatus::STOPPED); | 465 DCHECK(status_ == EmbeddedWorkerStatus::STOPPED); |
469 | 466 |
470 DCHECK(!params->pause_after_download || !params->is_installed); | 467 DCHECK(!params->pause_after_download || !params->is_installed); |
471 DCHECK_NE(kInvalidServiceWorkerVersionId, params->service_worker_version_id); | 468 DCHECK_NE(kInvalidServiceWorkerVersionId, params->service_worker_version_id); |
472 step_time_ = base::TimeTicks::Now(); | 469 step_time_ = base::TimeTicks::Now(); |
473 status_ = EmbeddedWorkerStatus::STARTING; | 470 status_ = EmbeddedWorkerStatus::STARTING; |
474 starting_phase_ = ALLOCATING_PROCESS; | 471 starting_phase_ = ALLOCATING_PROCESS; |
475 network_accessed_for_script_ = false; | 472 network_accessed_for_script_ = false; |
476 interface_registry_ = | |
477 base::MakeUnique<service_manager::InterfaceRegistry>(std::string()); | |
478 remote_interfaces_.reset(new service_manager::InterfaceProvider); | |
479 for (auto& observer : listener_list_) | 473 for (auto& observer : listener_list_) |
480 observer.OnStarting(); | 474 observer.OnStarting(); |
481 | 475 |
482 params->embedded_worker_id = embedded_worker_id_; | 476 params->embedded_worker_id = embedded_worker_id_; |
483 params->worker_devtools_agent_route_id = MSG_ROUTING_NONE; | 477 params->worker_devtools_agent_route_id = MSG_ROUTING_NONE; |
484 params->wait_for_debugger = false; | 478 params->wait_for_debugger = false; |
485 params->settings.v8_cache_options = GetV8CacheOptions(); | 479 params->settings.v8_cache_options = GetV8CacheOptions(); |
486 | 480 |
487 mojom::EmbeddedWorkerInstanceClientRequest request; | 481 mojom::EmbeddedWorkerInstanceClientRequest request; |
488 if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { | 482 if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { |
489 request = mojo::GetProxy(&client_); | 483 request = mojo::GetProxy(&client_); |
490 client_.set_connection_error_handler( | 484 client_.set_connection_error_handler( |
491 base::Bind(&CallDetach, base::Unretained(this))); | 485 base::Bind(&CallDetach, base::Unretained(this))); |
492 } | 486 } |
493 | 487 |
| 488 pending_dispatcher_request_ = std::move(dispatcher_request); |
| 489 |
494 inflight_start_task_.reset( | 490 inflight_start_task_.reset( |
495 new StartTask(this, params->script_url, std::move(request))); | 491 new StartTask(this, params->script_url, std::move(request))); |
496 inflight_start_task_->Start(std::move(params), callback); | 492 inflight_start_task_->Start(std::move(params), callback); |
497 } | 493 } |
498 | 494 |
499 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { | 495 ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() { |
500 DCHECK(status_ == EmbeddedWorkerStatus::STARTING || | 496 DCHECK(status_ == EmbeddedWorkerStatus::STARTING || |
501 status_ == EmbeddedWorkerStatus::RUNNING) | 497 status_ == EmbeddedWorkerStatus::RUNNING) |
502 << static_cast<int>(status_); | 498 << static_cast<int>(status_); |
503 | 499 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 | 554 |
559 void EmbeddedWorkerInstance::ResumeAfterDownload() { | 555 void EmbeddedWorkerInstance::ResumeAfterDownload() { |
560 if (process_id() == ChildProcessHost::kInvalidUniqueID || | 556 if (process_id() == ChildProcessHost::kInvalidUniqueID || |
561 status_ != EmbeddedWorkerStatus::STARTING) { | 557 status_ != EmbeddedWorkerStatus::STARTING) { |
562 return; | 558 return; |
563 } | 559 } |
564 registry_->Send(process_id(), new EmbeddedWorkerMsg_ResumeAfterDownload( | 560 registry_->Send(process_id(), new EmbeddedWorkerMsg_ResumeAfterDownload( |
565 embedded_worker_id_)); | 561 embedded_worker_id_)); |
566 } | 562 } |
567 | 563 |
568 service_manager::InterfaceRegistry* | |
569 EmbeddedWorkerInstance::GetInterfaceRegistry() { | |
570 DCHECK(status_ == EmbeddedWorkerStatus::STARTING || | |
571 status_ == EmbeddedWorkerStatus::RUNNING) | |
572 << static_cast<int>(status_); | |
573 return interface_registry_.get(); | |
574 } | |
575 | |
576 service_manager::InterfaceProvider* | |
577 EmbeddedWorkerInstance::GetRemoteInterfaces() { | |
578 DCHECK(status_ == EmbeddedWorkerStatus::STARTING || | |
579 status_ == EmbeddedWorkerStatus::RUNNING) | |
580 << static_cast<int>(status_); | |
581 return remote_interfaces_.get(); | |
582 } | |
583 | |
584 EmbeddedWorkerInstance::EmbeddedWorkerInstance( | 564 EmbeddedWorkerInstance::EmbeddedWorkerInstance( |
585 base::WeakPtr<ServiceWorkerContextCore> context, | 565 base::WeakPtr<ServiceWorkerContextCore> context, |
586 int embedded_worker_id) | 566 int embedded_worker_id) |
587 : context_(context), | 567 : context_(context), |
588 registry_(context->embedded_worker_registry()), | 568 registry_(context->embedded_worker_registry()), |
589 embedded_worker_id_(embedded_worker_id), | 569 embedded_worker_id_(embedded_worker_id), |
590 status_(EmbeddedWorkerStatus::STOPPED), | 570 status_(EmbeddedWorkerStatus::STOPPED), |
591 starting_phase_(NOT_STARTING), | 571 starting_phase_(NOT_STARTING), |
592 thread_id_(kInvalidEmbeddedWorkerThreadId), | 572 thread_id_(kInvalidEmbeddedWorkerThreadId), |
593 devtools_attached_(false), | 573 devtools_attached_(false), |
(...skipping 28 matching lines...) Expand all Loading... |
622 step_time_ = base::TimeTicks(); | 602 step_time_ = base::TimeTicks(); |
623 } | 603 } |
624 for (auto& observer : listener_list_) | 604 for (auto& observer : listener_list_) |
625 observer.OnRegisteredToDevToolsManager(); | 605 observer.OnRegisteredToDevToolsManager(); |
626 } | 606 } |
627 | 607 |
628 ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMojoStartWorker( | 608 ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMojoStartWorker( |
629 std::unique_ptr<EmbeddedWorkerStartParams> params) { | 609 std::unique_ptr<EmbeddedWorkerStartParams> params) { |
630 if (!context_) | 610 if (!context_) |
631 return SERVICE_WORKER_ERROR_ABORT; | 611 return SERVICE_WORKER_ERROR_ABORT; |
632 service_manager::mojom::InterfaceProviderPtr remote_interfaces; | 612 DCHECK(pending_dispatcher_request_.is_pending()); |
633 service_manager::mojom::InterfaceProviderRequest request = | 613 client_->StartWorker(*params, std::move(pending_dispatcher_request_)); |
634 mojo::GetProxy(&remote_interfaces); | |
635 remote_interfaces_->Bind(std::move(remote_interfaces)); | |
636 service_manager::mojom::InterfaceProviderPtr exposed_interfaces; | |
637 interface_registry_->Bind( | |
638 mojo::GetProxy(&exposed_interfaces), service_manager::Identity(), | |
639 service_manager::InterfaceProviderSpec(), service_manager::Identity(), | |
640 service_manager::InterfaceProviderSpec()); | |
641 client_->StartWorker(*params, std::move(exposed_interfaces), | |
642 std::move(request)); | |
643 registry_->BindWorkerToProcess(process_id(), embedded_worker_id()); | 614 registry_->BindWorkerToProcess(process_id(), embedded_worker_id()); |
644 TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start", | 615 TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start", |
645 this, "SendStartWorker", "Status", "mojo"); | 616 this, "SendStartWorker", "Status", "mojo"); |
646 OnStartWorkerMessageSent(); | 617 OnStartWorkerMessageSent(); |
647 return SERVICE_WORKER_OK; | 618 return SERVICE_WORKER_OK; |
648 } | 619 } |
649 | 620 |
650 void EmbeddedWorkerInstance::OnStartWorkerMessageSent() { | 621 void EmbeddedWorkerInstance::OnStartWorkerMessageSent() { |
651 if (!step_time_.is_null()) { | 622 if (!step_time_.is_null()) { |
652 base::TimeDelta duration = UpdateStepTime(); | 623 base::TimeDelta duration = UpdateStepTime(); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 if (!step_time_.is_null()) { | 707 if (!step_time_.is_null()) { |
737 base::TimeDelta duration = UpdateStepTime(); | 708 base::TimeDelta duration = UpdateStepTime(); |
738 if (inflight_start_task_->is_installed()) | 709 if (inflight_start_task_->is_installed()) |
739 ServiceWorkerMetrics::RecordTimeToStartThread(duration, start_situation_); | 710 ServiceWorkerMetrics::RecordTimeToStartThread(duration, start_situation_); |
740 } | 711 } |
741 | 712 |
742 thread_id_ = thread_id; | 713 thread_id_ = thread_id; |
743 for (auto& observer : listener_list_) | 714 for (auto& observer : listener_list_) |
744 observer.OnThreadStarted(); | 715 observer.OnThreadStarted(); |
745 | 716 |
746 // This code is for BackgroundSync and FetchEvent, which have been already | 717 // The pending request is sent at StartWorker if mojo for the service worker |
747 // mojofied. Interfaces are exchanged at StartWorker when mojo for the service | 718 // is enabled. |
748 // worker is enabled, so this code isn't necessary when the flag is enabled. | |
749 if (!ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { | 719 if (!ServiceWorkerUtils::IsMojoForServiceWorkerEnabled()) { |
750 service_manager::mojom::InterfaceProviderPtr exposed_interfaces; | 720 DCHECK(pending_dispatcher_request_.is_pending()); |
751 interface_registry_->Bind( | |
752 mojo::GetProxy(&exposed_interfaces), service_manager::Identity(), | |
753 service_manager::InterfaceProviderSpec(), service_manager::Identity(), | |
754 service_manager::InterfaceProviderSpec()); | |
755 service_manager::mojom::InterfaceProviderPtr remote_interfaces; | |
756 service_manager::mojom::InterfaceProviderRequest request = | |
757 mojo::GetProxy(&remote_interfaces); | |
758 remote_interfaces_->Bind(std::move(remote_interfaces)); | |
759 BrowserThread::PostTask( | 721 BrowserThread::PostTask( |
760 BrowserThread::UI, FROM_HERE, | 722 BrowserThread::UI, FROM_HERE, |
761 base::Bind(SetupMojoOnUIThread, process_id(), thread_id_, | 723 base::Bind(SetupEventDispatcherOnUIThread, process_id(), thread_id_, |
762 base::Passed(&request), | 724 base::Passed(&pending_dispatcher_request_))); |
763 base::Passed(exposed_interfaces.PassInterface()))); | |
764 } | 725 } |
765 } | 726 } |
766 | 727 |
767 void EmbeddedWorkerInstance::OnScriptLoadFailed() { | 728 void EmbeddedWorkerInstance::OnScriptLoadFailed() { |
768 if (!inflight_start_task_) | 729 if (!inflight_start_task_) |
769 return; | 730 return; |
770 TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker", "EmbeddedWorkerInstance::Start", | 731 TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker", "EmbeddedWorkerInstance::Start", |
771 inflight_start_task_.get(), | 732 inflight_start_task_.get(), |
772 "OnScriptLoadFailed"); | 733 "OnScriptLoadFailed"); |
773 for (auto& observer : listener_list_) | 734 for (auto& observer : listener_list_) |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 | 861 |
901 void EmbeddedWorkerInstance::ReleaseProcess() { | 862 void EmbeddedWorkerInstance::ReleaseProcess() { |
902 // Abort an inflight start task. | 863 // Abort an inflight start task. |
903 inflight_start_task_.reset(); | 864 inflight_start_task_.reset(); |
904 | 865 |
905 client_.reset(); | 866 client_.reset(); |
906 devtools_proxy_.reset(); | 867 devtools_proxy_.reset(); |
907 process_handle_.reset(); | 868 process_handle_.reset(); |
908 status_ = EmbeddedWorkerStatus::STOPPED; | 869 status_ = EmbeddedWorkerStatus::STOPPED; |
909 thread_id_ = kInvalidEmbeddedWorkerThreadId; | 870 thread_id_ = kInvalidEmbeddedWorkerThreadId; |
910 interface_registry_.reset(); | |
911 remote_interfaces_.reset(); | |
912 } | 871 } |
913 | 872 |
914 void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback, | 873 void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback, |
915 ServiceWorkerStatusCode status) { | 874 ServiceWorkerStatusCode status) { |
916 EmbeddedWorkerStatus old_status = status_; | 875 EmbeddedWorkerStatus old_status = status_; |
917 ReleaseProcess(); | 876 ReleaseProcess(); |
918 base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr(); | 877 base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr(); |
919 callback.Run(status); | 878 callback.Run(status); |
920 if (weak_this && old_status != EmbeddedWorkerStatus::STOPPED) { | 879 if (weak_this && old_status != EmbeddedWorkerStatus::STOPPED) { |
921 for (auto& observer : weak_this->listener_list_) | 880 for (auto& observer : weak_this->listener_list_) |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 case SCRIPT_READ_FINISHED: | 942 case SCRIPT_READ_FINISHED: |
984 return "Script read finished"; | 943 return "Script read finished"; |
985 case STARTING_PHASE_MAX_VALUE: | 944 case STARTING_PHASE_MAX_VALUE: |
986 NOTREACHED(); | 945 NOTREACHED(); |
987 } | 946 } |
988 NOTREACHED() << phase; | 947 NOTREACHED() << phase; |
989 return std::string(); | 948 return std::string(); |
990 } | 949 } |
991 | 950 |
992 } // namespace content | 951 } // namespace content |
OLD | NEW |