LibIPC+LibWeb+LibWebView+Services: Add IPC::TransportHandle

Add IPC::TransportHandle as an abstraction for passing IPC
transports through .ipc messages. This replaces IPC::File at
all sites where a transport (not a generic file) is being
transferred between processes.

TransportHandle provides from_transport(),
clone_from_transport(), and create_transport() methods that
encapsulate the fd-to-socket-to-transport conversion in one
place. This is preparatory work for Mach port support on
macOS -- when that lands, only TransportHandle's internals
need to change while all .ipc definitions and call sites
remain untouched.
This commit is contained in:
Aliaksandr Kalenik 2026-03-11 20:10:08 +01:00 committed by Alexander Kalenik
parent d1f98d596d
commit 3bea3908b2
33 changed files with 263 additions and 136 deletions

View file

@ -3,6 +3,7 @@ set(SOURCES
Connection.cpp
Decoder.cpp
Encoder.cpp
TransportHandle.cpp
)
if (UNIX)

View file

@ -123,6 +123,9 @@ ErrorOr<URL::Host> decode(Decoder&);
template<>
ErrorOr<File> decode(Decoder&);
template<>
ErrorOr<TransportHandle> decode(Decoder&);
template<>
ErrorOr<Empty> decode(Decoder&);

View file

@ -127,6 +127,9 @@ ErrorOr<void> encode(Encoder&, URL::Host const&);
template<>
ErrorOr<void> encode(Encoder&, File const&);
template<>
ErrorOr<void> encode(Encoder&, TransportHandle const&);
template<>
ErrorOr<void> encode(Encoder&, Empty const&);

View file

@ -17,6 +17,7 @@ class Message;
class MessageBuffer;
class File;
class Stub;
class TransportHandle;
template<typename T>
ErrorOr<void> encode(Encoder&, T const&);

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/Socket.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibIPC/File.h>
#include <LibIPC/Transport.h>
#include <LibIPC/TransportHandle.h>
namespace IPC {
TransportHandle::TransportHandle(File file)
: m_file(move(file))
{
}
ErrorOr<TransportHandle> TransportHandle::from_transport(Transport& transport)
{
auto fd = TRY(transport.release_underlying_transport_for_transfer());
return TransportHandle { File::adopt_fd(fd) };
}
ErrorOr<TransportHandle> TransportHandle::clone_from_transport(Transport& transport)
{
auto file = TRY(transport.clone_for_transfer());
return TransportHandle { move(file) };
}
ErrorOr<NonnullOwnPtr<Transport>> TransportHandle::create_transport() const
{
auto socket = TRY(Core::LocalSocket::adopt_fd(m_file.take_fd()));
TRY(socket->set_blocking(true));
return make<Transport>(move(socket));
}
int TransportHandle::fd() const
{
return m_file.fd();
}
ErrorOr<void> TransportHandle::clear_close_on_exec()
{
return m_file.clear_close_on_exec();
}
template<>
ErrorOr<void> encode(Encoder& encoder, TransportHandle const& handle)
{
return encoder.encode(handle.m_file);
}
template<>
ErrorOr<TransportHandle> decode(Decoder& decoder)
{
auto file = TRY(decoder.decode<File>());
return TransportHandle { move(file) };
}
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/Noncopyable.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/Platform.h>
#include <LibIPC/File.h>
#include <LibIPC/Forward.h>
namespace IPC {
#if !defined(AK_OS_WINDOWS)
class TransportSocket;
using Transport = TransportSocket;
#else
class TransportSocketWindows;
using Transport = TransportSocketWindows;
#endif
class TransportHandle {
AK_MAKE_NONCOPYABLE(TransportHandle);
public:
TransportHandle() = default;
TransportHandle(TransportHandle&&) = default;
TransportHandle& operator=(TransportHandle&&) = default;
static ErrorOr<TransportHandle> from_transport(Transport& transport);
static ErrorOr<TransportHandle> clone_from_transport(Transport& transport);
ErrorOr<NonnullOwnPtr<Transport>> create_transport() const;
int fd() const;
ErrorOr<void> clear_close_on_exec();
private:
explicit TransportHandle(File);
template<typename U>
friend ErrorOr<void> encode(Encoder&, U const&);
template<typename U>
friend ErrorOr<U> decode(Decoder&);
mutable File m_file;
};
}

View file

@ -49,14 +49,9 @@ 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(m_agent_type);
auto worker_socket = MUST(Core::LocalSocket::adopt_fd(worker_socket_file.take_fd()));
MUST(worker_socket->set_blocking(true));
// TODO: Mach IPC
auto transport = make<IPC::Transport>(move(worker_socket));
auto handle = Bindings::principal_host_defined_page(realm).client().request_worker_agent(m_agent_type);
auto transport = MUST(handle.create_transport());
m_worker_ipc = make_ref_counted<WebWorkerClient>(move(transport));
setup_worker_ipc_callbacks(realm);

View file

@ -23,6 +23,7 @@
#include <LibHTTP/Forward.h>
#include <LibHTTP/Header.h>
#include <LibIPC/Forward.h>
#include <LibIPC/TransportHandle.h>
#include <LibRequests/NetworkError.h>
#include <LibRequests/RequestTimingInfo.h>
#include <LibURL/URL.h>
@ -439,7 +440,7 @@ public:
virtual void page_did_receive_network_response_body([[maybe_unused]] u64 request_id, [[maybe_unused]] ReadonlyBytes data) { }
virtual void page_did_finish_network_request([[maybe_unused]] u64 request_id, [[maybe_unused]] u64 body_size, [[maybe_unused]] Requests::RequestTimingInfo const& timing_info, [[maybe_unused]] Optional<Requests::NetworkError> const& network_error) { }
virtual IPC::File request_worker_agent([[maybe_unused]] Web::Bindings::AgentType worker_type) { return IPC::File {}; }
virtual IPC::TransportHandle request_worker_agent([[maybe_unused]] Web::Bindings::AgentType worker_type) { return IPC::TransportHandle {}; }
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

@ -37,7 +37,7 @@ Messages::WebWorkerClient::RequestWorkerAgentResponse WebWorkerClient::request_w
{
if (on_request_worker_agent)
return on_request_worker_agent(worker_type);
return IPC::File {};
return IPC::TransportHandle {};
}
WebWorkerClient::WebWorkerClient(NonnullOwnPtr<IPC::Transport> transport)
@ -45,9 +45,9 @@ WebWorkerClient::WebWorkerClient(NonnullOwnPtr<IPC::Transport> transport)
{
}
IPC::File WebWorkerClient::clone_transport()
IPC::TransportHandle WebWorkerClient::clone_transport()
{
return MUST(m_transport->clone_for_transfer());
return MUST(IPC::TransportHandle::clone_from_transport(*m_transport));
}
}

