Skip to content

Commit

Permalink
Convert ExtensionHostMsg_DidInitializeServiceWorkerContext to mojo
Browse files Browse the repository at this point in the history
This CL is step 1 for adding extensions.mojom.ServiceWorkerHost and
converts ExtensionHostMsg_DidInitializeServiceWorkerContext to mojo as
a part of step 2.

ServiceWorkerHost and EventRouter for extensions should be associated
each other and bound to the worker thread. Currently EventRouter mojo
interface is Legacy IPC associated, so we follow below steps to avoid
flaky.

Steps:
1) Get an associated interface for mojom::ServiceWorkerHost from the
   IPC::SyncMessageFilter as mojom::EventRouter
2) Convert ExtensionHostMsg_* to mojom::ServiceWorkerHost.
3) Add an AssociatedInterfaceRegistry for service worker and obtain
   intefaces for both mojom::ServiceWorkerHost and mojom::EventRouter.

Bug: 1364183
Change-Id: Ie546fb2df1b130ea9b4d2e5bd1f05cb871b49900
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3990164
Reviewed-by: Chris Bookholt <bookholt@chromium.org>
Commit-Queue: Yeunjoo Choi <ychoi@igalia.com>
Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1113217}
  • Loading branch information
duswnchl authored and Chromium LUCI CQ committed Mar 6, 2023
1 parent 1c35807 commit 93b78dd
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#include "extensions/browser/info_map.h"
#include "extensions/browser/process_map.h"
#include "extensions/browser/renderer_startup_helper.h"
#include "extensions/browser/service_worker/service_worker_host.h"
#include "extensions/browser/url_loader_factory_manager.h"
#include "extensions/browser/url_request_util.h"
#include "extensions/browser/view_type_utils.h"
Expand Down Expand Up @@ -781,6 +782,8 @@ void ChromeContentBrowserClientExtensionsPart::ExposeInterfacesToRenderer(
&ExtensionsGuestView::CreateForExtensions, host->GetID()));
associated_registry->AddInterface<mojom::RendererHost>(base::BindRepeating(
&RendererStartupHelper::BindForRenderer, host->GetID()));
associated_registry->AddInterface<mojom::ServiceWorkerHost>(
base::BindRepeating(&ServiceWorkerHost::BindReceiver, host->GetID()));
}

} // namespace extensions
2 changes: 2 additions & 0 deletions extensions/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ source_set("browser_sources") {
"sandboxed_unpacker.h",
"script_executor.cc",
"script_executor.h",
"service_worker/service_worker_host.cc",
"service_worker/service_worker_host.h",
"service_worker/worker_id.cc",
"service_worker/worker_id.h",
"service_worker/worker_id_set.cc",
Expand Down
34 changes: 0 additions & 34 deletions extensions/browser/extension_service_worker_message_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/events/event_ack_data.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_factory.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_manager_factory.h"
Expand Down Expand Up @@ -92,8 +91,6 @@ void ExtensionServiceWorkerMessageFilter::OverrideThreadForMessage(
content::BrowserThread::ID* thread) {
if (message.type() == ExtensionHostMsg_RequestWorker::ID ||
message.type() == ExtensionHostMsg_EventAckWorker::ID ||
message.type() ==
ExtensionHostMsg_DidInitializeServiceWorkerContext::ID ||
message.type() == ExtensionHostMsg_DidStartServiceWorkerContext::ID ||
message.type() == ExtensionHostMsg_DidStopServiceWorkerContext::ID ||
message.type() == ExtensionHostMsg_WorkerResponseAck::ID) {
Expand All @@ -116,8 +113,6 @@ bool ExtensionServiceWorkerMessageFilter::OnMessageReceived(
IPC_MESSAGE_HANDLER(ExtensionHostMsg_DecrementServiceWorkerActivity,
OnDecrementServiceWorkerActivity)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_EventAckWorker, OnEventAckWorker)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidInitializeServiceWorkerContext,
OnDidInitializeServiceWorkerContext)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidStartServiceWorkerContext,
OnDidStartServiceWorkerContext)
IPC_MESSAGE_HANDLER(ExtensionHostMsg_DidStopServiceWorkerContext,
Expand Down Expand Up @@ -205,35 +200,6 @@ void ExtensionServiceWorkerMessageFilter::OnEventAckWorker(
this));
}

