| 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 |