View file

@ -8,6 +8,7 @@
#include <LibHTTP/Cookie/Cookie.h>
#include <LibIPC/ConnectionToServer.h>
#include <LibIPC/TransportHandle.h>
#include <LibWeb/Export.h>
#include <LibWeb/Worker/WebWorkerClientEndpoint.h>
#include <LibWeb/Worker/WebWorkerServerEndpoint.h>
@ -30,9 +31,9 @@ public:
Function<void()> on_worker_close;
Function<void()> on_worker_script_load_failure;
Function<HTTP::Cookie::VersionedCookie(URL::URL const&, HTTP::Cookie::Source)> on_request_cookie;
Function<IPC::File(Web::Bindings::AgentType)> on_request_worker_agent;
Function<IPC::TransportHandle(Web::Bindings::AgentType)> on_request_worker_agent;
IPC::File clone_transport();
IPC::TransportHandle clone_transport();
private:
virtual void die() override;

View file

@ -1,4 +1,5 @@
#include <LibHTTP/Cookie/Cookie.h>
#include <LibIPC/TransportHandle.h>
#include <LibURL/URL.h>
#include <LibWeb/Bindings/AgentType.h>
@ -6,5 +7,5 @@ endpoint WebWorkerClient {
did_close_worker() =|
did_fail_loading_worker_script() =|
did_request_cookie(URL::URL url, HTTP::Cookie::Source source) => (HTTP::Cookie::VersionedCookie cookie)
request_worker_agent(Web::Bindings::AgentType worker_type) => (IPC::File socket)
request_worker_agent(Web::Bindings::AgentType worker_type) => (IPC::TransportHandle handle)
}

View file

@ -326,12 +326,12 @@ void Application::open_url_in_new_tab(URL::URL const& url, Web::HTML::ActivateTa
static ErrorOr<NonnullRefPtr<WebContentClient>> create_web_content_client(Optional<ViewImplementation&> view)
{
auto request_server_socket = TRY(connect_new_request_server_client());
auto image_decoder_socket = TRY(connect_new_image_decoder_client());
auto request_server_handle = TRY(connect_new_request_server_client());
auto image_decoder_handle = TRY(connect_new_image_decoder_client());
if (view.has_value())
return WebView::launch_web_content_process(*view, move(image_decoder_socket), move(request_server_socket));
return WebView::launch_spare_web_content_process(move(image_decoder_socket), move(request_server_socket));
return WebView::launch_web_content_process(*view, move(image_decoder_handle), move(request_server_handle));
return WebView::launch_spare_web_content_process(move(image_decoder_handle), move(request_server_handle));
}
ErrorOr<NonnullRefPtr<WebContentClient>> Application::launch_web_content_process(ViewImplementation& view)
@ -443,14 +443,14 @@ ErrorOr<void> Application::launch_request_server()
}
auto client_count = WebContentClient::client_count();
auto request_server_sockets = m_request_server_client->send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClients>(client_count);
if (!request_server_sockets || request_server_sockets->sockets().is_empty()) {
auto request_server_response = m_request_server_client->send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClients>(client_count);
if (!request_server_response || request_server_response->handles().is_empty()) {
warnln("\033Failed to connect {} new clients to ImageDecoder\033[0m", client_count);
VERIFY_NOT_REACHED();
}
WebContentClient::for_each_client([sockets = request_server_sockets->take_sockets()](WebContentClient& client) mutable {
client.async_connect_to_request_server(sockets.take_last());
WebContentClient::for_each_client([handles = request_server_response->take_handles()](WebContentClient& client) mutable {
client.async_connect_to_request_server(handles.take_last());
return IterationDecision::Continue;
});
};
@ -477,14 +477,14 @@ ErrorOr<void> Application::launch_image_decoder_server()
}
auto client_count = WebContentClient::client_count();
auto new_sockets = m_image_decoder_client->send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(client_count);
if (!new_sockets || new_sockets->sockets().is_empty()) {
auto image_decoder_response = m_image_decoder_client->send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(client_count);
if (!image_decoder_response || image_decoder_response->handles().is_empty()) {
dbgln("Failed to connect {} new clients to ImageDecoder", client_count);
VERIFY_NOT_REACHED();
}
WebContentClient::for_each_client([sockets = new_sockets->take_sockets()](WebContentClient& client) mutable {
client.async_connect_to_image_decoder(sockets.take_last());
WebContentClient::for_each_client([handles = image_decoder_response->take_handles()](WebContentClient& client) mutable {
client.async_connect_to_image_decoder(handles.take_last());
return IterationDecision::Continue;
});
};

View file

@ -83,8 +83,8 @@ static ErrorOr<NonnullRefPtr<ClientType>> launch_server_process(
template<typename... ClientArguments>
static ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process_impl(
IPC::File image_decoder_socket,
Optional<IPC::File> request_server_socket,
IPC::TransportHandle image_decoder_handle,
Optional<IPC::TransportHandle> request_server_handle,
ClientArguments&&... client_arguments)
{
auto const& browser_options = WebView::Application::browser_options();
@ -145,30 +145,30 @@ static ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_proc
arguments.append("--mach-server-name"sv);
arguments.append(server.value());
}
if (request_server_socket.has_value()) {
if (request_server_handle.has_value()) {
arguments.append("--request-server-socket"sv);
arguments.append(ByteString::number(request_server_socket->fd()));
arguments.append(ByteString::number(request_server_handle->fd()));
}
arguments.append("--image-decoder-socket"sv);
arguments.append(ByteString::number(image_decoder_socket.fd()));
arguments.append(ByteString::number(image_decoder_handle.fd()));
return launch_server_process<WebView::WebContentClient>("WebContent"sv, move(arguments), forward<ClientArguments>(client_arguments)...);
}
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
WebView::ViewImplementation& view,
IPC::File image_decoder_socket,
Optional<IPC::File> request_server_socket)
IPC::TransportHandle image_decoder_handle,
Optional<IPC::TransportHandle> request_server_handle)
{
return launch_web_content_process_impl(move(image_decoder_socket), move(request_server_socket), view);
return launch_web_content_process_impl(move(image_decoder_handle), move(request_server_handle), view);
}
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_spare_web_content_process(
IPC::File image_decoder_socket,
Optional<IPC::File> request_server_socket)
IPC::TransportHandle image_decoder_handle,
Optional<IPC::TransportHandle> request_server_handle)
{
return launch_web_content_process_impl(move(image_decoder_socket), move(request_server_socket));
return launch_web_content_process_impl(move(image_decoder_handle), move(request_server_handle));
}
ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process()
@ -193,13 +193,13 @@ ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(Web
if (web_content_options.enable_http_memory_cache == WebView::EnableMemoryHTTPCache::Yes)
arguments.append("--enable-http-memory-cache"sv);
auto request_server_socket = TRY(connect_new_request_server_client());
auto request_server_handle = TRY(connect_new_request_server_client());
arguments.append("--request-server-socket"sv);
arguments.append(ByteString::number(request_server_socket.fd()));
arguments.append(ByteString::number(request_server_handle.fd()));
auto image_decoder_socket = TRY(connect_new_image_decoder_client());
auto image_decoder_handle = TRY(connect_new_image_decoder_client());
arguments.append("--image-decoder-socket"sv);
arguments.append(ByteString::number(image_decoder_socket.fd()));
arguments.append(ByteString::number(image_decoder_handle.fd()));
arguments.append("--type"sv);
switch (type) {
@ -276,32 +276,32 @@ ErrorOr<NonnullRefPtr<Requests::RequestClient>> launch_request_server_process()
return client;
}
ErrorOr<IPC::File> connect_new_request_server_client()
ErrorOr<IPC::TransportHandle> connect_new_request_server_client()
{
auto new_socket = Application::request_server_client().send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClient>();
if (!new_socket)
auto response = Application::request_server_client().send_sync_but_allow_failure<Messages::RequestServer::ConnectNewClient>();
if (!response)
return Error::from_string_literal("Failed to connect to RequestServer");
auto socket = new_socket->take_client_socket();
TRY(socket.clear_close_on_exec());
auto handle = response->take_handle();
TRY(handle.clear_close_on_exec());
return socket;
return handle;
}
ErrorOr<IPC::File> connect_new_image_decoder_client()
ErrorOr<IPC::TransportHandle> connect_new_image_decoder_client()
{
auto new_socket = Application::image_decoder_client().send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(1);
if (!new_socket)
auto response = Application::image_decoder_client().send_sync_but_allow_failure<Messages::ImageDecoderServer::ConnectNewClients>(1);
if (!response)
return Error::from_string_literal("Failed to connect to ImageDecoder");
auto sockets = new_socket->take_sockets();
if (sockets.size() != 1)
auto handles = response->take_handles();
if (handles.size() != 1)
return Error::from_string_literal("Failed to connect to ImageDecoder");
auto socket = sockets.take_last();
TRY(socket.clear_close_on_exec());
auto handle = handles.take_last();
TRY(handle.clear_close_on_exec());
return socket;
return handle;
}
}

View file

@ -8,6 +8,7 @@
#include <AK/Error.h>
#include <AK/Optional.h>
#include <LibIPC/TransportHandle.h>
#include <LibImageDecoderClient/Client.h>
#include <LibRequests/RequestClient.h>
#include <LibWeb/Bindings/MainThreadVM.h>
@ -20,18 +21,18 @@ namespace WebView {
WEBVIEW_API ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
WebView::ViewImplementation& view,
IPC::File image_decoder_socket,
Optional<IPC::File> request_server_socket = {});
IPC::TransportHandle image_decoder_handle,
Optional<IPC::TransportHandle> request_server_handle = {});
WEBVIEW_API ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_spare_web_content_process(
IPC::File image_decoder_socket,
Optional<IPC::File> request_server_socket = {});
IPC::TransportHandle image_decoder_handle,
Optional<IPC::TransportHandle> request_server_handle = {});
WEBVIEW_API ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process();
WEBVIEW_API ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(Web::Bindings::AgentType);
WEBVIEW_API ErrorOr<NonnullRefPtr<Requests::RequestClient>> launch_request_server_process();
WEBVIEW_API ErrorOr<IPC::File> connect_new_request_server_client();
WEBVIEW_API ErrorOr<IPC::File> connect_new_image_decoder_client();
WEBVIEW_API ErrorOr<IPC::TransportHandle> connect_new_request_server_client();
WEBVIEW_API ErrorOr<IPC::TransportHandle> connect_new_image_decoder_client();
}

View file

@ -5,6 +5,7 @@
*/
#include <LibHTTP/Cookie/ParsedCookie.h>
#include <LibIPC/TransportHandle.h>
#include <LibWebView/Application.h>
#include <LibWebView/CookieJar.h>
#include <LibWebView/HelperProcess.h>
@ -791,7 +792,7 @@ Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request
return worker_client->clone_transport();
}
return IPC::File {};
return IPC::TransportHandle {};
}
Optional<ViewImplementation&> WebContentClient::view_for_page_id(u64 page_id, SourceLocation location)

View file

@ -5,6 +5,7 @@
*/
#include <LibIPC/Transport.h>
#include <LibIPC/TransportHandle.h>
#include <LibWebView/WebContentClient.h>
#include <LibWebView/WebUI.h>
#include <LibWebView/WebUI/ProcessesUI.h>
@ -16,10 +17,10 @@ template<typename WebUIType>
static ErrorOr<NonnullRefPtr<WebUIType>> create_web_ui(WebContentClient& client, String host)
{
auto paired = TRY(IPC::Transport::create_paired());
auto peer_fd = TRY(paired.remote->release_underlying_transport_for_transfer());
auto handle = TRY(IPC::TransportHandle::from_transport(*paired.remote));
auto web_ui = WebUIType::create(client, move(paired.local), move(host));
client.async_connect_to_web_ui(0, IPC::File::adopt_fd(peer_fd));
client.async_connect_to_web_ui(0, move(handle));
return web_ui;
}

View file