void ExtensionServiceWorkerMessageFilter::OnDidInitializeServiceWorkerContext(
const ExtensionId& extension_id,
int64_t service_worker_version_id,
int thread_id) {
if (!browser_context_)
return;

ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
DCHECK(registry);
if (!registry->enabled_extensions().GetByID(extension_id)) {
// This can happen if the extension is unloaded at this point. Just
// checking the extension process (as below) is insufficient because
// tearing down processes is async and happens after extension unload.
return;
}

if (!ProcessMap::Get(browser_context_)
->Contains(extension_id, render_process_id_)) {
// We check the process in addition to the registry to guard against
// situations in which an extension may still be enabled, but no longer
// running in a given process.
return;
}

ServiceWorkerTaskQueue::Get(browser_context_)
->DidInitializeServiceWorkerContext(render_process_id_, extension_id,
service_worker_version_id, thread_id);
}

void ExtensionServiceWorkerMessageFilter::OnDidStartServiceWorkerContext(
const ExtensionId& extension_id,
const base::UnguessableToken& activation_sequence,
Expand Down
3 changes: 0 additions & 3 deletions extensions/browser/extension_service_worker_message_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ class ExtensionServiceWorkerMessageFilter
int64_t service_worker_version_id,
int thread_id,
int event_id);
void OnDidInitializeServiceWorkerContext(const ExtensionId& extension_id,
int64_t service_worker_version_id,
int thread_id);
void OnDidStartServiceWorkerContext(
const ExtensionId& extension_id,
const base::UnguessableToken& activation_sequence,
Expand Down
84 changes: 84 additions & 0 deletions extensions/browser/service_worker/service_worker_host.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2023 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/browser/service_worker/service_worker_host.h"

#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_map.h"
#include "extensions/browser/service_worker_task_queue.h"

namespace extensions {

namespace {
const void* const kUserDataKey = &kUserDataKey;
} // namespace

ServiceWorkerHost::ServiceWorkerHost(
content::RenderProcessHost* render_process_host)
: render_process_host_(render_process_host) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}

ServiceWorkerHost::~ServiceWorkerHost() = default;

// static
void ServiceWorkerHost::BindReceiver(
int render_process_id,
mojo::PendingAssociatedReceiver<mojom::ServiceWorkerHost> receiver) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto* render_process_host =
content::RenderProcessHost::FromID(render_process_id);
if (!render_process_host) {
return;
}

auto* service_worker_host = static_cast<ServiceWorkerHost*>(
render_process_host->GetUserData(kUserDataKey));
if (!service_worker_host) {
auto new_host = std::make_unique<ServiceWorkerHost>(render_process_host);
service_worker_host = new_host.get();
render_process_host->SetUserData(kUserDataKey, std::move(new_host));
}

service_worker_host->receiver_.Bind(std::move(receiver));
service_worker_host->receiver_.reset_on_disconnect();
}

void ServiceWorkerHost::DidInitializeServiceWorkerContext(
const ExtensionId& extension_id,
int64_t service_worker_version_id,
int worker_thread_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserContext* browser_context = GetBrowserContext();
ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context);
DCHECK(registry);
if (!registry->enabled_extensions().GetByID(extension_id)) {
// This can happen if the extension is unloaded at this point. Just
// checking the extension process (as below) is insufficient because
// tearing down processes is async and happens after extension unload.
return;
}

int render_process_id = render_process_host_->GetID();
if (!ProcessMap::Get(browser_context)
->Contains(extension_id, render_process_id)) {
// We check the process in addition to the registry to guard against
// situations in which an extension may still be enabled, but no longer
// running in a given process.
return;
}

ServiceWorkerTaskQueue::Get(browser_context)
->DidInitializeServiceWorkerContext(render_process_id, extension_id,
service_worker_version_id,
worker_thread_id);
}

content::BrowserContext* ServiceWorkerHost::GetBrowserContext() {
return render_process_host_->GetBrowserContext();
}

} // namespace extensions
54 changes: 54 additions & 0 deletions extensions/browser/service_worker/service_worker_host.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EXTENSIONS_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HOST_H_
#define EXTENSIONS_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HOST_H_

#include "base/memory/raw_ptr.h"
#include "base/supports_user_data.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/mojom/service_worker_host.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"

namespace content {
class BrowserContext;
class RenderProcessHost;
} // namespace content

namespace extensions {

// This class is the host of service worker execution context for extension
// in the renderer process. Lives on the UI thread.
class ServiceWorkerHost : public base::SupportsUserData::Data,
public mojom::ServiceWorkerHost {
public:
explicit ServiceWorkerHost(content::RenderProcessHost* render_process_host);
ServiceWorkerHost(const ServiceWorkerHost&) = delete;
ServiceWorkerHost& operator=(const ServiceWorkerHost&) = delete;
~ServiceWorkerHost() override;

static void BindReceiver(
int render_process_id,
mojo::PendingAssociatedReceiver<mojom::ServiceWorkerHost> receiver);

// mojom::ServiceWorkerHost:
void DidInitializeServiceWorkerContext(const ExtensionId& extension_id,
int64_t service_worker_version_id,
int worker_thread_id) override;

private:
// Returns the browser context associated with the render process this
// `ServiceWorkerHost` belongs to.
content::BrowserContext* GetBrowserContext();

// This is safe because ServiceWorkerHost is tied to the life time of
// RenderProcessHost.
const raw_ptr<content::RenderProcessHost> render_process_host_;

mojo::AssociatedReceiver<mojom::ServiceWorkerHost> receiver_{this};
};

} // namespace extensions

#endif // EXTENSIONS_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HOST_H_
1 change: 1 addition & 0 deletions extensions/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ mojom("mojom") {
"mojom/renderer.mojom",
"mojom/renderer_host.mojom",
"mojom/run_location.mojom",
"mojom/service_worker_host.mojom",
"mojom/stack_frame.mojom",
"mojom/url_pattern_set.mojom",
"mojom/view_type.mojom",
Expand Down
7 changes: 0 additions & 7 deletions extensions/common/extension_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,6 @@ IPC_MESSAGE_CONTROL4(ExtensionHostMsg_EventAckWorker,
int /* worker_thread_id */,
int /* event_id */)

// Tells the browser that an extension service worker context was initialized,
// but possibly didn't start executing its top-level JavaScript.
IPC_MESSAGE_CONTROL3(ExtensionHostMsg_DidInitializeServiceWorkerContext,
std::string /* extension_id */,
int64_t /* service_worker_version_id */,
int /* worker_thread_id */)

// Tells the browser that an extension service worker context has started and
// finished executing its top-level JavaScript.
// Start corresponds to EmbeddedWorkerInstance::OnStarted notification.
Expand Down
15 changes: 15 additions & 0 deletions extensions/common/mojom/service_worker_host.mojom
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module extensions.mojom;

// An interface for an extension service worker context. Implemented in the
// browser process.
interface ServiceWorkerHost {
// Tells the browser that an extension service worker context was initialized,
// but possibly didn't start executing its top-level JavaScript.
DidInitializeServiceWorkerContext(string extension_id,
int64 service_worker_version_id,
int32 worker_thread_id);
};
25 changes: 24 additions & 1 deletion extensions/renderer/worker_thread_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,11 @@ bool WorkerThreadDispatcher::PostTaskToWorkerThread(int worker_thread_id,
return task_posted;
}

void WorkerThreadDispatcher::PostTaskToIOThread(base::OnceClosure task) {
bool task_posted = io_task_runner_->PostTask(FROM_HERE, std::move(task));
DCHECK(task_posted) << "Could not PostTask IPC to IO thread.";
}

bool WorkerThreadDispatcher::Send(IPC::Message* message) {
return message_filter_->Send(message);
}
Expand All @@ -353,6 +358,17 @@ mojom::EventRouter* WorkerThreadDispatcher::GetEventRouterOnIO() {
return event_router_remote_.get();
}

mojom::ServiceWorkerHost* WorkerThreadDispatcher::GetServiceWorkerHostOnIO() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (!service_worker_host_) {
mojo::PendingAssociatedRemote<mojom::ServiceWorkerHost>
pending_service_worker_host;
message_filter_->GetRemoteAssociatedInterface(&pending_service_worker_host);
service_worker_host_.Bind(std::move(pending_service_worker_host));
}
return service_worker_host_.get();
}

