LibWeb+LibWebView+Services: Add IPC for starting WebWorker of a type

The provides some of the plumbing for a WebContent process to spin
up a WebWorker that is not just a dedicated worker.
This commit is contained in:
Shannon Booth 2025-04-24 17:07:09 +12:00 committed by Andreas Kling
commit a2cca59516
Notes: github-actions[bot] 2025-04-25 14:45:22 +00:00
10 changed files with 49 additions and 13 deletions

View file

@ -34,7 +34,7 @@ void WorkerAgentParent::initialize(JS::Realm& realm)
// NOTE: This blocking IPC call may launch another process.
// If spinning the event loop for this can cause other javascript to execute, we're in trouble.
auto worker_socket_file = Bindings::principal_host_defined_page(realm).client().request_worker_agent();
auto worker_socket_file = Bindings::principal_host_defined_page(realm).client().request_worker_agent(Bindings::AgentType::DedicatedWorker);
auto worker_socket = MUST(Core::LocalSocket::adopt_fd(worker_socket_file.take_fd()));
MUST(worker_socket->set_blocking(true));

View file

@ -2,7 +2,7 @@
* Copyright (c) 2020-2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2025, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -20,6 +20,7 @@
#include <LibGfx/Size.h>
#include <LibIPC/Forward.h>
#include <LibURL/URL.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/CSS/PreferredColorScheme.h>
#include <LibWeb/CSS/PreferredContrast.h>
#include <LibWeb/CSS/PreferredMotion.h>
@ -396,7 +397,7 @@ public:
virtual void page_did_change_audio_play_state(HTML::AudioPlayState) { }
virtual IPC::File request_worker_agent() { return IPC::File {}; }
virtual IPC::File request_worker_agent([[maybe_unused]] Web::Bindings::AgentType worker_type) { return IPC::File {}; }
virtual void page_did_mutate_dom([[maybe_unused]] FlyString const& type, [[maybe_unused]] DOM::Node const& target, [[maybe_unused]] DOM::NodeList& added_nodes, [[maybe_unused]] DOM::NodeList& removed_nodes, [[maybe_unused]] GC::Ptr<DOM::Node> previous_sibling, [[maybe_unused]] GC::Ptr<DOM::Node> next_sibling, [[maybe_unused]] Optional<String> const& attribute_name) { }

View file

@ -167,7 +167,7 @@ ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process(
return launch_server_process<ImageDecoderClient::Client>("ImageDecoder"sv, arguments);
}
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process()
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(Web::Bindings::AgentType type)
{
Vector<ByteString> arguments;
@ -179,6 +179,21 @@ ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process()
arguments.append("--image-decoder-socket"sv);
arguments.append(ByteString::number(image_decoder_socket.fd()));
arguments.append("--type"sv);
switch (type) {
case Web::Bindings::AgentType::DedicatedWorker:
arguments.append("dedicated"sv);
break;
case Web::Bindings::AgentType::SharedWorker:
arguments.append("shared"sv);
break;
case Web::Bindings::AgentType::ServiceWorker:
arguments.append("service"sv);
break;
default:
VERIFY_NOT_REACHED();
}
return launch_server_process<Web::HTML::WebWorkerClient>("WebWorker"sv, move(arguments));
}

View file

@ -10,6 +10,7 @@
#include <AK/Optional.h>
#include <LibImageDecoderClient/Client.h>
#include <LibRequests/RequestClient.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Worker/WebWorkerClient.h>
#include <LibWebView/ViewImplementation.h>
#include <LibWebView/WebContentClient.h>
@ -26,7 +27,7 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_spare_web_content_proce
Optional<IPC::File> request_server_socket = {});
ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process();
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process();
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(Web::Bindings::AgentType);
ErrorOr<NonnullRefPtr<Requests::RequestClient>> launch_request_server_process();
ErrorOr<IPC::File> connect_new_request_server_client();

View file

@ -659,10 +659,10 @@ void WebContentClient::did_allocate_backing_stores(u64 page_id, i32 front_bitmap
view->did_allocate_backing_stores({}, front_bitmap_id, front_bitmap, back_bitmap_id, back_bitmap);
}
Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request_worker_agent(u64 page_id)
Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request_worker_agent(u64 page_id, Web::Bindings::AgentType worker_type)
{
if (auto view = view_for_page_id(page_id); view.has_value()) {
auto worker_client = MUST(WebView::launch_web_worker_process());
auto worker_client = MUST(WebView::launch_web_worker_process(worker_type));
return worker_client->clone_transport();
}

View file

@ -10,6 +10,7 @@
#include <AK/SourceLocation.h>
#include <LibIPC/ConnectionToServer.h>
#include <LibIPC/Transport.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/CSS/StyleSheetIdentifier.h>
#include <LibWeb/HTML/ActivateTab.h>
#include <LibWeb/HTML/FileFilter.h>
@ -129,7 +130,7 @@ private:
virtual void did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState) override;
virtual void did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) override;
virtual void did_allocate_backing_stores(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap, i32 back_bitmap_id, Gfx::ShareableBitmap) override;
virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent(u64 page_id) override;
virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent(u64 page_id, Web::Bindings::AgentType worker_type) override;
Optional<ViewImplementation&> view_for_page_id(u64, SourceLocation = SourceLocation::current());