@ -12,6 +12,7 @@
#include <LibGfx/Bitmap.h>
#include <LibGfx/ImageFormats/ImageDecoder.h>
#include <LibGfx/ImageFormats/TIFFMetadata.h>
#include <LibIPC/TransportHandle.h>
namespace ImageDecoder {
@ -54,30 +55,30 @@ Messages::ImageDecoderServer::InitTransportResponse ConnectionFromClient::init_t
VERIFY_NOT_REACHED();
}
ErrorOr<IPC::File> ConnectionFromClient::connect_new_client()
ErrorOr<IPC::TransportHandle> ConnectionFromClient::connect_new_client()
{
auto paired = TRY(IPC::Transport::create_paired());
auto peer_fd = TRY(paired.remote->release_underlying_transport_for_transfer());
auto handle = TRY(IPC::TransportHandle::from_transport(*paired.remote));
// Note: A ref is stored in the static s_connections map
auto client = adopt_ref(*new ConnectionFromClient(move(paired.local)));
return IPC::File::adopt_fd(peer_fd);
return handle;
}
Messages::ImageDecoderServer::ConnectNewClientsResponse ConnectionFromClient::connect_new_clients(size_t count)
{
Vector<IPC::File> files;
files.ensure_capacity(count);
Vector<IPC::TransportHandle> handles;
handles.ensure_capacity(count);
for (size_t i = 0; i < count; ++i) {
auto file_or_error = connect_new_client();
if (file_or_error.is_error()) {
dbgln("Failed to connect new client: {}", file_or_error.error());
return Vector<IPC::File> {};
auto handle_or_error = connect_new_client();
if (handle_or_error.is_error()) {
dbgln("Failed to connect new client: {}", handle_or_error.error());
return Vector<IPC::TransportHandle> {};
}
files.unchecked_append(file_or_error.release_value());
handles.unchecked_append(handle_or_error.release_value());
}
return files;
return handles;
}
static void decode_image_to_bitmaps_and_durations_with_decoder(Gfx::ImageDecoder const& decoder, Optional<Gfx::IntSize> ideal_size, Vector<RefPtr<Gfx::Bitmap>>& bitmaps, Vector<u32>& durations)

View file

@ -62,7 +62,7 @@ private:
virtual Messages::ImageDecoderServer::ConnectNewClientsResponse connect_new_clients(size_t count) override;
virtual Messages::ImageDecoderServer::InitTransportResponse init_transport(int peer_pid) override;
ErrorOr<IPC::File> connect_new_client();
ErrorOr<IPC::TransportHandle> connect_new_client();
NonnullRefPtr<Job> make_decode_image_job(i64 request_id, Core::AnonymousBuffer, Optional<Gfx::IntSize> ideal_size, Optional<ByteString> mime_type);

View file

@ -1,4 +1,5 @@
#include <LibCore/AnonymousBuffer.h>
#include <LibIPC/TransportHandle.h>
endpoint ImageDecoderServer
{
@ -9,5 +10,5 @@ endpoint ImageDecoderServer
request_animation_frames(i64 session_id, u32 start_frame_index, u32 count) =|
stop_animation_decode(i64 session_id) =|
connect_new_clients(size_t count) => (Vector<IPC::File> sockets)
connect_new_clients(size_t count) => (Vector<IPC::TransportHandle> handles)
}

View file

@ -13,6 +13,7 @@
#include <LibCore/StandardPaths.h>
#include <LibCore/System.h>
#include <LibHTTP/Cache/DiskCache.h>
#include <LibIPC/TransportHandle.h>
#include <LibRequests/WebSocket.h>
#include <LibWebSocket/ConnectionInfo.h>
#include <LibWebSocket/Message.h>
@ -113,7 +114,7 @@ Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_
auto client_socket = create_client_socket();
if (client_socket.is_error()) {
dbgln("Failed to create client socket: {}", client_socket.error());
return IPC::File {};
return IPC::TransportHandle {};
}
return client_socket.release_value();
@ -121,31 +122,31 @@ Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_
Messages::RequestServer::ConnectNewClientsResponse ConnectionFromClient::connect_new_clients(size_t count)
{
Vector<IPC::File> files;
files.ensure_capacity(count);
Vector<IPC::TransportHandle> handles;
handles.ensure_capacity(count);
for (size_t i = 0; i < count; ++i) {
auto client_socket = create_client_socket();
if (client_socket.is_error()) {
dbgln("Failed to create client socket: {}", client_socket.error());
return Vector<IPC::File> {};
return Vector<IPC::TransportHandle> {};
}
files.unchecked_append(client_socket.release_value());
handles.unchecked_append(client_socket.release_value());
}
return files;
return handles;
}
ErrorOr<IPC::File> ConnectionFromClient::create_client_socket()
ErrorOr<IPC::TransportHandle> ConnectionFromClient::create_client_socket()
{
auto paired = TRY(IPC::Transport::create_paired());
auto peer_fd = TRY(paired.remote->release_underlying_transport_for_transfer());
auto handle = TRY(IPC::TransportHandle::from_transport(*paired.remote));
// Note: A ref is stored in the m_connections map
auto client = adopt_ref(*new ConnectionFromClient(move(paired.local), IsPrimaryConnection::No, m_connections, m_disk_cache));
return IPC::File::adopt_fd(peer_fd);
return handle;
}
void ConnectionFromClient::set_disk_cache_settings(HTTP::DiskCacheSettings disk_cache_settings)

View file

@ -71,7 +71,7 @@ private:
static int on_timeout_callback(void*, long timeout_ms, void* user_data);
void check_active_requests();
ErrorOr<IPC::File> create_client_socket();
ErrorOr<IPC::TransportHandle> create_client_socket();
ConnectionMap& m_connections;
Optional<HTTP::DiskCache&> m_disk_cache;

View file

@ -3,14 +3,15 @@
#include <LibHTTP/Cache/DiskCacheSettings.h>
#include <LibHTTP/Cookie/IncludeCredentials.h>
#include <LibHTTP/Header.h>
#include <LibIPC/TransportHandle.h>
#include <LibURL/URL.h>
#include <RequestServer/CacheLevel.h>
endpoint RequestServer
{
init_transport(int peer_pid) => (int peer_pid)
connect_new_client() => (IPC::File client_socket)
connect_new_clients(size_t count) => (Vector<IPC::File> sockets)
connect_new_client() => (IPC::TransportHandle handle)
connect_new_clients(size_t count) => (Vector<IPC::TransportHandle> handles)
set_disk_cache_settings(HTTP::DiskCacheSettings disk_cache_settings) =|

View file

@ -131,25 +131,25 @@ void ConnectionFromClient::connect_to_webdriver(u64 page_id, ByteString webdrive
}
}
void ConnectionFromClient::connect_to_web_ui(u64 page_id, IPC::File web_ui_socket)
void ConnectionFromClient::connect_to_web_ui(u64 page_id, IPC::TransportHandle handle)
{
if (auto page = this->page(page_id); page.has_value()) {
// FIXME: Propagate this error back to the browser.
if (auto result = page->connect_to_web_ui(move(web_ui_socket)); result.is_error())
if (auto result = page->connect_to_web_ui(move(handle)); result.is_error())
dbgln("Unable to connect to the WebUI host: {}", result.error());
}
}
void ConnectionFromClient::connect_to_image_decoder(IPC::File image_decoder_socket)
void ConnectionFromClient::connect_to_image_decoder(IPC::TransportHandle handle)
{
if (on_image_decoder_connection)
on_image_decoder_connection(image_decoder_socket);
on_image_decoder_connection(handle);
}
void ConnectionFromClient::connect_to_request_server(IPC::File request_server_socket)
void ConnectionFromClient::connect_to_request_server(IPC::TransportHandle handle)
{
if (on_request_server_connection)
on_request_server_connection(request_server_socket);
on_request_server_connection(handle);
}
void ConnectionFromClient::update_system_theme(u64 page_id, Core::AnonymousBuffer theme_buffer)

View file

@ -46,8 +46,8 @@ public:
PageHost& page_host() { return *m_page_host; }
PageHost const& page_host() const { return *m_page_host; }
Function<void(IPC::File const&)> on_request_server_connection;
Function<void(IPC::File const&)> on_image_decoder_connection;
Function<void(IPC::TransportHandle const&)> on_request_server_connection;
Function<void(IPC::TransportHandle const&)> on_image_decoder_connection;
Queue<Web::QueuedInputEvent>& input_event_queue() { return m_input_event_queue; }
@ -62,9 +62,9 @@ private:
virtual Messages::WebContentServer::GetWindowHandleResponse get_window_handle(u64 page_id) override;
virtual void set_window_handle(u64 page_id, String handle) override;
virtual void connect_to_webdriver(u64 page_id, ByteString webdriver_ipc_path) override;
virtual void connect_to_web_ui(u64 page_id, IPC::File web_ui_socket) override;
virtual void connect_to_request_server(IPC::File request_server_socket) override;
virtual void connect_to_image_decoder(IPC::File image_decoder_socket) override;
virtual void connect_to_web_ui(u64 page_id, IPC::TransportHandle handle) override;
virtual void connect_to_request_server(IPC::TransportHandle handle) override;
virtual void connect_to_image_decoder(IPC::TransportHandle handle) override;
virtual void update_system_theme(u64 page_id, Core::AnonymousBuffer) override;
virtual void update_screen_rects(u64 page_id, Vector<Web::DevicePixelRect>, u32) override;
virtual void load_url(u64 page_id, URL::URL) override;

View file

@ -13,6 +13,7 @@
#include <LibGfx/Bitmap.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibHTTP/Cookie/ParsedCookie.h>
#include <LibIPC/TransportHandle.h>
#include <LibJS/Console.h>
#include <LibJS/Runtime/ConsoleObject.h>
#include <LibWeb/Bindings/MainThreadVM.h>
@ -730,7 +731,7 @@ 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(Web::Bindings::AgentType type)
IPC::TransportHandle PageClient::request_worker_agent(Web::Bindings::AgentType type)
{
auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::RequestWorkerAgent>(m_id, type);
if (!response) {
@ -738,7 +739,7 @@ IPC::File PageClient::request_worker_agent(Web::Bindings::AgentType type)
exit(0);
}
return response->take_socket();
return response->take_handle();
}
void PageClient::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>, GC::Ptr<Web::DOM::Node>, Optional<String> const& attribute_name)
@ -797,14 +798,14 @@ ErrorOr<void> PageClient::connect_to_webdriver(ByteString const& webdriver_ipc_p
return {};
}
ErrorOr<void> PageClient::connect_to_web_ui(IPC::File web_ui_socket)
ErrorOr<void> PageClient::connect_to_web_ui(IPC::TransportHandle handle)
{
auto* active_document = page().top_level_browsing_context().active_document();
if (!active_document || !active_document->window())
return {};
VERIFY(!m_web_ui);
m_web_ui = TRY(WebUIConnection::connect(move(web_ui_socket), *active_document));
m_web_ui = TRY(WebUIConnection::connect(move(handle), *active_document));
return {};
}