void WorkerThreadDispatcher::OnResponseWorker(
int worker_thread_id,
int request_id,
Expand Down Expand Up @@ -483,7 +499,14 @@ void WorkerThreadDispatcher::DidInitializeContext(
DCHECK_EQ(service_worker_version_id, data->service_worker_version_id());
const int thread_id = content::WorkerThread::GetCurrentId();
DCHECK_NE(thread_id, kMainThreadId);
Send(new ExtensionHostMsg_DidInitializeServiceWorkerContext(
PostTaskToIOThread(base::BindOnce(
[](const ExtensionId& extension_id, int64_t service_worker_version_id,
int thread_id) {
WorkerThreadDispatcher::Get()
->GetServiceWorkerHostOnIO()
->DidInitializeServiceWorkerContext(
extension_id, service_worker_version_id, thread_id);
},
data->context()->GetExtensionID(), service_worker_version_id, thread_id));
}

Expand Down
6 changes: 6 additions & 0 deletions extensions/renderer/worker_thread_dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "extensions/common/extension_messages.h"
#include "extensions/common/mojom/event_dispatcher.mojom.h"
#include "extensions/common/mojom/event_router.mojom.h"
#include "extensions/common/mojom/service_worker_host.mojom.h"
#include "ipc/ipc_sync_message_filter.h"
#include "mojo/public/cpp/bindings/associated_remote.h"

Expand Down Expand Up @@ -150,7 +151,10 @@ class WorkerThreadDispatcher : public content::RenderThreadObserver,
// NOTE: This must be called on the IO thread because it can call
// SyncMessageFilter::GetRemoteAssociatedInterface() which must be called on
// the IO thread.
// TODO(https://crbug.com/1364183): Obtain these interfaces at the worker
// thread once `AssociatedInterfaceRegistry` for ServiceWorker is added.
mojom::EventRouter* GetEventRouterOnIO();
mojom::ServiceWorkerHost* GetServiceWorkerHostOnIO();

// Mojo interface implementation, called from the main thread.
void DispatchEvent(mojom::DispatchEventParamsPtr params,
Expand All @@ -167,6 +171,7 @@ class WorkerThreadDispatcher : public content::RenderThreadObserver,
const IPC::Message& message);

bool PostTaskToWorkerThread(int worker_thread_id, base::OnceClosure task);
void PostTaskToIOThread(base::OnceClosure task);

// IPC handlers.
void OnResponseWorker(int worker_thread_id,
Expand Down Expand Up @@ -198,6 +203,7 @@ class WorkerThreadDispatcher : public content::RenderThreadObserver,
base::Lock task_runner_map_lock_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
mojo::AssociatedRemote<mojom::EventRouter> event_router_remote_;
mojo::AssociatedRemote<mojom::ServiceWorkerHost> service_worker_host_;
};

} // namespace extensions
Expand Down

0 comments on commit 93b78dd

Please sign in to comment.