| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "extensions/renderer/service_worker_data.h" |
| |
| #include "extensions/common/extension.h" |
| #include "extensions/common/permissions/permissions_data.h" |
| #include "extensions/renderer/dispatcher.h" |
| #include "extensions/renderer/extension_interaction_provider.h" |
| #include "extensions/renderer/native_extension_bindings_system.h" |
| #include "extensions/renderer/renderer_extension_registry.h" |
| #include "extensions/renderer/worker_script_context_set.h" |
| #include "extensions/renderer/worker_thread_dispatcher.h" |
| #include "extensions/renderer/worker_thread_util.h" |
| #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" |
| #include "third_party/blink/public/common/tokens/tokens.h" |
| |
| namespace extensions { |
| |
| ServiceWorkerData::ServiceWorkerData( |
| blink::WebServiceWorkerContextProxy* proxy, |
| int64_t service_worker_version_id, |
| const std::optional<base::UnguessableToken>& activation_sequence, |
| const blink::ServiceWorkerToken& service_worker_token, |
| ScriptContext* context, |
| std::unique_ptr<NativeExtensionBindingsSystem> bindings_system) |
| : proxy_(proxy), |
| service_worker_version_id_(service_worker_version_id), |
| activation_sequence_(std::move(activation_sequence)), |
| service_worker_token_(service_worker_token), |
| context_(context), |
| v8_schema_registry_(new V8SchemaRegistry), |
| bindings_system_(std::move(bindings_system)) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| CHECK(bindings_system_); |
| proxy_->GetAssociatedInterfaceRegistry().AddInterface<mojom::ServiceWorker>( |
| base::BindRepeating(&ServiceWorkerData::OnServiceWorkerRequest, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| ServiceWorkerData::~ServiceWorkerData() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| } |
| |
| void ServiceWorkerData::OnServiceWorkerRequest( |
| mojo::PendingAssociatedReceiver<mojom::ServiceWorker> receiver) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| CHECK(bindings_system_); |
| receiver_.reset(); |
| receiver_.Bind(std::move(receiver)); |
| } |
| |
| void ServiceWorkerData::UpdatePermissions(PermissionSet active_permissions, |
| PermissionSet withheld_permissions) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| DCHECK(worker_thread_util::IsWorkerThread()); |
| CHECK(bindings_system_); |
| |
| const ExtensionId& extension_id = context_->GetExtensionID(); |
| const Extension* extension = |
| RendererExtensionRegistry::Get()->GetByID(extension_id); |
| if (!extension) { |
| return; |
| } |
| extension->permissions_data()->SetPermissions( |
| std::make_unique<const PermissionSet>(std::move(active_permissions)), |
| std::make_unique<const PermissionSet>(std::move(withheld_permissions))); |
| |
| bindings_system_->UpdateBindings(extension_id, /*permissions_changed=*/true, |
| Dispatcher::GetWorkerScriptContextSet()); |
| } |
| |
| mojom::ServiceWorkerHost* ServiceWorkerData::GetServiceWorkerHost() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| CHECK(bindings_system_); |
| if (!service_worker_host_.is_bound()) { |
| proxy_->GetRemoteAssociatedInterface( |
| service_worker_host_.BindNewEndpointAndPassReceiver()); |
| } |
| return service_worker_host_.get(); |
| } |
| |
| mojom::EventRouter* ServiceWorkerData::GetEventRouter() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| CHECK(bindings_system_); |
| if (!event_router_remote_.is_bound()) { |
| proxy_->GetRemoteAssociatedInterface( |
| event_router_remote_.BindNewEndpointAndPassReceiver()); |
| } |
| return event_router_remote_.get(); |
| } |
| |
| mojom::RendererAutomationRegistry* ServiceWorkerData::GetAutomationRegistry() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| CHECK(bindings_system_); |
| if (!renderer_automation_registry_remote_.is_bound()) { |
| proxy_->GetRemoteAssociatedInterface( |
| renderer_automation_registry_remote_.BindNewEndpointAndPassReceiver()); |
| } |
| return renderer_automation_registry_remote_.get(); |
| } |
| |
| mojom::RendererHost* ServiceWorkerData::GetRendererHost() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| // We allow access to mojom::RendererHost without a `bindings_system_`. |
| if (!renderer_host_.is_bound()) { |
| proxy_->GetRemoteAssociatedInterface( |
| renderer_host_.BindNewEndpointAndPassReceiver()); |
| } |
| return renderer_host_.get(); |
| } |
| |
| void ServiceWorkerData::Init() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| CHECK(bindings_system_); |
| const int thread_id = content::WorkerThread::GetCurrentId(); |
| GetServiceWorkerHost()->DidInitializeServiceWorkerContext( |
| context_->GetExtensionID(), service_worker_version_id_, thread_id, |
| service_worker_token_, |
| event_dispatcher_receiver_.BindNewEndpointAndPassRemote()); |
| } |
| |
| void ServiceWorkerData::DispatchEvent(mojom::DispatchEventParamsPtr params, |
| base::Value::List event_args, |
| DispatchEventCallback callback) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| ScriptContext* script_context = context(); |
| // Note |scoped_extension_interaction| requires a HandleScope. |
| v8::Isolate* isolate = script_context->isolate(); |
| v8::HandleScope handle_scope(isolate); |
| std::unique_ptr<InteractionProvider::Scope> scoped_extension_interaction; |
| if (params->is_user_gesture) { |
| scoped_extension_interaction = |
| ExtensionInteractionProvider::Scope::ForWorker( |
| script_context->v8_context()); |
| } |
| |
| bindings_system()->DispatchEventInContext(params->event_name, event_args, |
| std::move(params->filtering_info), |
| context()); |
| |
| std::move(callback).Run( |
| // False since this is only possibly true for lazy background page. |
| /*event_will_run_in_lazy_background_page_script=*/false); |
| } |
| |
| void ServiceWorkerData::DispatchOnConnect( |
| const PortId& port_id, |
| extensions::mojom::ChannelType channel_type, |
| const std::string& channel_name, |
| extensions::mojom::TabConnectionInfoPtr tab_info, |
| extensions::mojom::ExternalConnectionInfoPtr external_connection_info, |
| mojo::PendingAssociatedReceiver<extensions::mojom::MessagePort> port, |
| mojo::PendingAssociatedRemote<extensions::mojom::MessagePortHost> port_host, |
| DispatchOnConnectCallback callback) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| WorkerThreadDispatcher::GetBindingsSystem() |
| ->messaging_service() |
| ->DispatchOnConnect(Dispatcher::GetWorkerScriptContextSet(), port_id, |
| channel_type, channel_name, *tab_info, |
| *external_connection_info, std::move(port), |
| std::move(port_host), |
| // Render frames do not matter. |
| nullptr, std::move(callback)); |
| } |
| |
| } // namespace extensions |