View file

@ -46,7 +46,7 @@ public:
virtual Web::Page const& page() const override { return *m_page; }
ErrorOr<void> connect_to_webdriver(ByteString const& webdriver_ipc_path);
ErrorOr<void> connect_to_web_ui(IPC::File);
ErrorOr<void> connect_to_web_ui(IPC::TransportHandle);
virtual Queue<Web::QueuedInputEvent>& input_event_queue() override;
virtual void report_finished_handling_input_event(u64 page_id, Web::EventResult event_was_handled) override;
@ -188,7 +188,7 @@ private:
virtual void page_did_request_clipboard_entries(u64 request_id) 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(Web::Bindings::AgentType) override;
virtual IPC::TransportHandle 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 page_did_paint(Gfx::IntRect const& content_rect, i32 bitmap_id) override;
virtual void page_did_take_screenshot(Gfx::ShareableBitmap const& screenshot) override;

View file

@ -1,5 +1,6 @@
#include <LibCore/AnonymousBuffer.h>
#include <LibGfx/Color.h>
#include <LibIPC/TransportHandle.h>
#include <LibGfx/Cursor.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibHTTP/Cookie/Cookie.h>
@ -134,5 +135,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, Web::Bindings::AgentType worker_type) => (IPC::File socket) // FIXME: Add required attributes to select a SharedWorker Agent
request_worker_agent(u64 page_id, Web::Bindings::AgentType worker_type) => (IPC::TransportHandle handle) // FIXME: Add required attributes to select a SharedWorker Agent
}

View file

@ -2,6 +2,7 @@
#include <LibGfx/Rect.h>
#include <LibHTTP/Cookie/Cookie.h>
#include <LibIPC/File.h>
#include <LibIPC/TransportHandle.h>
#include <LibURL/URL.h>
#include <LibWeb/Clipboard/SystemClipboard.h>
#include <LibWeb/CSS/PreferredColorScheme.h>
@ -27,9 +28,9 @@ endpoint WebContentServer
set_window_handle(u64 page_id, String handle) =|
connect_to_webdriver(u64 page_id, ByteString webdriver_ipc_path) =|
connect_to_web_ui(u64 page_id, IPC::File socket_fd) =|
connect_to_request_server(IPC::File request_server_socket) =|
connect_to_image_decoder(IPC::File socket_fd) =|
connect_to_web_ui(u64 page_id, IPC::TransportHandle handle) =|
connect_to_request_server(IPC::TransportHandle handle) =|
connect_to_image_decoder(IPC::TransportHandle handle) =|
update_system_theme(u64 page_id, Core::AnonymousBuffer theme_buffer) =|
update_screen_rects(u64 page_id, Vector<Web::DevicePixelRect> rects, u32 main_screen_index) =|

View file

@ -21,12 +21,10 @@ static auto LADYBIRD_PROPERTY = JS::PropertyKey { "ladybird"_utf16_fly_string };
static auto WEB_UI_LOADED_EVENT = "WebUILoaded"_fly_string;
static auto WEB_UI_MESSAGE_EVENT = "WebUIMessage"_fly_string;
ErrorOr<NonnullRefPtr<WebUIConnection>> WebUIConnection::connect(IPC::File web_ui_socket, Web::DOM::Document& document)
ErrorOr<NonnullRefPtr<WebUIConnection>> WebUIConnection::connect(IPC::TransportHandle handle, Web::DOM::Document& document)
{
auto socket = TRY(Core::LocalSocket::adopt_fd(web_ui_socket.take_fd()));
TRY(socket->set_blocking(true));
return adopt_ref(*new WebUIConnection(make<IPC::Transport>(move(socket)), document));
auto transport = TRY(handle.create_transport());
return adopt_ref(*new WebUIConnection(move(transport), document));
}
WebUIConnection::WebUIConnection(NonnullOwnPtr<IPC::Transport> transport, Web::DOM::Document& document)

View file

@ -11,6 +11,7 @@
#include <LibGC/Ptr.h>
#include <LibIPC/ConnectionFromClient.h>
#include <LibIPC/Transport.h>
#include <LibIPC/TransportHandle.h>
#include <LibJS/Heap/Cell.h>
#include <LibWeb/Forward.h>
#include <WebContent/WebUIClientEndpoint.h>
@ -20,7 +21,7 @@ namespace WebContent {
class WebUIConnection final : public IPC::ConnectionFromClient<WebUIClientEndpoint, WebUIServerEndpoint> {
public:
static ErrorOr<NonnullRefPtr<WebUIConnection>> connect(IPC::File, Web::DOM::Document&);
static ErrorOr<NonnullRefPtr<WebUIConnection>> connect(IPC::TransportHandle, Web::DOM::Document&);
virtual ~WebUIConnection() override;
void visit_edges(JS::Cell::Visitor&);

View file

@ -16,6 +16,7 @@
#include <LibGfx/Font/FontDatabase.h>
#include <LibGfx/Font/PathFontProvider.h>
#include <LibIPC/ConnectionFromClient.h>
#include <LibIPC/TransportHandle.h>
#include <LibJS/Bytecode/Interpreter.h>
#include <LibMain/Main.h>
#include <LibRequests/RequestClient.h>
@ -97,10 +98,10 @@ static void install_crash_signal_handlers()
static ErrorOr<void> load_content_filters(StringView config_path);
static ErrorOr<void> initialize_resource_loader(GC::Heap&, int request_server_socket);
static ErrorOr<void> reinitialize_resource_loader(IPC::File const& image_decoder_socket);
static ErrorOr<void> reinitialize_resource_loader(IPC::TransportHandle const& handle);
static ErrorOr<void> initialize_image_decoder(int image_decoder_socket);
static ErrorOr<void> reinitialize_image_decoder(IPC::File const& image_decoder_socket);
static ErrorOr<void> reinitialize_image_decoder(IPC::TransportHandle const& handle);
ErrorOr<int> ladybird_main(Main::Arguments arguments)
{
@ -262,12 +263,12 @@ ErrorOr<int> ladybird_main(Main::Arguments arguments)
auto webcontent_socket = TRY(Core::take_over_socket_from_system_server("WebContent"sv));
auto webcontent_client = WebContent::ConnectionFromClient::construct(make<IPC::Transport>(move(webcontent_socket)));
webcontent_client->on_request_server_connection = [&](auto const& socket_file) {
if (auto result = reinitialize_resource_loader(socket_file); result.is_error())
webcontent_client->on_request_server_connection = [&](auto const& handle) {
if (auto result = reinitialize_resource_loader(handle); result.is_error())
dbgln("Failed to reinitialize resource loader: {}", result.error());
};
webcontent_client->on_image_decoder_connection = [&](auto const& socket_file) {
if (auto result = reinitialize_image_decoder(socket_file); result.is_error())
webcontent_client->on_image_decoder_connection = [&](auto const& handle) {
if (auto result = reinitialize_image_decoder(handle); result.is_error())
dbgln("Failed to reinitialize image decoder: {}", result.error());
};
@ -314,13 +315,10 @@ ErrorOr<void> initialize_resource_loader(GC::Heap& heap, int request_server_sock
return {};
}
ErrorOr<void> reinitialize_resource_loader(IPC::File const& request_server_socket)
ErrorOr<void> reinitialize_resource_loader(IPC::TransportHandle const& handle)
{
// TODO: Mach IPC
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket.take_fd()));
TRY(socket->set_blocking(true));
auto request_client = TRY(try_make_ref_counted<Requests::RequestClient>(make<IPC::Transport>(move(socket))));
auto transport = TRY(handle.create_transport());
auto request_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(transport)));
Web::ResourceLoader::the().set_client(move(request_client));
return {};
@ -342,13 +340,10 @@ ErrorOr<void> initialize_image_decoder(int image_decoder_socket)
return {};
}
ErrorOr<void> reinitialize_image_decoder(IPC::File const& image_decoder_socket)
ErrorOr<void> reinitialize_image_decoder(IPC::TransportHandle const& handle)
{
// TODO: Mach IPC
auto socket = TRY(Core::LocalSocket::adopt_fd(image_decoder_socket.take_fd()));
TRY(socket->set_blocking(true));
auto new_client = TRY(try_make_ref_counted<ImageDecoderClient::Client>(make<IPC::Transport>(move(socket))));
auto transport = TRY(handle.create_transport());
auto new_client = TRY(try_make_ref_counted<ImageDecoderClient::Client>(move(transport)));
static_cast<WebView::ImageCodecPlugin&>(Web::Platform::ImageCodecPlugin::the()).set_client(move(new_client));
return {};

View file

@ -97,7 +97,7 @@ void PageHost::request_file(Web::FileRequest request)
m_client.request_file(move(request));
}
IPC::File PageHost::request_worker_agent(Web::Bindings::AgentType worker_type)
IPC::TransportHandle PageHost::request_worker_agent(Web::Bindings::AgentType worker_type)
{
return m_client.request_worker_agent(worker_type);
}

View file

@ -38,7 +38,7 @@ public:
virtual size_t screen_count() const override { return 1; }
virtual HTTP::Cookie::VersionedCookie page_did_request_cookie(URL::URL const&, HTTP::Cookie::Source) override;
virtual void request_file(Web::FileRequest) override;
virtual IPC::File request_worker_agent(Web::Bindings::AgentType) override;
virtual IPC::TransportHandle request_worker_agent(Web::Bindings::AgentType) override;
virtual Web::DisplayListPlayerType display_list_player_type() const override { VERIFY_NOT_REACHED(); }
virtual bool is_headless() const override { VERIFY_NOT_REACHED(); }
virtual Queue<Web::QueuedInputEvent>& input_event_queue() override { VERIFY_NOT_REACHED(); }