View file

@ -664,9 +664,9 @@ void PageClient::page_did_allocate_backing_stores(i32 front_bitmap_id, Gfx::Shar
client().async_did_allocate_backing_stores(m_id, front_bitmap_id, front_bitmap, back_bitmap_id, back_bitmap);
}
IPC::File PageClient::request_worker_agent()
IPC::File PageClient::request_worker_agent(Web::Bindings::AgentType type)
{
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::RequestWorkerAgent>(m_id);
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::RequestWorkerAgent>(m_id, type);
if (!response) {
dbgln("WebContent client disconnected during RequestWorkerAgent. Exiting peacefully.");
exit(0);

View file

@ -172,7 +172,7 @@ private:
virtual void page_did_insert_clipboard_entry(StringView data, StringView presentation_style, StringView mime_type) override;
virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override;
virtual void page_did_allocate_backing_stores(i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) override;
virtual IPC::File request_worker_agent() override;
virtual IPC::File request_worker_agent(Web::Bindings::AgentType) override;
virtual void page_did_mutate_dom(FlyString const& type, Web::DOM::Node const& target, Web::DOM::NodeList& added_nodes, Web::DOM::NodeList& removed_nodes, GC::Ptr<Web::DOM::Node> previous_sibling, GC::Ptr<Web::DOM::Node> next_sibling, Optional<String> const& attribute_name) override;
virtual void received_message_from_web_ui(String const& name, JS::Value data) override;

View file

@ -21,6 +21,7 @@
#include <LibWebView/Mutation.h>
#include <LibWebView/PageInfo.h>
#include <LibWebView/ProcessHandle.h>
#include <LibWeb/Bindings/MainThreadVM.h>
endpoint WebContentClient
{
@ -107,5 +108,5 @@ endpoint WebContentClient
did_find_in_page(u64 page_id, size_t current_match_index, Optional<size_t> total_match_count) =|
request_worker_agent(u64 page_id) => (IPC::File socket) // FIXME: Add required attributes to select a SharedWorker Agent
request_worker_agent(u64 page_id, Web::Bindings::AgentType worker_type) => (IPC::File socket) // FIXME: Add required attributes to select a SharedWorker Agent
}

View file

@ -33,6 +33,18 @@
static ErrorOr<void> initialize_image_decoder(int image_decoder_socket);
static ErrorOr<void> initialize_resource_loader(GC::Heap&, int request_server_socket);
static ErrorOr<Web::Bindings::AgentType> agent_type_from_string(StringView type)
{
if (type == "dedicated"sv)
return Web::Bindings::AgentType::DedicatedWorker;
if (type == "shared"sv)
return Web::Bindings::AgentType::SharedWorker;
if (type == "service"sv)
return Web::Bindings::AgentType::ServiceWorker;
return Error::from_string_literal("Invalid worker type, must be one of: 'dedicated', 'shared', or 'service'");
}
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
AK::set_rich_debug_enabled(true);
@ -40,6 +52,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
int request_server_socket { -1 };
int image_decoder_socket { -1 };
StringView serenity_resource_root;
StringView worker_type_string;
Vector<ByteString> certificates;
bool wait_for_debugger = false;
@ -49,11 +62,15 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.add_option(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root");
args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
args_parser.add_option(wait_for_debugger, "Wait for debugger", "wait-for-debugger");
args_parser.add_option(worker_type_string, "Type of WebWorker to start (dedicated, shared, or service)", "type", 't', "type");
args_parser.parse(arguments);
if (wait_for_debugger)
Core::Process::wait_for_debugger_and_break();
auto worker_type = TRY(agent_type_from_string(worker_type_string));
#if defined(HAVE_QT)
QCoreApplication app(arguments.argc, arguments.argv);
Core::EventLoopManager::install(*new WebView::EventLoopManagerQt);
@ -68,7 +85,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
Web::Platform::FontPlugin::install(*new WebView::FontPlugin(false));
Web::Bindings::initialize_main_thread_vm(Web::Bindings::AgentType::DedicatedWorker);
Web::Bindings::initialize_main_thread_vm(worker_type);
TRY(initialize_resource_loader(Web::Bindings::main_thread_vm().heap(), request_server_socket));