mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-05 15:49:15 +00:00
Ladybird+Userland: Remove use of unnecessary fd passing socket concept
Now that LibIPC is using SCM_RIGHTS properly, we can go back to only having one socket laying around when needing to transfer fds to peers.
This commit is contained in:
parent
cb87725ec8
commit
5e1d678bae
Notes:
sideshowbarker
2024-07-16 23:38:54 +09:00
Author: https://github.com/ADKaster
Commit: 5e1d678bae
Pull-request: https://github.com/SerenityOS/serenity/pull/24025
Issue: https://github.com/SerenityOS/serenity/issues/22357
Reviewed-by: https://github.com/trflynn89 ✅
32 changed files with 61 additions and 236 deletions
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibIPC/Forward.h>
|
||||||
#include <LibWebView/Forward.h>
|
#include <LibWebView/Forward.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
|
|
||||||
#import <System/Cocoa.h>
|
#import <System/Cocoa.h>
|
||||||
|
|
||||||
|
@ -23,6 +23,6 @@ class WebViewBridge;
|
||||||
|
|
||||||
- (ErrorOr<void>)launchRequestServer:(Vector<ByteString> const&)certificates;
|
- (ErrorOr<void>)launchRequestServer:(Vector<ByteString> const&)certificates;
|
||||||
- (ErrorOr<NonnullRefPtr<WebView::WebContentClient>>)launchWebContent:(Ladybird::WebViewBridge&)web_view_bridge;
|
- (ErrorOr<NonnullRefPtr<WebView::WebContentClient>>)launchWebContent:(Ladybird::WebViewBridge&)web_view_bridge;
|
||||||
- (ErrorOr<WebView::SocketPair>)launchWebWorker;
|
- (ErrorOr<IPC::File>)launchWebWorker;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
return m_application_bridge->launch_web_content(web_view_bridge);
|
return m_application_bridge->launch_web_content(web_view_bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ErrorOr<WebView::SocketPair>)launchWebWorker
|
- (ErrorOr<IPC::File>)launchWebWorker
|
||||||
{
|
{
|
||||||
return m_application_bridge->launch_web_worker();
|
return m_application_bridge->launch_web_worker();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,20 +40,20 @@ ErrorOr<void> ApplicationBridge::launch_request_server(Vector<ByteString> const&
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ApplicationBridge::launch_web_content(WebViewBridge& web_view_bridge)
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ApplicationBridge::launch_web_content(WebViewBridge& web_view_bridge)
|
||||||
{
|
{
|
||||||
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
|
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
|
||||||
auto request_server_sockets = TRY(connect_new_request_server_client(*m_impl->request_server_client));
|
auto request_server_socket = TRY(connect_new_request_server_client(*m_impl->request_server_client));
|
||||||
|
|
||||||
auto web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
|
auto web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
|
||||||
auto web_content = TRY(launch_web_content_process(web_view_bridge, web_content_paths, web_view_bridge.web_content_options(), move(request_server_sockets)));
|
auto web_content = TRY(launch_web_content_process(web_view_bridge, web_content_paths, web_view_bridge.web_content_options(), move(request_server_socket)));
|
||||||
|
|
||||||
return web_content;
|
return web_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<WebView::SocketPair> ApplicationBridge::launch_web_worker()
|
ErrorOr<IPC::File> ApplicationBridge::launch_web_worker()
|
||||||
{
|
{
|
||||||
auto web_worker_paths = TRY(get_paths_for_helper_process("WebWorker"sv));
|
auto web_worker_paths = TRY(get_paths_for_helper_process("WebWorker"sv));
|
||||||
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, *m_impl->request_server_client));
|
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, *m_impl->request_server_client));
|
||||||
|
|
||||||
return worker_client->dup_sockets();
|
return worker_client->dup_socket();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#include <AK/NonnullOwnPtr.h>
|
#include <AK/NonnullOwnPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibIPC/Forward.h>
|
||||||
#include <LibWebView/Forward.h>
|
#include <LibWebView/Forward.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
|
|
||||||
namespace Ladybird {
|
namespace Ladybird {
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public:
|
||||||
|
|
||||||
ErrorOr<void> launch_request_server(Vector<ByteString> const& certificates);
|
ErrorOr<void> launch_request_server(Vector<ByteString> const& certificates);
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content(WebViewBridge&);
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content(WebViewBridge&);
|
||||||
ErrorOr<WebView::SocketPair> launch_web_worker();
|
ErrorOr<IPC::File> launch_web_worker();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NonnullOwnPtr<ApplicationBridgeImpl> m_impl;
|
NonnullOwnPtr<ApplicationBridgeImpl> m_impl;
|
||||||
|
|
|
@ -13,7 +13,7 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
WebView::ViewImplementation& view,
|
WebView::ViewImplementation& view,
|
||||||
ReadonlySpan<ByteString> candidate_web_content_paths,
|
ReadonlySpan<ByteString> candidate_web_content_paths,
|
||||||
Ladybird::WebContentOptions const& web_content_options,
|
Ladybird::WebContentOptions const& web_content_options,
|
||||||
Optional<WebView::SocketPair> request_server_sockets)
|
Optional<IPC::File> request_server_socket)
|
||||||
{
|
{
|
||||||
int socket_fds[2] {};
|
int socket_fds[2] {};
|
||||||
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
|
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
|
||||||
|
@ -21,22 +21,13 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
int ui_fd = socket_fds[0];
|
int ui_fd = socket_fds[0];
|
||||||
int wc_fd = socket_fds[1];
|
int wc_fd = socket_fds[1];
|
||||||
|
|
||||||
int fd_passing_socket_fds[2] {};
|
|
||||||
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds));
|
|
||||||
|
|
||||||
int ui_fd_passing_fd = fd_passing_socket_fds[0];
|
|
||||||
int wc_fd_passing_fd = fd_passing_socket_fds[1];
|
|
||||||
|
|
||||||
auto child_pid = TRY(Core::System::fork());
|
auto child_pid = TRY(Core::System::fork());
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
TRY(Core::System::close(ui_fd_passing_fd));
|
|
||||||
TRY(Core::System::close(ui_fd));
|
TRY(Core::System::close(ui_fd));
|
||||||
|
|
||||||
auto takeover_string = TRY(String::formatted("WebContent:{}", wc_fd));
|
auto takeover_string = TRY(String::formatted("WebContent:{}", wc_fd));
|
||||||
TRY(Core::Environment::set("SOCKET_TAKEOVER"sv, takeover_string, Core::Environment::Overwrite::Yes));
|
TRY(Core::Environment::set("SOCKET_TAKEOVER"sv, takeover_string, Core::Environment::Overwrite::Yes));
|
||||||
|
|
||||||
auto webcontent_fd_passing_socket_string = TRY(String::number(wc_fd_passing_fd));
|
|
||||||
|
|
||||||
ErrorOr<void> result;
|
ErrorOr<void> result;
|
||||||
for (auto const& path : candidate_web_content_paths) {
|
for (auto const& path : candidate_web_content_paths) {
|
||||||
constexpr auto callgrind_prefix_length = 3;
|
constexpr auto callgrind_prefix_length = 3;
|
||||||
|
@ -53,8 +44,6 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
web_content_options.command_line,
|
web_content_options.command_line,
|
||||||
"--executable-path"sv,
|
"--executable-path"sv,
|
||||||
web_content_options.executable_path,
|
web_content_options.executable_path,
|
||||||
"--webcontent-fd-passing-socket"sv,
|
|
||||||
webcontent_fd_passing_socket_string
|
|
||||||
};
|
};
|
||||||
if (web_content_options.enable_callgrind_profiling == Ladybird::EnableCallgrindProfiling::No)
|
if (web_content_options.enable_callgrind_profiling == Ladybird::EnableCallgrindProfiling::No)
|
||||||
arguments.remove(0, callgrind_prefix_length);
|
arguments.remove(0, callgrind_prefix_length);
|
||||||
|
@ -74,14 +63,11 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
arguments.append("--mach-server-name"sv);
|
arguments.append("--mach-server-name"sv);
|
||||||
arguments.append(server.value());
|
arguments.append(server.value());
|
||||||
}
|
}
|
||||||
Vector<String> fd_strings;
|
String fd_string;
|
||||||
if (request_server_sockets.has_value()) {
|
if (request_server_socket.has_value()) {
|
||||||
arguments.append("--request-server-socket"sv);
|
arguments.append("--request-server-socket"sv);
|
||||||
fd_strings.append(MUST(String::number(request_server_sockets->socket.fd())));
|
fd_string = MUST(String::number(request_server_socket->fd()));
|
||||||
arguments.append(fd_strings.last());
|
arguments.append(fd_string.bytes_as_string_view());
|
||||||
arguments.append("--request-server-fd-passing-socket"sv);
|
|
||||||
fd_strings.append(MUST(String::number(request_server_sockets->fd_passing_socket.fd())));
|
|
||||||
arguments.append(fd_strings.last());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Core::System::exec(arguments[0], arguments.span(), Core::System::SearchInPath::Yes);
|
result = Core::System::exec(arguments[0], arguments.span(), Core::System::SearchInPath::Yes);
|
||||||
|
@ -94,14 +80,12 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(Core::System::close(wc_fd_passing_fd));
|
|
||||||
TRY(Core::System::close(wc_fd));
|
TRY(Core::System::close(wc_fd));
|
||||||
|
|
||||||
auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
|
auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
|
||||||
TRY(socket->set_blocking(true));
|
TRY(socket->set_blocking(true));
|
||||||
|
|
||||||
auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), view)));
|
auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), view)));
|
||||||
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
|
|
||||||
|
|
||||||
if (web_content_options.enable_callgrind_profiling == Ladybird::EnableCallgrindProfiling::Yes) {
|
if (web_content_options.enable_callgrind_profiling == Ladybird::EnableCallgrindProfiling::Yes) {
|
||||||
dbgln();
|
dbgln();
|
||||||
|
@ -122,22 +106,13 @@ ErrorOr<NonnullRefPtr<Client>> launch_generic_server_process(ReadonlySpan<ByteSt
|
||||||
int ui_fd = socket_fds[0];
|
int ui_fd = socket_fds[0];
|
||||||
int server_fd = socket_fds[1];
|
int server_fd = socket_fds[1];
|
||||||
|
|
||||||
int fd_passing_socket_fds[2] {};
|
|
||||||
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds));
|
|
||||||
|
|
||||||
int ui_fd_passing_fd = fd_passing_socket_fds[0];
|
|
||||||
int server_fd_passing_fd = fd_passing_socket_fds[1];
|
|
||||||
|
|
||||||
auto child_pid = TRY(Core::System::fork());
|
auto child_pid = TRY(Core::System::fork());
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
TRY(Core::System::close(ui_fd));
|
TRY(Core::System::close(ui_fd));
|
||||||
TRY(Core::System::close(ui_fd_passing_fd));
|
|
||||||
|
|
||||||
auto takeover_string = TRY(String::formatted("{}:{}", server_name, server_fd));
|
auto takeover_string = TRY(String::formatted("{}:{}", server_name, server_fd));
|
||||||
TRY(Core::Environment::set("SOCKET_TAKEOVER"sv, takeover_string, Core::Environment::Overwrite::Yes));
|
TRY(Core::Environment::set("SOCKET_TAKEOVER"sv, takeover_string, Core::Environment::Overwrite::Yes));
|
||||||
|
|
||||||
auto fd_passing_socket_string = TRY(String::number(server_fd_passing_fd));
|
|
||||||
|
|
||||||
ErrorOr<void> result;
|
ErrorOr<void> result;
|
||||||
for (auto const& path : candidate_server_paths) {
|
for (auto const& path : candidate_server_paths) {
|
||||||
|
|
||||||
|
@ -146,8 +121,6 @@ ErrorOr<NonnullRefPtr<Client>> launch_generic_server_process(ReadonlySpan<ByteSt
|
||||||
|
|
||||||
auto arguments = Vector<StringView> {
|
auto arguments = Vector<StringView> {
|
||||||
path.view(),
|
path.view(),
|
||||||
"--fd-passing-socket"sv,
|
|
||||||
fd_passing_socket_string,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!extra_arguments.is_empty())
|
if (!extra_arguments.is_empty())
|
||||||
|
@ -164,13 +137,11 @@ ErrorOr<NonnullRefPtr<Client>> launch_generic_server_process(ReadonlySpan<ByteSt
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(Core::System::close(server_fd));
|
TRY(Core::System::close(server_fd));
|
||||||
TRY(Core::System::close(server_fd_passing_fd));
|
|
||||||
|
|
||||||
auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
|
auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd));
|
||||||
TRY(socket->set_blocking(true));
|
TRY(socket->set_blocking(true));
|
||||||
|
|
||||||
auto new_client = TRY(try_make_ref_counted<Client>(move(socket)));
|
auto new_client = TRY(try_make_ref_counted<Client>(move(socket)));
|
||||||
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd)));
|
|
||||||
|
|
||||||
WebView::ProcessManager::the().add_process(WebView::process_type_from_name(server_name), child_pid);
|
WebView::ProcessManager::the().add_process(WebView::process_type_from_name(server_name), child_pid);
|
||||||
|
|
||||||
|
@ -184,17 +155,13 @@ ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process(
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, NonnullRefPtr<Protocol::RequestClient> request_client)
|
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, NonnullRefPtr<Protocol::RequestClient> request_client)
|
||||||
{
|
{
|
||||||
auto request_server_sockets = TRY(connect_new_request_server_client(move(request_client)));
|
auto socket = TRY(connect_new_request_server_client(move(request_client)));
|
||||||
|
|
||||||
Vector<StringView> arguments;
|
Vector<StringView> arguments;
|
||||||
Vector<String> fd_strings;
|
String fd_string = MUST(String::number(socket.fd()));
|
||||||
|
|
||||||
arguments.append("--request-server-socket"sv);
|
arguments.append("--request-server-socket"sv);
|
||||||
fd_strings.append(MUST(String::number(request_server_sockets.socket.fd())));
|
arguments.append(fd_string.bytes_as_string_view());
|
||||||
arguments.append(fd_strings.last());
|
|
||||||
arguments.append("--request-server-fd-passing-socket"sv);
|
|
||||||
fd_strings.append(MUST(String::number(request_server_sockets.fd_passing_socket.fd())));
|
|
||||||
arguments.append(fd_strings.last());
|
|
||||||
|
|
||||||
return launch_generic_server_process<Web::HTML::WebWorkerClient>(candidate_web_worker_paths, "WebWorker"sv, move(arguments));
|
return launch_generic_server_process<Web::HTML::WebWorkerClient>(candidate_web_worker_paths, "WebWorker"sv, move(arguments));
|
||||||
}
|
}
|
||||||
|
@ -215,23 +182,21 @@ ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(Re
|
||||||
return launch_generic_server_process<Protocol::RequestClient>(candidate_request_server_paths, "RequestServer"sv, move(arguments));
|
return launch_generic_server_process<Protocol::RequestClient>(candidate_request_server_paths, "RequestServer"sv, move(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<WebView::SocketPair> connect_new_request_server_client(Protocol::RequestClient& client)
|
ErrorOr<IPC::File> connect_new_request_server_client(Protocol::RequestClient& client)
|
||||||
{
|
{
|
||||||
auto new_sockets = client.send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClient>();
|
auto new_socket = client.send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClient>();
|
||||||
if (!new_sockets)
|
if (!new_socket)
|
||||||
return Error::from_string_literal("Failed to connect to RequestServer");
|
return Error::from_string_literal("Failed to connect to RequestServer");
|
||||||
|
|
||||||
auto socket = new_sockets->take_client_socket();
|
auto socket = new_socket->take_client_socket();
|
||||||
auto fd_passing_socket = new_sockets->take_client_fd_passing_socket();
|
|
||||||
|
|
||||||
// FIXME: IPC::Files transferred over the wire are always set O_CLOEXEC during decoding.
|
// FIXME: IPC::Files transferred over the wire are always set O_CLOEXEC during decoding.
|
||||||
// Perhaps we should add an option to IPC::File to allow the receiver to decide whether to
|
// Perhaps we should add an option to IPC::File to allow the receiver to decide whether to
|
||||||
// make it O_CLOEXEC or not. Or an attribute in the .ipc file?
|
// make it O_CLOEXEC or not. Or an attribute in the .ipc file?
|
||||||
for (auto fd : { socket.fd(), fd_passing_socket.fd() }) {
|
auto fd = socket.fd();
|
||||||
auto fd_flags = MUST(Core::System::fcntl(fd, F_GETFD));
|
auto fd_flags = MUST(Core::System::fcntl(fd, F_GETFD));
|
||||||
fd_flags &= ~FD_CLOEXEC;
|
fd_flags &= ~FD_CLOEXEC;
|
||||||
MUST(Core::System::fcntl(fd, F_SETFD, fd_flags));
|
MUST(Core::System::fcntl(fd, F_SETFD, fd_flags));
|
||||||
}
|
|
||||||
|
|
||||||
return WebView::SocketPair { move(socket), move(fd_passing_socket) };
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <LibImageDecoderClient/Client.h>
|
#include <LibImageDecoderClient/Client.h>
|
||||||
#include <LibProtocol/RequestClient.h>
|
#include <LibProtocol/RequestClient.h>
|
||||||
#include <LibWeb/Worker/WebWorkerClient.h>
|
#include <LibWeb/Worker/WebWorkerClient.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
#include <LibWebView/ViewImplementation.h>
|
#include <LibWebView/ViewImplementation.h>
|
||||||
#include <LibWebView/WebContentClient.h>
|
#include <LibWebView/WebContentClient.h>
|
||||||
|
|
||||||
|
@ -22,10 +21,10 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
||||||
WebView::ViewImplementation& view,
|
WebView::ViewImplementation& view,
|
||||||
ReadonlySpan<ByteString> candidate_web_content_paths,
|
ReadonlySpan<ByteString> candidate_web_content_paths,
|
||||||
Ladybird::WebContentOptions const&,
|
Ladybird::WebContentOptions const&,
|
||||||
Optional<WebView::SocketPair> request_server_sockets = {});
|
Optional<IPC::File> request_server_socket = {});
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process(ReadonlySpan<ByteString> candidate_image_decoder_paths);
|
ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process(ReadonlySpan<ByteString> candidate_image_decoder_paths);
|
||||||
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, NonnullRefPtr<Protocol::RequestClient>);
|
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, NonnullRefPtr<Protocol::RequestClient>);
|
||||||
ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(ReadonlySpan<ByteString> candidate_request_server_paths, StringView serenity_resource_root, Vector<ByteString> const& certificates);
|
ErrorOr<NonnullRefPtr<Protocol::RequestClient>> launch_request_server_process(ReadonlySpan<ByteString> candidate_request_server_paths, StringView serenity_resource_root, Vector<ByteString> const& certificates);
|
||||||
|
|
||||||
ErrorOr<WebView::SocketPair> connect_new_request_server_client(Protocol::RequestClient&);
|
ErrorOr<IPC::File> connect_new_request_server_client(Protocol::RequestClient&);
|
||||||
|
|
|
@ -12,24 +12,13 @@
|
||||||
#include <LibIPC/SingleServer.h>
|
#include <LibIPC/SingleServer.h>
|
||||||
#include <LibMain/Main.h>
|
#include <LibMain/Main.h>
|
||||||
|
|
||||||
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
ErrorOr<int> serenity_main(Main::Arguments)
|
||||||
{
|
{
|
||||||
AK::set_rich_debug_enabled(true);
|
AK::set_rich_debug_enabled(true);
|
||||||
|
|
||||||
int fd_passing_socket { -1 };
|
|
||||||
StringView serenity_resource_root;
|
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
|
||||||
args_parser.add_option(fd_passing_socket, "File descriptor of the fd passing socket", "fd-passing-socket", 'c', "fd-passing-socket");
|
|
||||||
args_parser.add_option(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root");
|
|
||||||
args_parser.parse(arguments);
|
|
||||||
|
|
||||||
Core::EventLoop event_loop;
|
Core::EventLoop event_loop;
|
||||||
|
|
||||||
auto client = TRY(IPC::take_over_accepted_client_from_system_server<ImageDecoder::ConnectionFromClient>());
|
auto client = TRY(IPC::take_over_accepted_client_from_system_server<ImageDecoder::ConnectionFromClient>());
|
||||||
client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
|
|
||||||
|
|
||||||
auto result = event_loop.exec();
|
return event_loop.exec();
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include <LibGfx/SystemTheme.h>
|
#include <LibGfx/SystemTheme.h>
|
||||||
#include <LibWeb/Crypto/Crypto.h>
|
#include <LibWeb/Crypto/Crypto.h>
|
||||||
#include <LibWeb/Worker/WebWorkerClient.h>
|
#include <LibWeb/Worker/WebWorkerClient.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
#include <LibWebView/WebContentClient.h>
|
#include <LibWebView/WebContentClient.h>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
|
@ -125,7 +124,7 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
|
||||||
on_request_worker_agent = []() {
|
on_request_worker_agent = []() {
|
||||||
auto& request_server_client = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
auto& request_server_client = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
||||||
auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), *request_server_client));
|
auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), *request_server_client));
|
||||||
return worker_client->dup_sockets();
|
return worker_client->dup_socket();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,17 +533,17 @@ void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewCli
|
||||||
if (create_new_client == CreateNewClient::Yes) {
|
if (create_new_client == CreateNewClient::Yes) {
|
||||||
m_client_state = {};
|
m_client_state = {};
|
||||||
|
|
||||||
Optional<WebView::SocketPair> request_server_sockets;
|
Optional<IPC::File> request_server_socket;
|
||||||
if (m_web_content_options.use_lagom_networking == UseLagomNetworking::Yes) {
|
if (m_web_content_options.use_lagom_networking == UseLagomNetworking::Yes) {
|
||||||
auto& protocol = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
auto& protocol = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
||||||
|
|
||||||
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
|
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
|
||||||
auto sockets = connect_new_request_server_client(*protocol).release_value_but_fixme_should_propagate_errors();
|
auto socket = connect_new_request_server_client(*protocol).release_value_but_fixme_should_propagate_errors();
|
||||||
request_server_sockets = AK::move(sockets);
|
request_server_socket = AK::move(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
|
auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
|
||||||
auto new_client = launch_web_content_process(*this, candidate_web_content_paths, m_web_content_options, AK::move(request_server_sockets)).release_value_but_fixme_should_propagate_errors();
|
auto new_client = launch_web_content_process(*this, candidate_web_content_paths, m_web_content_options, AK::move(request_server_socket)).release_value_but_fixme_should_propagate_errors();
|
||||||
|
|
||||||
m_client_state.client = new_client;
|
m_client_state.client = new_client;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <RequestServer/HttpProtocol.h>
|
#include <RequestServer/HttpProtocol.h>
|
||||||
#include <RequestServer/HttpsProtocol.h>
|
#include <RequestServer/HttpsProtocol.h>
|
||||||
|
|
||||||
// FIXME: Share b/w RequestServer and WebSocket
|
|
||||||
ErrorOr<ByteString> find_certificates(StringView serenity_resource_root)
|
ErrorOr<ByteString> find_certificates(StringView serenity_resource_root)
|
||||||
{
|
{
|
||||||
auto cert_path = ByteString::formatted("{}/ladybird/cacert.pem", serenity_resource_root);
|
auto cert_path = ByteString::formatted("{}/ladybird/cacert.pem", serenity_resource_root);
|
||||||
|
@ -33,12 +32,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
{
|
{
|
||||||
AK::set_rich_debug_enabled(true);
|
AK::set_rich_debug_enabled(true);
|
||||||
|
|
||||||
int fd_passing_socket { -1 };
|
|
||||||
StringView serenity_resource_root;
|
StringView serenity_resource_root;
|
||||||
Vector<ByteString> certificates;
|
Vector<ByteString> certificates;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_option(fd_passing_socket, "File descriptor of the fd passing socket", "fd-passing-socket", 'c', "fd-passing-socket");
|
|
||||||
args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
|
args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
|
||||||
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(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root");
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
@ -56,7 +53,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
RequestServer::HttpsProtocol::install();
|
RequestServer::HttpsProtocol::install();
|
||||||
|
|
||||||
auto client = TRY(IPC::take_over_accepted_client_from_system_server<RequestServer::ConnectionFromClient>());
|
auto client = TRY(IPC::take_over_accepted_client_from_system_server<RequestServer::ConnectionFromClient>());
|
||||||
client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
|
|
||||||
|
|
||||||
return event_loop.exec();
|
return event_loop.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
static ErrorOr<void> load_content_filters();
|
static ErrorOr<void> load_content_filters();
|
||||||
static ErrorOr<void> load_autoplay_allowlist();
|
static ErrorOr<void> load_autoplay_allowlist();
|
||||||
static ErrorOr<void> initialize_lagom_networking(int request_server_socket, int request_server_fd_passing_socket);
|
static ErrorOr<void> initialize_lagom_networking(int request_server_socket);
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
extern bool g_log_all_js_exceptions;
|
extern bool g_log_all_js_exceptions;
|
||||||
|
@ -92,9 +92,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
StringView executable_path {};
|
StringView executable_path {};
|
||||||
StringView mach_server_name {};
|
StringView mach_server_name {};
|
||||||
Vector<ByteString> certificates;
|
Vector<ByteString> certificates;
|
||||||
int webcontent_fd_passing_socket { -1 };
|
|
||||||
int request_server_socket { -1 };
|
int request_server_socket { -1 };
|
||||||
int request_server_fd_passing_socket { -1 };
|
|
||||||
bool is_layout_test_mode = false;
|
bool is_layout_test_mode = false;
|
||||||
bool use_lagom_networking = false;
|
bool use_lagom_networking = false;
|
||||||
bool use_gpu_painting = false;
|
bool use_gpu_painting = false;
|
||||||
|
@ -105,9 +103,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_option(command_line, "Chrome process command line", "command-line", 0, "command_line");
|
args_parser.add_option(command_line, "Chrome process command line", "command-line", 0, "command_line");
|
||||||
args_parser.add_option(executable_path, "Chrome process executable path", "executable-path", 0, "executable_path");
|
args_parser.add_option(executable_path, "Chrome process executable path", "executable-path", 0, "executable_path");
|
||||||
args_parser.add_option(webcontent_fd_passing_socket, "File descriptor of the passing socket for the WebContent connection", "webcontent-fd-passing-socket", 'c', "webcontent_fd_passing_socket");
|
|
||||||
args_parser.add_option(request_server_socket, "File descriptor of the socket for the RequestServer connection", "request-server-socket", 'r', "request_server_socket");
|
args_parser.add_option(request_server_socket, "File descriptor of the socket for the RequestServer connection", "request-server-socket", 'r', "request_server_socket");
|
||||||
args_parser.add_option(request_server_fd_passing_socket, "File descriptor of the fd passing socket for the RequestServer connection", "request-server-fd-passing-socket", 'f', "request_server_fd_passing_socket");
|
|
||||||
args_parser.add_option(is_layout_test_mode, "Is layout test mode", "layout-test-mode", 0);
|
args_parser.add_option(is_layout_test_mode, "Is layout test mode", "layout-test-mode", 0);
|
||||||
args_parser.add_option(use_lagom_networking, "Enable Lagom servers for networking", "use-lagom-networking", 0);
|
args_parser.add_option(use_lagom_networking, "Enable Lagom servers for networking", "use-lagom-networking", 0);
|
||||||
args_parser.add_option(use_gpu_painting, "Enable GPU painting", "use-gpu-painting", 0);
|
args_parser.add_option(use_gpu_painting, "Enable GPU painting", "use-gpu-painting", 0);
|
||||||
|
@ -139,12 +135,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
Web::ResourceLoader::initialize(Ladybird::RequestManagerQt::create());
|
Web::ResourceLoader::initialize(Ladybird::RequestManagerQt::create());
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
TRY(initialize_lagom_networking(request_server_socket, request_server_fd_passing_socket));
|
TRY(initialize_lagom_networking(request_server_socket));
|
||||||
|
|
||||||
Web::HTML::Window::set_internals_object_exposed(is_layout_test_mode);
|
Web::HTML::Window::set_internals_object_exposed(is_layout_test_mode);
|
||||||
|
|
||||||
VERIFY(webcontent_fd_passing_socket >= 0);
|
|
||||||
|
|
||||||
Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(is_layout_test_mode));
|
Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(is_layout_test_mode));
|
||||||
|
|
||||||
TRY(Web::Bindings::initialize_main_thread_vm());
|
TRY(Web::Bindings::initialize_main_thread_vm());
|
||||||
|
@ -167,7 +161,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
auto webcontent_socket = TRY(Core::take_over_socket_from_system_server("WebContent"sv));
|
auto webcontent_socket = TRY(Core::take_over_socket_from_system_server("WebContent"sv));
|
||||||
auto webcontent_client = TRY(WebContent::ConnectionFromClient::try_create(move(webcontent_socket)));
|
auto webcontent_client = TRY(WebContent::ConnectionFromClient::try_create(move(webcontent_socket)));
|
||||||
webcontent_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(webcontent_fd_passing_socket)));
|
|
||||||
|
|
||||||
return event_loop.exec();
|
return event_loop.exec();
|
||||||
}
|
}
|
||||||
|
@ -220,13 +213,12 @@ static ErrorOr<void> load_autoplay_allowlist()
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> initialize_lagom_networking(int request_server_socket, int request_server_fd_passing_socket)
|
ErrorOr<void> initialize_lagom_networking(int request_server_socket)
|
||||||
{
|
{
|
||||||
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket));
|
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket));
|
||||||
TRY(socket->set_blocking(true));
|
TRY(socket->set_blocking(true));
|
||||||
|
|
||||||
auto new_client = TRY(try_make_ref_counted<Protocol::RequestClient>(move(socket)));
|
auto new_client = TRY(try_make_ref_counted<Protocol::RequestClient>(move(socket)));
|
||||||
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(request_server_fd_passing_socket)));
|
|
||||||
|
|
||||||
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(new_client))));
|
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(new_client))));
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -26,21 +26,17 @@
|
||||||
#include <LibWebView/WebSocketClientAdapter.h>
|
#include <LibWebView/WebSocketClientAdapter.h>
|
||||||
#include <WebWorker/ConnectionFromClient.h>
|
#include <WebWorker/ConnectionFromClient.h>
|
||||||
|
|
||||||
static ErrorOr<void> initialize_lagom_networking(int request_server_socket, int request_server_fd_passing_socket);
|
static ErrorOr<void> initialize_lagom_networking(int request_server_socket);
|
||||||
|
|
||||||
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
{
|
{
|
||||||
AK::set_rich_debug_enabled(true);
|
AK::set_rich_debug_enabled(true);
|
||||||
|
|
||||||
int fd_passing_socket { -1 };
|
|
||||||
int request_server_socket { -1 };
|
int request_server_socket { -1 };
|
||||||
int request_server_fd_passing_socket { -1 };
|
|
||||||
StringView serenity_resource_root;
|
StringView serenity_resource_root;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_option(fd_passing_socket, "File descriptor of the fd passing socket", "fd-passing-socket", 'c', "fd-passing-socket");
|
|
||||||
args_parser.add_option(request_server_socket, "File descriptor of the request server socket", "request-server-socket", 's', "request-server-socket");
|
args_parser.add_option(request_server_socket, "File descriptor of the request server socket", "request-server-socket", 's', "request-server-socket");
|
||||||
args_parser.add_option(request_server_fd_passing_socket, "File descriptor of the request server fd passing socket", "request-server-fd-passing-socket", 'f', "request-server-fd-passing-socket");
|
|
||||||
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(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root");
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
|
@ -51,25 +47,21 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
Web::Platform::FontPlugin::install(*new Web::Platform::FontPluginSerenity);
|
Web::Platform::FontPlugin::install(*new Web::Platform::FontPluginSerenity);
|
||||||
|
|
||||||
TRY(initialize_lagom_networking(request_server_socket, request_server_fd_passing_socket));
|
TRY(initialize_lagom_networking(request_server_socket));
|
||||||
|
|
||||||
VERIFY(fd_passing_socket >= 0);
|
|
||||||
|
|
||||||
TRY(Web::Bindings::initialize_main_thread_vm());
|
TRY(Web::Bindings::initialize_main_thread_vm());
|
||||||
|
|
||||||
auto client = TRY(IPC::take_over_accepted_client_from_system_server<WebWorker::ConnectionFromClient>());
|
auto client = TRY(IPC::take_over_accepted_client_from_system_server<WebWorker::ConnectionFromClient>());
|
||||||
client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
|
|
||||||
|
|
||||||
return event_loop.exec();
|
return event_loop.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErrorOr<void> initialize_lagom_networking(int request_server_socket, int request_server_fd_passing_socket)
|
static ErrorOr<void> initialize_lagom_networking(int request_server_socket)
|
||||||
{
|
{
|
||||||
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket));
|
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket));
|
||||||
TRY(socket->set_blocking(true));
|
TRY(socket->set_blocking(true));
|
||||||
|
|
||||||
auto new_client = TRY(try_make_ref_counted<Protocol::RequestClient>(move(socket)));
|
auto new_client = TRY(try_make_ref_counted<Protocol::RequestClient>(move(socket)));
|
||||||
new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(request_server_fd_passing_socket)));
|
|
||||||
|
|
||||||
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(new_client))));
|
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(new_client))));
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,6 @@ shared_library("LibWebView") {
|
||||||
"ProcessManager.cpp",
|
"ProcessManager.cpp",
|
||||||
"RequestServerAdapter.cpp",
|
"RequestServerAdapter.cpp",
|
||||||
"SearchEngine.cpp",
|
"SearchEngine.cpp",
|
||||||
"SocketPair.cpp",
|
|
||||||
"SourceHighlighter.cpp",
|
"SourceHighlighter.cpp",
|
||||||
"URL.cpp",
|
"URL.cpp",
|
||||||
"UserAgent.cpp",
|
"UserAgent.cpp",
|
||||||
|
|
|
@ -40,7 +40,6 @@ class ConnectionBase : public Core::EventReceiver {
|
||||||
public:
|
public:
|
||||||
virtual ~ConnectionBase() override = default;
|
virtual ~ConnectionBase() override = default;
|
||||||
|
|
||||||
void set_fd_passing_socket(NonnullOwnPtr<Core::LocalSocket>) { }
|
|
||||||
void set_deferred_invoker(NonnullOwnPtr<DeferredInvoker>);
|
void set_deferred_invoker(NonnullOwnPtr<DeferredInvoker>);
|
||||||
DeferredInvoker& deferred_invoker() { return *m_deferred_invoker; }
|
DeferredInvoker& deferred_invoker() { return *m_deferred_invoker; }
|
||||||
|
|
||||||
|
@ -51,7 +50,6 @@ public:
|
||||||
virtual void die() { }
|
virtual void die() { }
|
||||||
|
|
||||||
Core::LocalSocket& socket() { return *m_socket; }
|
Core::LocalSocket& socket() { return *m_socket; }
|
||||||
Core::LocalSocket const& fd_passing_socket() const { return *m_socket; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::LocalSocket>, u32 local_endpoint_magic);
|
explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::LocalSocket>, u32 local_endpoint_magic);
|
||||||
|
|
|
@ -83,11 +83,6 @@ WebIDL::ExceptionOr<void> MessagePort::transfer_steps(HTML::TransferDataHolder&
|
||||||
m_socket = nullptr;
|
m_socket = nullptr;
|
||||||
data_holder.fds.append(IPC::File::adopt_fd(fd));
|
data_holder.fds.append(IPC::File::adopt_fd(fd));
|
||||||
data_holder.data.append(IPC_FILE_TAG);
|
data_holder.data.append(IPC_FILE_TAG);
|
||||||
|
|
||||||
auto fd_passing_socket = MUST(m_fd_passing_socket->release_fd());
|
|
||||||
m_fd_passing_socket = nullptr;
|
|
||||||
data_holder.fds.append(IPC::File::adopt_fd(fd_passing_socket));
|
|
||||||
data_holder.data.append(IPC_FILE_TAG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Otherwise, set dataHolder.[[RemotePort]] to null.
|
// 4. Otherwise, set dataHolder.[[RemotePort]] to null.
|
||||||
|
@ -114,11 +109,6 @@ WebIDL::ExceptionOr<void> MessagePort::transfer_receiving_steps(HTML::TransferDa
|
||||||
auto fd = data_holder.fds.take_first();
|
auto fd = data_holder.fds.take_first();
|
||||||
m_socket = MUST(Core::LocalSocket::adopt_fd(fd.take_fd()));
|
m_socket = MUST(Core::LocalSocket::adopt_fd(fd.take_fd()));
|
||||||
|
|
||||||
fd_tag = data_holder.data.take_first();
|
|
||||||
VERIFY(fd_tag == IPC_FILE_TAG);
|
|
||||||
fd = data_holder.fds.take_first();
|
|
||||||
m_fd_passing_socket = MUST(Core::LocalSocket::adopt_fd(fd.take_fd()));
|
|
||||||
|
|
||||||
m_socket->on_ready_to_read = [strong_this = JS::make_handle(this)]() {
|
m_socket->on_ready_to_read = [strong_this = JS::make_handle(this)]() {
|
||||||
strong_this->read_from_socket();
|
strong_this->read_from_socket();
|
||||||
};
|
};
|
||||||
|
@ -137,7 +127,6 @@ void MessagePort::disentangle()
|
||||||
m_remote_port = nullptr;
|
m_remote_port = nullptr;
|
||||||
|
|
||||||
m_socket = nullptr;
|
m_socket = nullptr;
|
||||||
m_fd_passing_socket = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
|
||||||
|
@ -181,10 +170,6 @@ void MessagePort::entangle_with(MessagePort& remote_port)
|
||||||
m_remote_port->m_socket->on_ready_to_read = [remote_port = JS::make_handle(m_remote_port)]() {
|
m_remote_port->m_socket->on_ready_to_read = [remote_port = JS::make_handle(m_remote_port)]() {
|
||||||
remote_port->read_from_socket();
|
remote_port->read_from_socket();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto fd_sockets = create_paired_sockets();
|
|
||||||
m_fd_passing_socket = move(fd_sockets[0]);
|
|
||||||
m_remote_port->m_fd_passing_socket = move(fd_sockets[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage-options
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage-options
|
||||||
|
@ -408,7 +393,6 @@ void MessagePort::start()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VERIFY(m_socket);
|
VERIFY(m_socket);
|
||||||
VERIFY(m_fd_passing_socket);
|
|
||||||
|
|
||||||
// TODO: The start() method steps are to enable this's port message queue, if it is not already enabled.
|
// TODO: The start() method steps are to enable this's port message queue, if it is not already enabled.
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@ private:
|
||||||
bool m_has_been_shipped { false };
|
bool m_has_been_shipped { false };
|
||||||
|
|
||||||
OwnPtr<Core::LocalSocket> m_socket;
|
OwnPtr<Core::LocalSocket> m_socket;
|
||||||
OwnPtr<Core::LocalSocket> m_fd_passing_socket;
|
|
||||||
|
|
||||||
enum class SocketState : u8 {
|
enum class SocketState : u8 {
|
||||||
Header,
|
Header,
|
||||||
|
|
|
@ -33,14 +33,11 @@ void WorkerAgent::initialize(JS::Realm& realm)
|
||||||
|
|
||||||
// NOTE: This blocking IPC call may launch another process.
|
// 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.
|
// If spinning the event loop for this can cause other javascript to execute, we're in trouble.
|
||||||
auto worker_ipc_sockets = Bindings::host_defined_page(realm).client().request_worker_agent();
|
auto worker_socket_file = Bindings::host_defined_page(realm).client().request_worker_agent();
|
||||||
auto worker_socket = MUST(Core::LocalSocket::adopt_fd(worker_ipc_sockets.socket.take_fd()));
|
auto worker_socket = MUST(Core::LocalSocket::adopt_fd(worker_socket_file.take_fd()));
|
||||||
MUST(worker_socket->set_blocking(true));
|
MUST(worker_socket->set_blocking(true));
|
||||||
|
|
||||||
auto fd_passing_socket = MUST(Core::LocalSocket::adopt_fd(worker_ipc_sockets.fd_passing_socket.take_fd()));
|
|
||||||
|
|
||||||
m_worker_ipc = make_ref_counted<WebWorkerClient>(move(worker_socket));
|
m_worker_ipc = make_ref_counted<WebWorkerClient>(move(worker_socket));
|
||||||
m_worker_ipc->set_fd_passing_socket(move(fd_passing_socket));
|
|
||||||
|
|
||||||
m_worker_ipc->async_start_dedicated_worker(m_url, m_worker_options.type, m_worker_options.credentials, m_worker_options.name, move(data_holder), m_outside_settings->serialize());
|
m_worker_ipc->async_start_dedicated_worker(m_url, m_worker_options.type, m_worker_options.credentials, m_worker_options.name, move(data_holder), m_outside_settings->serialize());
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include <LibWeb/HTML/WebViewHints.h>
|
#include <LibWeb/HTML/WebViewHints.h>
|
||||||
#include <LibWeb/Loader/FileRequest.h>
|
#include <LibWeb/Loader/FileRequest.h>
|
||||||
#include <LibWeb/PixelUnits.h>
|
#include <LibWeb/PixelUnits.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
|
|
||||||
namespace Web {
|
namespace Web {
|
||||||
|
|
||||||
|
@ -315,7 +314,7 @@ public:
|
||||||
|
|
||||||
virtual void page_did_change_audio_play_state(HTML::AudioPlayState) { }
|
virtual void page_did_change_audio_play_state(HTML::AudioPlayState) { }
|
||||||
|
|
||||||
virtual WebView::SocketPair request_worker_agent() { return { IPC::File {}, IPC::File {} }; }
|
virtual IPC::File request_worker_agent() { return IPC::File {}; }
|
||||||
|
|
||||||
virtual void inspector_did_load() { }
|
virtual void inspector_did_load() { }
|
||||||
virtual void inspector_did_select_dom_node([[maybe_unused]] i32 node_id, [[maybe_unused]] Optional<CSS::Selector::PseudoElement::Type> const& pseudo_element) { }
|
virtual void inspector_did_select_dom_node([[maybe_unused]] i32 node_id, [[maybe_unused]] Optional<CSS::Selector::PseudoElement::Type> const& pseudo_element) { }
|
||||||
|
|
|
@ -19,12 +19,9 @@ WebWorkerClient::WebWorkerClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
WebView::SocketPair WebWorkerClient::dup_sockets()
|
IPC::File WebWorkerClient::dup_socket()
|
||||||
{
|
{
|
||||||
WebView::SocketPair pair;
|
return MUST(IPC::File::clone_fd(socket().fd().value()));
|
||||||
pair.socket = MUST(IPC::File::clone_fd(socket().fd().value()));
|
|
||||||
pair.fd_passing_socket = MUST(IPC::File::clone_fd(fd_passing_socket().fd().value()));
|
|
||||||
return pair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <LibIPC/ConnectionToServer.h>
|
#include <LibIPC/ConnectionToServer.h>
|
||||||
#include <LibWeb/Worker/WebWorkerClientEndpoint.h>
|
#include <LibWeb/Worker/WebWorkerClientEndpoint.h>
|
||||||
#include <LibWeb/Worker/WebWorkerServerEndpoint.h>
|
#include <LibWeb/Worker/WebWorkerServerEndpoint.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ class WebWorkerClient final
|
||||||
public:
|
public:
|
||||||
explicit WebWorkerClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit WebWorkerClient(NonnullOwnPtr<Core::LocalSocket>);
|
||||||
|
|
||||||
WebView::SocketPair dup_sockets();
|
IPC::File dup_socket();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void die() override;
|
virtual void die() override;
|
||||||
|
|
|
@ -9,7 +9,6 @@ set(SOURCES
|
||||||
ProcessManager.cpp
|
ProcessManager.cpp
|
||||||
RequestServerAdapter.cpp
|
RequestServerAdapter.cpp
|
||||||
SearchEngine.cpp
|
SearchEngine.cpp
|
||||||
SocketPair.cpp
|
|
||||||
SourceHighlighter.cpp
|
SourceHighlighter.cpp
|
||||||
URL.cpp
|
URL.cpp
|
||||||
UserAgent.cpp
|
UserAgent.cpp
|
||||||
|
|
|
@ -22,7 +22,6 @@ struct Attribute;
|
||||||
struct CookieStorageKey;
|
struct CookieStorageKey;
|
||||||
struct ProcessHandle;
|
struct ProcessHandle;
|
||||||
struct SearchEngine;
|
struct SearchEngine;
|
||||||
struct SocketPair;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ OutOfProcessWebView::OutOfProcessWebView()
|
||||||
|
|
||||||
on_request_worker_agent = []() {
|
on_request_worker_agent = []() {
|
||||||
auto worker_client = MUST(Web::HTML::WebWorkerClient::try_create());
|
auto worker_client = MUST(Web::HTML::WebWorkerClient::try_create());
|
||||||
return worker_client->dup_sockets();
|
return worker_client->dup_socket();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <LibIPC/Decoder.h>
|
|
||||||
#include <LibIPC/Encoder.h>
|
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
|
|
||||||
template<>
|
|
||||||
ErrorOr<void> IPC::encode(Encoder& encoder, WebView::SocketPair const& pair)
|
|
||||||
{
|
|
||||||
TRY(encoder.encode(pair.socket));
|
|
||||||
TRY(encoder.encode(pair.fd_passing_socket));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
ErrorOr<WebView::SocketPair> IPC::decode(Decoder& decoder)
|
|
||||||
{
|
|
||||||
auto socket = TRY(decoder.decode<IPC::File>());
|
|
||||||
auto fd_passing_socket = TRY(decoder.decode<IPC::File>());
|
|
||||||
|
|
||||||
return WebView::SocketPair { move(socket), move(fd_passing_socket) };
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <LibIPC/File.h>
|
|
||||||
|
|
||||||
namespace WebView {
|
|
||||||
|
|
||||||
struct SocketPair {
|
|
||||||
IPC::File socket;
|
|
||||||
IPC::File fd_passing_socket;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace IPC {
|
|
||||||
|
|
||||||
template<>
|
|
||||||
ErrorOr<void> encode(Encoder&, WebView::SocketPair const&);
|
|
||||||
|
|
||||||
template<>
|
|
||||||
ErrorOr<WebView::SocketPair> decode(Decoder&);
|
|
||||||
|
|
||||||
}
|
|
|
@ -200,7 +200,7 @@ public:
|
||||||
Function<void(i32, size_t, Vector<Attribute> const&)> on_inspector_replaced_dom_node_attribute;
|
Function<void(i32, size_t, Vector<Attribute> const&)> on_inspector_replaced_dom_node_attribute;
|
||||||
Function<void(i32, Gfx::IntPoint, String const&, Optional<String> const&, Optional<size_t> const&)> on_inspector_requested_dom_tree_context_menu;
|
Function<void(i32, Gfx::IntPoint, String const&, Optional<String> const&, Optional<size_t> const&)> on_inspector_requested_dom_tree_context_menu;
|
||||||
Function<void(String const&)> on_inspector_executed_console_script;
|
Function<void(String const&)> on_inspector_executed_console_script;
|
||||||
Function<SocketPair()> on_request_worker_agent;
|
Function<IPC::File()> on_request_worker_agent;
|
||||||
|
|
||||||
virtual Web::DevicePixelRect viewport_rect() const = 0;
|
virtual Web::DevicePixelRect viewport_rect() const = 0;
|
||||||
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
|
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0;
|
||||||
|
|
|
@ -665,7 +665,7 @@ Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request
|
||||||
return view->on_request_worker_agent();
|
return view->on_request_worker_agent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return WebView::SocketPair { IPC::File {}, IPC::File {} };
|
return IPC::File {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<ViewImplementation&> WebContentClient::view_for_page_id(u64 page_id, SourceLocation location)
|
Optional<ViewImplementation&> WebContentClient::view_for_page_id(u64 page_id, SourceLocation location)
|
||||||
|
|
|
@ -42,12 +42,10 @@ void ConnectionFromClient::die()
|
||||||
|
|
||||||
Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_new_client()
|
Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_new_client()
|
||||||
{
|
{
|
||||||
Messages::RequestServer::ConnectNewClientResponse error_response = { IPC::File {}, IPC::File {} };
|
|
||||||
|
|
||||||
int socket_fds[2] {};
|
int socket_fds[2] {};
|
||||||
if (auto err = Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds); err.is_error()) {
|
if (auto err = Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds); err.is_error()) {
|
||||||
dbgln("Failed to create client socketpair: {}", err.error());
|
dbgln("Failed to create client socketpair: {}", err.error());
|
||||||
return error_response;
|
return IPC::File {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto client_socket_or_error = Core::LocalSocket::adopt_fd(socket_fds[0]);
|
auto client_socket_or_error = Core::LocalSocket::adopt_fd(socket_fds[0]);
|
||||||
|
@ -55,32 +53,13 @@ Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_
|
||||||
close(socket_fds[0]);
|
close(socket_fds[0]);
|
||||||
close(socket_fds[1]);
|
close(socket_fds[1]);
|
||||||
dbgln("Failed to adopt client socket: {}", client_socket_or_error.error());
|
dbgln("Failed to adopt client socket: {}", client_socket_or_error.error());
|
||||||
return error_response;
|
return IPC::File {};
|
||||||
}
|
}
|
||||||
auto client_socket = client_socket_or_error.release_value();
|
auto client_socket = client_socket_or_error.release_value();
|
||||||
// Note: A ref is stored in the static s_connections map
|
// Note: A ref is stored in the static s_connections map
|
||||||
auto client = adopt_ref(*new ConnectionFromClient(move(client_socket)));
|
auto client = adopt_ref(*new ConnectionFromClient(move(client_socket)));
|
||||||
|
|
||||||
int fd_passing_socket_fds[2] {};
|
return IPC::File::adopt_fd(socket_fds[1]);
|
||||||
if (auto err = Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds); err.is_error()) {
|
|
||||||
close(socket_fds[1]);
|
|
||||||
dbgln("Failed to create fd-passing socketpair: {}", err.error());
|
|
||||||
return error_response;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fd_passing_socket_or_error = Core::LocalSocket::adopt_fd(fd_passing_socket_fds[0]);
|
|
||||||
if (fd_passing_socket_or_error.is_error()) {
|
|
||||||
// socket_fds[0] is already owned by client
|
|
||||||
close(socket_fds[1]);
|
|
||||||
close(fd_passing_socket_fds[0]);
|
|
||||||
close(fd_passing_socket_fds[1]);
|
|
||||||
dbgln("Failed to adopt fd-passing socket: {}", fd_passing_socket_or_error.error());
|
|
||||||
return error_response;
|
|
||||||
}
|
|
||||||
auto fd_passing_socket = fd_passing_socket_or_error.release_value();
|
|
||||||
client->set_fd_passing_socket(move(fd_passing_socket));
|
|
||||||
|
|
||||||
return { IPC::File::adopt_fd(socket_fds[1]), IPC::File::adopt_fd(fd_passing_socket_fds[1]) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_supported_protocol(ByteString const& protocol)
|
Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_supported_protocol(ByteString const& protocol)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
endpoint RequestServer
|
endpoint RequestServer
|
||||||
{
|
{
|
||||||
connect_new_client() => (IPC::File client_socket, IPC::File client_fd_passing_socket)
|
connect_new_client() => (IPC::File client_socket)
|
||||||
|
|
||||||
// Test if a specific protocol is supported, e.g "http"
|
// Test if a specific protocol is supported, e.g "http"
|
||||||
is_supported_protocol(ByteString protocol) => (bool supported)
|
is_supported_protocol(ByteString protocol) => (bool supported)
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include <LibWeb/Painting/ViewportPaintable.h>
|
#include <LibWeb/Painting/ViewportPaintable.h>
|
||||||
#include <LibWeb/Platform/Timer.h>
|
#include <LibWeb/Platform/Timer.h>
|
||||||
#include <LibWebView/Attribute.h>
|
#include <LibWebView/Attribute.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
#include <WebContent/ConnectionFromClient.h>
|
#include <WebContent/ConnectionFromClient.h>
|
||||||
#include <WebContent/PageClient.h>
|
#include <WebContent/PageClient.h>
|
||||||
#include <WebContent/PageHost.h>
|
#include <WebContent/PageHost.h>
|
||||||
|
@ -601,7 +600,7 @@ void PageClient::page_did_change_audio_play_state(Web::HTML::AudioPlayState play
|
||||||
client().async_did_change_audio_play_state(m_id, play_state);
|
client().async_did_change_audio_play_state(m_id, play_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebView::SocketPair PageClient::request_worker_agent()
|
IPC::File PageClient::request_worker_agent()
|
||||||
{
|
{
|
||||||
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);
|
||||||
if (!response) {
|
if (!response) {
|
||||||
|
@ -609,7 +608,7 @@ WebView::SocketPair PageClient::request_worker_agent()
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response->take_sockets();
|
return response->take_socket();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageClient::inspector_did_load()
|
void PageClient::inspector_did_load()
|
||||||
|
|
|
@ -146,7 +146,7 @@ private:
|
||||||
virtual void page_did_change_theme_color(Gfx::Color color) override;
|
virtual void page_did_change_theme_color(Gfx::Color color) override;
|
||||||
virtual void page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type) override;
|
virtual void page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type) override;
|
||||||
virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override;
|
virtual void page_did_change_audio_play_state(Web::HTML::AudioPlayState) override;
|
||||||
virtual WebView::SocketPair request_worker_agent() override;
|
virtual IPC::File request_worker_agent() override;
|
||||||
virtual void inspector_did_load() override;
|
virtual void inspector_did_load() override;
|
||||||
virtual void inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
|
virtual void inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
|
||||||
virtual void inspector_did_set_dom_node_text(i32 node_id, String const& text) override;
|
virtual void inspector_did_set_dom_node_text(i32 node_id, String const& text) override;
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include <LibWeb/HTML/WebViewHints.h>
|
#include <LibWeb/HTML/WebViewHints.h>
|
||||||
#include <LibWeb/Page/Page.h>
|
#include <LibWeb/Page/Page.h>
|
||||||
#include <LibWebView/Attribute.h>
|
#include <LibWebView/Attribute.h>
|
||||||
#include <LibWebView/SocketPair.h>
|
|
||||||
#include <LibWebView/ProcessHandle.h>
|
#include <LibWebView/ProcessHandle.h>
|
||||||
|
|
||||||
endpoint WebContentClient
|
endpoint WebContentClient
|
||||||
|
@ -91,7 +90,7 @@ endpoint WebContentClient
|
||||||
|
|
||||||
did_finish_text_test(u64 page_id) =|
|
did_finish_text_test(u64 page_id) =|
|
||||||
|
|
||||||
request_worker_agent(u64 page_id) => (WebView::SocketPair sockets) // FIXME: Add required attributes to select a SharedWorker Agent
|
request_worker_agent(u64 page_id) => (IPC::File socket) // FIXME: Add required attributes to select a SharedWorker Agent
|
||||||
|
|
||||||
inspector_did_load(u64 page_id) =|
|
inspector_did_load(u64 page_id) =|
|
||||||
inspector_did_select_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
|
inspector_did_select_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
|
||||||
|
|
|
@ -96,10 +96,10 @@ public:
|
||||||
.is_layout_test_mode = is_layout_test_mode,
|
.is_layout_test_mode = is_layout_test_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto request_server_sockets = TRY(connect_new_request_server_client(*request_client));
|
auto request_server_socket = TRY(connect_new_request_server_client(*request_client));
|
||||||
|
|
||||||
auto candidate_web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
|
auto candidate_web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
|
||||||
view->m_client_state.client = TRY(launch_web_content_process(*view, candidate_web_content_paths, web_content_options, move(request_server_sockets)));
|
view->m_client_state.client = TRY(launch_web_content_process(*view, candidate_web_content_paths, web_content_options, move(request_server_socket)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
view->client().async_update_system_theme(0, move(theme));
|
view->client().async_update_system_theme(0, move(theme));
|
||||||
|
@ -196,7 +196,7 @@ private:
|
||||||
#else
|
#else
|
||||||
auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), *m_request_client));
|
auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), *m_request_client));
|
||||||
#endif
|
#endif
|
||||||
return worker_client->dup_sockets();
|
return worker_client->dup_socket();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue