mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
LibIPC+Everywhere: Introduce an IPC Transport abstraction
This abstraction will help us to support multiple IPC transport mechanisms going forward. For now, we only have a TransportSocket that implements the same behavior we previously had, using Unix Sockets for IPC.
This commit is contained in:
parent
9a6eccc590
commit
7372b2af48
Notes:
github-actions[bot]
2024-10-23 19:14:14 +00:00
Author: https://github.com/ADKaster Commit: https://github.com/LadybirdBrowser/ladybird/commit/7372b2af487 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1925 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/trflynn89
45 changed files with 415 additions and 234 deletions
|
@ -134,7 +134,7 @@ static ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_new_image_decod
|
||||||
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_request_server_client));
|
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, *m_request_server_client));
|
||||||
|
|
||||||
return worker_client->dup_socket();
|
return worker_client->clone_transport();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - NSApplication
|
#pragma mark - NSApplication
|
||||||
|
|
|
@ -33,7 +33,7 @@ HeadlessWebView::HeadlessWebView(Core::AnonymousBuffer theme, Gfx::IntSize viewp
|
||||||
auto web_worker_paths = MUST(get_paths_for_helper_process("WebWorker"sv));
|
auto web_worker_paths = MUST(get_paths_for_helper_process("WebWorker"sv));
|
||||||
auto worker_client = MUST(launch_web_worker_process(web_worker_paths, Application::request_client()));
|
auto worker_client = MUST(launch_web_worker_process(web_worker_paths, Application::request_client()));
|
||||||
|
|
||||||
return worker_client->dup_socket();
|
return worker_client->clone_transport();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ WebContentView::WebContentView(QWidget* window, RefPtr<WebView::WebContentClient
|
||||||
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_socket();
|
return worker_client->clone_transport();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_select_dropdown = new QMenu("Select Dropdown", this);
|
m_select_dropdown = new QMenu("Select Dropdown", this);
|
||||||
|
|
|
@ -188,8 +188,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
if (maybe_autoplay_allowlist_error.is_error())
|
if (maybe_autoplay_allowlist_error.is_error())
|
||||||
dbgln("Failed to load autoplay allowlist: {}", maybe_autoplay_allowlist_error.error());
|
dbgln("Failed to load autoplay allowlist: {}", maybe_autoplay_allowlist_error.error());
|
||||||
|
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
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(IPC::Transport(move(webcontent_socket))));
|
||||||
|
|
||||||
webcontent_client->on_image_decoder_connection = [&](auto& socket_file) {
|
webcontent_client->on_image_decoder_connection = [&](auto& socket_file) {
|
||||||
auto maybe_error = reinitialize_image_decoder(socket_file);
|
auto maybe_error = reinitialize_image_decoder(socket_file);
|
||||||
|
@ -250,10 +252,12 @@ static ErrorOr<void> load_autoplay_allowlist(StringView config_path)
|
||||||
|
|
||||||
ErrorOr<void> initialize_resource_loader(int request_server_socket)
|
ErrorOr<void> initialize_resource_loader(int request_server_socket)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
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 request_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(socket)));
|
auto request_client = TRY(try_make_ref_counted<Requests::RequestClient>(IPC::Transport(move(socket))));
|
||||||
Web::ResourceLoader::initialize(move(request_client));
|
Web::ResourceLoader::initialize(move(request_client));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -261,10 +265,11 @@ ErrorOr<void> initialize_resource_loader(int request_server_socket)
|
||||||
|
|
||||||
ErrorOr<void> initialize_image_decoder(int image_decoder_socket)
|
ErrorOr<void> initialize_image_decoder(int image_decoder_socket)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
auto socket = TRY(Core::LocalSocket::adopt_fd(image_decoder_socket));
|
auto socket = TRY(Core::LocalSocket::adopt_fd(image_decoder_socket));
|
||||||
TRY(socket->set_blocking(true));
|
TRY(socket->set_blocking(true));
|
||||||
|
|
||||||
auto new_client = TRY(try_make_ref_counted<ImageDecoderClient::Client>(move(socket)));
|
auto new_client = TRY(try_make_ref_counted<ImageDecoderClient::Client>(IPC::Transport(move(socket))));
|
||||||
|
|
||||||
Web::Platform::ImageCodecPlugin::install(*new Ladybird::ImageCodecPlugin(move(new_client)));
|
Web::Platform::ImageCodecPlugin::install(*new Ladybird::ImageCodecPlugin(move(new_client)));
|
||||||
|
|
||||||
|
@ -273,10 +278,12 @@ ErrorOr<void> initialize_image_decoder(int image_decoder_socket)
|
||||||
|
|
||||||
ErrorOr<void> reinitialize_image_decoder(IPC::File const& image_decoder_socket)
|
ErrorOr<void> reinitialize_image_decoder(IPC::File const& image_decoder_socket)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
auto socket = TRY(Core::LocalSocket::adopt_fd(image_decoder_socket.take_fd()));
|
auto socket = TRY(Core::LocalSocket::adopt_fd(image_decoder_socket.take_fd()));
|
||||||
TRY(socket->set_blocking(true));
|
TRY(socket->set_blocking(true));
|
||||||
|
|
||||||
auto new_client = TRY(try_make_ref_counted<ImageDecoderClient::Client>(move(socket)));
|
auto new_client = TRY(try_make_ref_counted<ImageDecoderClient::Client>(IPC::Transport(move(socket))));
|
||||||
|
|
||||||
static_cast<Ladybird::ImageCodecPlugin&>(Web::Platform::ImageCodecPlugin::the()).set_client(move(new_client));
|
static_cast<Ladybird::ImageCodecPlugin&>(Web::Platform::ImageCodecPlugin::the()).set_client(move(new_client));
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
static ErrorOr<void> initialize_resource_loader(int request_server_socket)
|
static ErrorOr<void> initialize_resource_loader(int request_server_socket)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
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 request_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(socket)));
|
auto request_client = TRY(try_make_ref_counted<Requests::RequestClient>(IPC::Transport(move(socket))));
|
||||||
Web::ResourceLoader::initialize(move(request_client));
|
Web::ResourceLoader::initialize(move(request_client));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -5,5 +5,9 @@ set(SOURCES
|
||||||
Message.cpp
|
Message.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
list(APPEND SOURCES TransportSocket.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
serenity_lib(LibIPC ipc)
|
serenity_lib(LibIPC ipc)
|
||||||
target_link_libraries(LibIPC PRIVATE LibCore LibURL LibThreading)
|
target_link_libraries(LibIPC PRIVATE LibCore LibURL LibThreading)
|
||||||
|
|
|
@ -14,22 +14,19 @@
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::LocalSocket> socket, u32 local_endpoint_magic)
|
ConnectionBase::ConnectionBase(IPC::Stub& local_stub, Transport transport, u32 local_endpoint_magic)
|
||||||
: m_local_stub(local_stub)
|
: m_local_stub(local_stub)
|
||||||
, m_socket(move(socket))
|
, m_transport(move(transport))
|
||||||
, m_local_endpoint_magic(local_endpoint_magic)
|
, m_local_endpoint_magic(local_endpoint_magic)
|
||||||
{
|
{
|
||||||
socklen_t socket_buffer_size = 128 * KiB;
|
|
||||||
(void)Core::System::setsockopt(m_socket->fd().value(), SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size));
|
|
||||||
(void)Core::System::setsockopt(m_socket->fd().value(), SOL_SOCKET, SO_RCVBUF, &socket_buffer_size, sizeof(socket_buffer_size));
|
|
||||||
|
|
||||||
m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); });
|
m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); });
|
||||||
m_socket->on_ready_to_read = [this] {
|
|
||||||
|
m_transport.set_up_read_hook([this] {
|
||||||
NonnullRefPtr protect = *this;
|
NonnullRefPtr protect = *this;
|
||||||
// FIXME: Do something about errors.
|
// FIXME: Do something about errors.
|
||||||
(void)drain_messages_from_peer();
|
(void)drain_messages_from_peer();
|
||||||
handle_messages();
|
handle_messages();
|
||||||
};
|
});
|
||||||
|
|
||||||
m_send_queue = adopt_ref(*new SendQueue);
|
m_send_queue = adopt_ref(*new SendQueue);
|
||||||
m_send_thread = Threading::Thread::construct([this, queue = m_send_queue]() -> intptr_t {
|
m_send_thread = Threading::Thread::construct([this, queue = m_send_queue]() -> intptr_t {
|
||||||
|
@ -46,7 +43,7 @@ ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::LocalS
|
||||||
auto message = queue->messages.take_first();
|
auto message = queue->messages.take_first();
|
||||||
queue->mutex.unlock();
|
queue->mutex.unlock();
|
||||||
|
|
||||||
if (auto result = message.transfer_message(*m_socket); result.is_error()) {
|
if (auto result = message.transfer_message(m_transport); result.is_error()) {
|
||||||
dbgln("ConnectionBase::send_thread: {}", result.error());
|
dbgln("ConnectionBase::send_thread: {}", result.error());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +65,7 @@ ConnectionBase::~ConnectionBase()
|
||||||
|
|
||||||
bool ConnectionBase::is_open() const
|
bool ConnectionBase::is_open() const
|
||||||
{
|
{
|
||||||
return m_socket->is_open();
|
return m_transport.is_open();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> ConnectionBase::post_message(Message const& message)
|
ErrorOr<void> ConnectionBase::post_message(Message const& message)
|
||||||
|
@ -80,7 +77,7 @@ ErrorOr<void> ConnectionBase::post_message(MessageBuffer buffer)
|
||||||
{
|
{
|
||||||
// NOTE: If this connection is being shut down, but has not yet been destroyed,
|
// NOTE: If this connection is being shut down, but has not yet been destroyed,
|
||||||
// the socket will be closed. Don't try to send more messages.
|
// the socket will be closed. Don't try to send more messages.
|
||||||
if (!m_socket->is_open())
|
if (!m_transport.is_open())
|
||||||
return Error::from_string_literal("Trying to post_message during IPC shutdown");
|
return Error::from_string_literal("Trying to post_message during IPC shutdown");
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -95,7 +92,7 @@ ErrorOr<void> ConnectionBase::post_message(MessageBuffer buffer)
|
||||||
|
|
||||||
void ConnectionBase::shutdown()
|
void ConnectionBase::shutdown()
|
||||||
{
|
{
|
||||||
m_socket->close();
|
m_transport.close();
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,19 +122,12 @@ void ConnectionBase::handle_messages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionBase::wait_for_socket_to_become_readable()
|
void ConnectionBase::wait_for_transport_to_become_readable()
|
||||||
{
|
{
|
||||||
auto maybe_did_become_readable = m_socket->can_read_without_blocking(-1);
|
m_transport.wait_until_readable();
|
||||||
if (maybe_did_become_readable.is_error()) {
|
|
||||||
dbgln("ConnectionBase::wait_for_socket_to_become_readable: {}", maybe_did_become_readable.error());
|
|
||||||
warnln("ConnectionBase::wait_for_socket_to_become_readable: {}", maybe_did_become_readable.error());
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
VERIFY(maybe_did_become_readable.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without_blocking()
|
ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_transport_without_blocking()
|
||||||
{
|
{
|
||||||
Vector<u8> bytes;
|
Vector<u8> bytes;
|
||||||
|
|
||||||
|
@ -146,9 +136,6 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
|
||||||
m_unprocessed_bytes.clear();
|
m_unprocessed_bytes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 buffer[4096];
|
|
||||||
Vector<int> received_fds;
|
|
||||||
|
|
||||||
bool should_shut_down = false;
|
bool should_shut_down = false;
|
||||||
auto schedule_shutdown = [this, &should_shut_down]() {
|
auto schedule_shutdown = [this, &should_shut_down]() {
|
||||||
should_shut_down = true;
|
should_shut_down = true;
|
||||||
|
@ -157,34 +144,11 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
while (m_socket->is_open()) {
|
auto&& [new_bytes, received_fds] = m_transport.read_as_much_as_possible_without_blocking(move(schedule_shutdown));
|
||||||
auto maybe_bytes_read = m_socket->receive_message({ buffer, 4096 }, MSG_DONTWAIT, received_fds);
|
bytes.append(new_bytes.data(), new_bytes.size());
|
||||||
if (maybe_bytes_read.is_error()) {
|
|
||||||
auto error = maybe_bytes_read.release_error();
|
|
||||||
if (error.is_syscall() && error.code() == EAGAIN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.is_syscall() && error.code() == ECONNRESET) {
|
|
||||||
schedule_shutdown();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbgln("ConnectionBase::read_as_much_as_possible_from_socket_without_blocking: {}", error);
|
|
||||||
warnln("ConnectionBase::read_as_much_as_possible_from_socket_without_blocking: {}", error);
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bytes_read = maybe_bytes_read.release_value();
|
|
||||||
if (bytes_read.is_empty()) {
|
|
||||||
schedule_shutdown();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes.append(bytes_read.data(), bytes_read.size());
|
|
||||||
for (auto const& fd : received_fds)
|
for (auto const& fd : received_fds)
|
||||||
m_unprocessed_fds.enqueue(IPC::File::adopt_fd(fd));
|
m_unprocessed_fds.enqueue(IPC::File::adopt_fd(fd));
|
||||||
}
|
|
||||||
|
|
||||||
if (!bytes.is_empty()) {
|
if (!bytes.is_empty()) {
|
||||||
m_responsiveness_timer->stop();
|
m_responsiveness_timer->stop();
|
||||||
|
@ -198,7 +162,7 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
|
||||||
|
|
||||||
ErrorOr<void> ConnectionBase::drain_messages_from_peer()
|
ErrorOr<void> ConnectionBase::drain_messages_from_peer()
|
||||||
{
|
{
|
||||||
auto bytes = TRY(read_as_much_as_possible_from_socket_without_blocking());
|
auto bytes = TRY(read_as_much_as_possible_from_transport_without_blocking());
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
try_parse_messages(bytes, index);
|
try_parse_messages(bytes, index);
|
||||||
|
@ -236,10 +200,10 @@ OwnPtr<IPC::Message> ConnectionBase::wait_for_specific_endpoint_message_impl(u32
|
||||||
return m_unprocessed_messages.take(i);
|
return m_unprocessed_messages.take(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_socket->is_open())
|
if (!is_open())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
wait_for_socket_to_become_readable();
|
wait_for_transport_to_become_readable();
|
||||||
if (drain_messages_from_peer().is_error())
|
if (drain_messages_from_peer().is_error())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <LibCore/EventReceiver.h>
|
#include <LibCore/EventReceiver.h>
|
||||||
#include <LibIPC/File.h>
|
#include <LibIPC/File.h>
|
||||||
#include <LibIPC/Forward.h>
|
#include <LibIPC/Forward.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <LibThreading/ConditionVariable.h>
|
#include <LibThreading/ConditionVariable.h>
|
||||||
#include <LibThreading/MutexProtected.h>
|
#include <LibThreading/MutexProtected.h>
|
||||||
#include <LibThreading/Thread.h>
|
#include <LibThreading/Thread.h>
|
||||||
|
@ -30,10 +31,10 @@ public:
|
||||||
void shutdown();
|
void shutdown();
|
||||||
virtual void die() { }
|
virtual void die() { }
|
||||||
|
|
||||||
Core::LocalSocket& socket() { return *m_socket; }
|
Transport& transport() { return m_transport; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::LocalSocket>, u32 local_endpoint_magic);
|
explicit ConnectionBase(IPC::Stub&, Transport, u32 local_endpoint_magic);
|
||||||
|
|
||||||
virtual void may_have_become_unresponsive() { }
|
virtual void may_have_become_unresponsive() { }
|
||||||
virtual void did_become_responsive() { }
|
virtual void did_become_responsive() { }
|
||||||
|
@ -41,8 +42,8 @@ protected:
|
||||||
virtual OwnPtr<Message> try_parse_message(ReadonlyBytes, Queue<IPC::File>&) = 0;
|
virtual OwnPtr<Message> try_parse_message(ReadonlyBytes, Queue<IPC::File>&) = 0;
|
||||||
|
|
||||||
OwnPtr<IPC::Message> wait_for_specific_endpoint_message_impl(u32 endpoint_magic, int message_id);
|
OwnPtr<IPC::Message> wait_for_specific_endpoint_message_impl(u32 endpoint_magic, int message_id);
|
||||||
void wait_for_socket_to_become_readable();
|
void wait_for_transport_to_become_readable();
|
||||||
ErrorOr<Vector<u8>> read_as_much_as_possible_from_socket_without_blocking();
|
ErrorOr<Vector<u8>> read_as_much_as_possible_from_transport_without_blocking();
|
||||||
ErrorOr<void> drain_messages_from_peer();
|
ErrorOr<void> drain_messages_from_peer();
|
||||||
void try_parse_messages(Vector<u8> const& bytes, size_t& index);
|
void try_parse_messages(Vector<u8> const& bytes, size_t& index);
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ protected:
|
||||||
|
|
||||||
IPC::Stub& m_local_stub;
|
IPC::Stub& m_local_stub;
|
||||||
|
|
||||||
NonnullOwnPtr<Core::LocalSocket> m_socket;
|
Transport m_transport;
|
||||||
|
|
||||||
RefPtr<Core::Timer> m_responsiveness_timer;
|
RefPtr<Core::Timer> m_responsiveness_timer;
|
||||||
|
|
||||||
|
@ -75,8 +76,8 @@ protected:
|
||||||
template<typename LocalEndpoint, typename PeerEndpoint>
|
template<typename LocalEndpoint, typename PeerEndpoint>
|
||||||
class Connection : public ConnectionBase {
|
class Connection : public ConnectionBase {
|
||||||
public:
|
public:
|
||||||
Connection(IPC::Stub& local_stub, NonnullOwnPtr<Core::LocalSocket> socket)
|
Connection(IPC::Stub& local_stub, Transport transport)
|
||||||
: ConnectionBase(local_stub, move(socket), LocalEndpoint::static_magic())
|
: ConnectionBase(local_stub, move(transport), LocalEndpoint::static_magic())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,16 +26,16 @@ public:
|
||||||
using ServerStub = typename ServerEndpoint::Stub;
|
using ServerStub = typename ServerEndpoint::Stub;
|
||||||
using IPCProxy = typename ClientEndpoint::template Proxy<ServerEndpoint>;
|
using IPCProxy = typename ClientEndpoint::template Proxy<ServerEndpoint>;
|
||||||
|
|
||||||
ConnectionFromClient(ServerStub& stub, NonnullOwnPtr<Core::LocalSocket> socket, int client_id)
|
ConnectionFromClient(ServerStub& stub, Transport transport, int client_id)
|
||||||
: IPC::Connection<ServerEndpoint, ClientEndpoint>(stub, move(socket))
|
: IPC::Connection<ServerEndpoint, ClientEndpoint>(stub, move(transport))
|
||||||
, ClientEndpoint::template Proxy<ServerEndpoint>(*this, {})
|
, ClientEndpoint::template Proxy<ServerEndpoint>(*this, {})
|
||||||
, m_client_id(client_id)
|
, m_client_id(client_id)
|
||||||
{
|
{
|
||||||
VERIFY(this->socket().is_open());
|
this->transport().set_up_read_hook([this] {
|
||||||
this->socket().on_ready_to_read = [this] {
|
NonnullRefPtr protect = *this;
|
||||||
// FIXME: Do something about errors.
|
// FIXME: Do something about errors.
|
||||||
(void)this->drain_messages_from_peer();
|
(void)this->drain_messages_from_peer();
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ConnectionFromClient() override = default;
|
virtual ~ConnectionFromClient() override = default;
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
/* We want to rate-limit our clients */ \
|
/* We want to rate-limit our clients */ \
|
||||||
TRY(socket->set_blocking(true)); \
|
TRY(socket->set_blocking(true)); \
|
||||||
\
|
\
|
||||||
return adopt_nonnull_ref_or_enomem(new (nothrow) Klass(move(socket), forward<Args>(args)...)); \
|
return adopt_nonnull_ref_or_enomem(new (nothrow) Klass(IPC::Transport(move(socket)), forward<Args>(args)...)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ClientEndpoint, typename ServerEndpoint>
|
template<typename ClientEndpoint, typename ServerEndpoint>
|
||||||
|
@ -33,8 +33,8 @@ public:
|
||||||
using ClientStub = typename ClientEndpoint::Stub;
|
using ClientStub = typename ClientEndpoint::Stub;
|
||||||
using IPCProxy = typename ServerEndpoint::template Proxy<ClientEndpoint>;
|
using IPCProxy = typename ServerEndpoint::template Proxy<ClientEndpoint>;
|
||||||
|
|
||||||
ConnectionToServer(ClientStub& local_endpoint, NonnullOwnPtr<Core::LocalSocket> socket)
|
ConnectionToServer(ClientStub& local_endpoint, Transport transport)
|
||||||
: Connection<ClientEndpoint, ServerEndpoint>(local_endpoint, move(socket))
|
: Connection<ClientEndpoint, ServerEndpoint>(local_endpoint, move(transport))
|
||||||
, ServerEndpoint::template Proxy<ClientEndpoint>(*this, {})
|
, ServerEndpoint::template Proxy<ClientEndpoint>(*this, {})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Checked.h>
|
#include <AK/Checked.h>
|
||||||
#include <LibCore/Socket.h>
|
|
||||||
#include <LibCore/System.h>
|
|
||||||
#include <LibIPC/Message.h>
|
#include <LibIPC/Message.h>
|
||||||
#include <sched.h>
|
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
|
@ -38,7 +35,7 @@ ErrorOr<void> MessageBuffer::append_file_descriptor(int fd)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> MessageBuffer::transfer_message(Core::LocalSocket& socket)
|
ErrorOr<void> MessageBuffer::transfer_message(Transport& transport)
|
||||||
{
|
{
|
||||||
Checked<MessageSizeType> checked_message_size { m_data.size() };
|
Checked<MessageSizeType> checked_message_size { m_data.size() };
|
||||||
checked_message_size -= sizeof(MessageSizeType);
|
checked_message_size -= sizeof(MessageSizeType);
|
||||||
|
@ -58,49 +55,7 @@ ErrorOr<void> MessageBuffer::transfer_message(Core::LocalSocket& socket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadonlyBytes bytes_to_write { m_data.span() };
|
TRY(transport.transfer(m_data.span(), raw_fds));
|
||||||
|
|
||||||
while (!bytes_to_write.is_empty()) {
|
|
||||||
ErrorOr<ssize_t> maybe_nwritten = 0;
|
|
||||||
if (num_fds_to_transfer > 0) {
|
|
||||||
maybe_nwritten = socket.send_message(bytes_to_write, 0, raw_fds);
|
|
||||||
if (!maybe_nwritten.is_error())
|
|
||||||
num_fds_to_transfer = 0;
|
|
||||||
} else {
|
|
||||||
maybe_nwritten = socket.write_some(bytes_to_write);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maybe_nwritten.is_error()) {
|
|
||||||
if (auto error = maybe_nwritten.release_error(); error.is_errno() && (error.code() == EAGAIN || error.code() == EWOULDBLOCK)) {
|
|
||||||
Vector<struct pollfd, 1> pollfds;
|
|
||||||
if (pollfds.is_empty())
|
|
||||||
pollfds.append({ .fd = socket.fd().value(), .events = POLLOUT, .revents = 0 });
|
|
||||||
|
|
||||||
ErrorOr<int> result { 0 };
|
|
||||||
do {
|
|
||||||
constexpr u32 POLL_TIMEOUT_MS = 100;
|
|
||||||
result = Core::System::poll(pollfds, POLL_TIMEOUT_MS);
|
|
||||||
} while (result.is_error() && result.error().code() == EINTR);
|
|
||||||
|
|
||||||
if (!result.is_error() && result.value() != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (error.code()) {
|
|
||||||
case EPIPE:
|
|
||||||
return Error::from_string_literal("IPC::transfer_message: Disconnected from peer");
|
|
||||||
case EAGAIN:
|
|
||||||
return Error::from_string_literal("IPC::transfer_message: Timed out waiting for socket to become writable");
|
|
||||||
default:
|
|
||||||
return Error::from_syscall("IPC::transfer_message write"sv, -error.code());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes_to_write = bytes_to_write.slice(maybe_nwritten.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibCore/Forward.h>
|
#include <LibCore/Forward.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
@ -44,7 +45,7 @@ public:
|
||||||
|
|
||||||
ErrorOr<void> append_file_descriptor(int fd);
|
ErrorOr<void> append_file_descriptor(int fd);
|
||||||
|
|
||||||
ErrorOr<void> transfer_message(Core::LocalSocket& socket);
|
ErrorOr<void> transfer_message(Transport& socket);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<u8, 1024> m_data;
|
Vector<u8, 1024> m_data;
|
||||||
|
|
|
@ -37,7 +37,7 @@ private:
|
||||||
m_server->on_accept = [&](auto client_socket) {
|
m_server->on_accept = [&](auto client_socket) {
|
||||||
auto client_id = ++m_next_client_id;
|
auto client_id = ++m_next_client_id;
|
||||||
|
|
||||||
auto client = IPC::new_client_connection<ConnectionFromClientType>(move(client_socket), client_id);
|
auto client = IPC::new_client_connection<ConnectionFromClientType>(IPC::Transport(move(client_socket)), client_id);
|
||||||
if (on_new_client)
|
if (on_new_client)
|
||||||
on_new_client(*client);
|
on_new_client(*client);
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ template<typename ConnectionFromClientType>
|
||||||
ErrorOr<NonnullRefPtr<ConnectionFromClientType>> take_over_accepted_client_from_system_server()
|
ErrorOr<NonnullRefPtr<ConnectionFromClientType>> take_over_accepted_client_from_system_server()
|
||||||
{
|
{
|
||||||
auto socket = TRY(Core::take_over_socket_from_system_server());
|
auto socket = TRY(Core::take_over_socket_from_system_server());
|
||||||
return IPC::new_client_connection<ConnectionFromClientType>(move(socket));
|
return IPC::new_client_connection<ConnectionFromClientType>(IPC::Transport(move(socket)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
24
Userland/Libraries/LibIPC/Transport.h
Normal file
24
Userland/Libraries/LibIPC/Transport.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Platform.h>
|
||||||
|
|
||||||
|
#if !defined(AK_OS_WINDOWS)
|
||||||
|
# include <LibIPC/TransportSocket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
|
||||||
|
#if !defined(AK_OS_WINDOWS)
|
||||||
|
// Unix Domain Sockets
|
||||||
|
using Transport = TransportSocket;
|
||||||
|
#else
|
||||||
|
# error "LibIPC Transport has not been ported to this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
151
Userland/Libraries/LibIPC/TransportSocket.cpp
Normal file
151
Userland/Libraries/LibIPC/TransportSocket.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/NonnullOwnPtr.h>
|
||||||
|
#include <LibCore/Socket.h>
|
||||||
|
#include <LibCore/System.h>
|
||||||
|
#include <LibIPC/File.h>
|
||||||
|
#include <LibIPC/TransportSocket.h>
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
|
||||||
|
TransportSocket::TransportSocket(NonnullOwnPtr<Core::LocalSocket> socket)
|
||||||
|
: m_socket(move(socket))
|
||||||
|
{
|
||||||
|
socklen_t socket_buffer_size = 128 * KiB;
|
||||||
|
(void)Core::System::setsockopt(m_socket->fd().value(), SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size));
|
||||||
|
(void)Core::System::setsockopt(m_socket->fd().value(), SOL_SOCKET, SO_RCVBUF, &socket_buffer_size, sizeof(socket_buffer_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportSocket::~TransportSocket() = default;
|
||||||
|
|
||||||
|
void TransportSocket::set_up_read_hook(Function<void()> hook)
|
||||||
|
{
|
||||||
|
VERIFY(m_socket->is_open());
|
||||||
|
m_socket->on_ready_to_read = move(hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TransportSocket::is_open() const
|
||||||
|
{
|
||||||
|
return m_socket->is_open();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransportSocket::close()
|
||||||
|
{
|
||||||
|
m_socket->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransportSocket::wait_until_readable()
|
||||||
|
{
|
||||||
|
auto maybe_did_become_readable = m_socket->can_read_without_blocking(-1);
|
||||||
|
if (maybe_did_become_readable.is_error()) {
|
||||||
|
dbgln("TransportSocket::wait_until_readable: {}", maybe_did_become_readable.error());
|
||||||
|
warnln("TransportSocket::wait_until_readable: {}", maybe_did_become_readable.error());
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(maybe_did_become_readable.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> TransportSocket::transfer(ReadonlyBytes bytes_to_write, Vector<int, 1> const& unowned_fds)
|
||||||
|
{
|
||||||
|
auto num_fds_to_transfer = unowned_fds.size();
|
||||||
|
while (!bytes_to_write.is_empty()) {
|
||||||
|
ErrorOr<ssize_t> maybe_nwritten = 0;
|
||||||
|
if (num_fds_to_transfer > 0) {
|
||||||
|
maybe_nwritten = m_socket->send_message(bytes_to_write, 0, unowned_fds);
|
||||||
|
if (!maybe_nwritten.is_error())
|
||||||
|
num_fds_to_transfer = 0;
|
||||||
|
} else {
|
||||||
|
maybe_nwritten = m_socket->write_some(bytes_to_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maybe_nwritten.is_error()) {
|
||||||
|
if (auto error = maybe_nwritten.release_error(); error.is_errno() && (error.code() == EAGAIN || error.code() == EWOULDBLOCK)) {
|
||||||
|
|
||||||
|
// FIXME: Refactor this to pass the unwritten bytes back to the caller to send 'later'
|
||||||
|
// or next time the socket is writable
|
||||||
|
Vector<struct pollfd, 1> pollfds;
|
||||||
|
if (pollfds.is_empty())
|
||||||
|
pollfds.append({ .fd = m_socket->fd().value(), .events = POLLOUT, .revents = 0 });
|
||||||
|
|
||||||
|
ErrorOr<int> result { 0 };
|
||||||
|
do {
|
||||||
|
constexpr u32 POLL_TIMEOUT_MS = 100;
|
||||||
|
result = Core::System::poll(pollfds, POLL_TIMEOUT_MS);
|
||||||
|
} while (result.is_error() && result.error().code() == EINTR);
|
||||||
|
|
||||||
|
if (!result.is_error() && result.value() != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (error.code()) {
|
||||||
|
case EPIPE:
|
||||||
|
return Error::from_string_literal("IPC::transfer_message: Disconnected from peer");
|
||||||
|
case EAGAIN:
|
||||||
|
return Error::from_string_literal("IPC::transfer_message: Timed out waiting for socket to become writable");
|
||||||
|
default:
|
||||||
|
return Error::from_syscall("IPC::transfer_message write"sv, -error.code());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_to_write = bytes_to_write.slice(maybe_nwritten.value());
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportSocket::ReadResult TransportSocket::read_as_much_as_possible_without_blocking(Function<void()> schedule_shutdown)
|
||||||
|
{
|
||||||
|
u8 buffer[4096];
|
||||||
|
|
||||||
|
ReadResult result;
|
||||||
|
auto received_fds = Vector<int> {};
|
||||||
|
auto& bytes = result.bytes;
|
||||||
|
|
||||||
|
while (is_open()) {
|
||||||
|
auto maybe_bytes_read = m_socket->receive_message({ buffer, 4096 }, MSG_DONTWAIT, received_fds);
|
||||||
|
if (maybe_bytes_read.is_error()) {
|
||||||
|
auto error = maybe_bytes_read.release_error();
|
||||||
|
if (error.is_syscall() && error.code() == EAGAIN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.is_syscall() && error.code() == ECONNRESET) {
|
||||||
|
schedule_shutdown();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgln("TransportSocket::read_as_much_as_possible_without_blocking: {}", error);
|
||||||
|
warnln("TransportSocket::read_as_much_as_possible_without_blocking: {}", error);
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bytes_read = maybe_bytes_read.release_value();
|
||||||
|
if (bytes_read.is_empty()) {
|
||||||
|
schedule_shutdown();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes.append(bytes_read.data(), bytes_read.size());
|
||||||
|
result.fds.append(received_fds.data(), received_fds.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<int> TransportSocket::release_underlying_transport_for_transfer()
|
||||||
|
{
|
||||||
|
return m_socket->release_fd();
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<IPC::File> TransportSocket::clone_for_transfer()
|
||||||
|
{
|
||||||
|
return IPC::File::clone_fd(m_socket->fd().value());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
Userland/Libraries/LibIPC/TransportSocket.h
Normal file
44
Userland/Libraries/LibIPC/TransportSocket.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibCore/File.h>
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
|
||||||
|
class TransportSocket {
|
||||||
|
AK_MAKE_NONCOPYABLE(TransportSocket);
|
||||||
|
AK_MAKE_DEFAULT_MOVABLE(TransportSocket);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TransportSocket(NonnullOwnPtr<Core::LocalSocket> socket);
|
||||||
|
~TransportSocket();
|
||||||
|
|
||||||
|
void set_up_read_hook(Function<void()>);
|
||||||
|
bool is_open() const;
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void wait_until_readable();
|
||||||
|
|
||||||
|
ErrorOr<void> transfer(ReadonlyBytes, Vector<int, 1> const& unowned_fds);
|
||||||
|
|
||||||
|
struct [[nodiscard]] ReadResult {
|
||||||
|
Vector<u8> bytes;
|
||||||
|
Vector<int> fds;
|
||||||
|
};
|
||||||
|
ReadResult read_as_much_as_possible_without_blocking(Function<void()> schedule_shutdown);
|
||||||
|
|
||||||
|
// Obnoxious name to make it clear that this is a dangerous operation.
|
||||||
|
ErrorOr<int> release_underlying_transport_for_transfer();
|
||||||
|
|
||||||
|
ErrorOr<IPC::File> clone_for_transfer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NonnullOwnPtr<Core::LocalSocket> m_socket;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
namespace ImageDecoderClient {
|
namespace ImageDecoderClient {
|
||||||
|
|
||||||
Client::Client(NonnullOwnPtr<Core::LocalSocket> socket)
|
Client::Client(IPC::Transport transport)
|
||||||
: IPC::ConnectionToServer<ImageDecoderClientEndpoint, ImageDecoderServerEndpoint>(*this, move(socket))
|
: IPC::ConnectionToServer<ImageDecoderClientEndpoint, ImageDecoderServerEndpoint>(*this, move(transport))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Client final
|
||||||
IPC_CLIENT_CONNECTION(Client, "/tmp/session/%sid/portal/image"sv);
|
IPC_CLIENT_CONNECTION(Client, "/tmp/session/%sid/portal/image"sv);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Client(NonnullOwnPtr<Core::LocalSocket>);
|
Client(IPC::Transport);
|
||||||
|
|
||||||
NonnullRefPtr<Core::Promise<DecodedImage>> decode_image(ReadonlyBytes, Function<ErrorOr<void>(DecodedImage&)> on_resolved, Function<void(Error&)> on_rejected, Optional<Gfx::IntSize> ideal_size = {}, Optional<ByteString> mime_type = {});
|
NonnullRefPtr<Core::Promise<DecodedImage>> decode_image(ReadonlyBytes, Function<ErrorOr<void>(DecodedImage&)> on_resolved, Function<void(Error&)> on_rejected, Optional<Gfx::IntSize> ideal_size = {}, Optional<ByteString> mime_type = {});
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
namespace Requests {
|
namespace Requests {
|
||||||
|
|
||||||
RequestClient::RequestClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
RequestClient::RequestClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionToServer<RequestClientEndpoint, RequestServerEndpoint>(*this, move(socket))
|
: IPC::ConnectionToServer<RequestClientEndpoint, RequestServerEndpoint>(*this, move(transport))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class RequestClient final
|
||||||
IPC_CLIENT_CONNECTION(RequestClient, "/tmp/session/%sid/portal/request"sv)
|
IPC_CLIENT_CONNECTION(RequestClient, "/tmp/session/%sid/portal/request"sv)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RequestClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit RequestClient(IPC::Transport);
|
||||||
virtual ~RequestClient() override;
|
virtual ~RequestClient() override;
|
||||||
|
|
||||||
RefPtr<Request> start_request(ByteString const& method, URL::URL const&, HTTP::HeaderMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {});
|
RefPtr<Request> start_request(ByteString const& method, URL::URL const&, HTTP::HeaderMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {});
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <LibIPC/Decoder.h>
|
#include <LibIPC/Decoder.h>
|
||||||
#include <LibIPC/Encoder.h>
|
#include <LibIPC/Encoder.h>
|
||||||
#include <LibIPC/File.h>
|
#include <LibIPC/File.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
#include <LibWeb/Bindings/MessagePortPrototype.h>
|
#include <LibWeb/Bindings/MessagePortPrototype.h>
|
||||||
|
@ -71,6 +72,11 @@ void MessagePort::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(m_worker_event_target);
|
visitor.visit(m_worker_event_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MessagePort::is_entangled() const
|
||||||
|
{
|
||||||
|
return m_transport.has_value();
|
||||||
|
}
|
||||||
|
|
||||||
void MessagePort::set_worker_event_target(JS::NonnullGCPtr<DOM::EventTarget> target)
|
void MessagePort::set_worker_event_target(JS::NonnullGCPtr<DOM::EventTarget> target)
|
||||||
{
|
{
|
||||||
m_worker_event_target = target;
|
m_worker_event_target = target;
|
||||||
|
@ -91,10 +97,14 @@ WebIDL::ExceptionOr<void> MessagePort::transfer_steps(HTML::TransferDataHolder&
|
||||||
m_remote_port->m_has_been_shipped = true;
|
m_remote_port->m_has_been_shipped = true;
|
||||||
|
|
||||||
// 2. Set dataHolder.[[RemotePort]] to remotePort.
|
// 2. Set dataHolder.[[RemotePort]] to remotePort.
|
||||||
auto fd = MUST(m_socket->release_fd());
|
if constexpr (IsSame<IPC::Transport, IPC::TransportSocket>) {
|
||||||
m_socket = nullptr;
|
auto fd = MUST(m_transport->release_underlying_transport_for_transfer());
|
||||||
|
m_transport = {};
|
||||||
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);
|
||||||
|
} else {
|
||||||
|
VERIFY(false && "Don't know how to transfer IPC::Transport type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Otherwise, set dataHolder.[[RemotePort]] to null.
|
// 4. Otherwise, set dataHolder.[[RemotePort]] to null.
|
||||||
|
@ -118,12 +128,16 @@ WebIDL::ExceptionOr<void> MessagePort::transfer_receiving_steps(HTML::TransferDa
|
||||||
// (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
|
// (This will disentangle dataHolder.[[RemotePort]] from the original port that was transferred.)
|
||||||
auto fd_tag = data_holder.data.take_first();
|
auto fd_tag = data_holder.data.take_first();
|
||||||
if (fd_tag == IPC_FILE_TAG) {
|
if (fd_tag == IPC_FILE_TAG) {
|
||||||
|
if constexpr (IsSame<IPC::Transport, IPC::TransportSocket>) {
|
||||||
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_transport = IPC::Transport(MUST(Core::LocalSocket::adopt_fd(fd.take_fd())));
|
||||||
|
|
||||||
m_socket->on_ready_to_read = [strong_this = JS::make_handle(this)]() {
|
m_transport->set_up_read_hook([strong_this = JS::make_handle(this)]() {
|
||||||
strong_this->read_from_socket();
|
strong_this->read_from_transport();
|
||||||
};
|
});
|
||||||
|
} else {
|
||||||
|
VERIFY(false && "Don't know how to receive IPC::Transport type");
|
||||||
|
}
|
||||||
} else if (fd_tag != 0) {
|
} else if (fd_tag != 0) {
|
||||||
dbgln("Unexpected byte {:x} in MessagePort transfer data", fd_tag);
|
dbgln("Unexpected byte {:x} in MessagePort transfer data", fd_tag);
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -138,7 +152,7 @@ void MessagePort::disentangle()
|
||||||
m_remote_port->m_remote_port = nullptr;
|
m_remote_port->m_remote_port = nullptr;
|
||||||
m_remote_port = nullptr;
|
m_remote_port = nullptr;
|
||||||
|
|
||||||
m_socket = nullptr;
|
m_transport = {};
|
||||||
|
|
||||||
m_worker_event_target = nullptr;
|
m_worker_event_target = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +174,7 @@ void MessagePort::entangle_with(MessagePort& remote_port)
|
||||||
remote_port.m_remote_port = this;
|
remote_port.m_remote_port = this;
|
||||||
m_remote_port = &remote_port;
|
m_remote_port = &remote_port;
|
||||||
|
|
||||||
|
// FIXME: Abstract such that we can entangle different transport types
|
||||||
auto create_paired_sockets = []() -> Array<NonnullOwnPtr<Core::LocalSocket>, 2> {
|
auto create_paired_sockets = []() -> Array<NonnullOwnPtr<Core::LocalSocket>, 2> {
|
||||||
int fds[2] = {};
|
int fds[2] = {};
|
||||||
MUST(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fds));
|
MUST(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fds));
|
||||||
|
@ -174,16 +189,16 @@ void MessagePort::entangle_with(MessagePort& remote_port)
|
||||||
};
|
};
|
||||||
|
|
||||||
auto sockets = create_paired_sockets();
|
auto sockets = create_paired_sockets();
|
||||||
m_socket = move(sockets[0]);
|
m_transport = IPC::Transport(move(sockets[0]));
|
||||||
m_remote_port->m_socket = move(sockets[1]);
|
m_remote_port->m_transport = IPC::Transport(move(sockets[1]));
|
||||||
|
|
||||||
m_socket->on_ready_to_read = [strong_this = JS::make_handle(this)]() {
|
m_transport->set_up_read_hook([strong_this = JS::make_handle(this)]() {
|
||||||
strong_this->read_from_socket();
|
strong_this->read_from_transport();
|
||||||
};
|
});
|
||||||
|
|
||||||
m_remote_port->m_socket->on_ready_to_read = [remote_port = JS::make_handle(m_remote_port)]() {
|
m_remote_port->m_transport->set_up_read_hook([remote_port = JS::make_handle(m_remote_port)]() {
|
||||||
remote_port->read_from_socket();
|
remote_port->read_from_transport();
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -243,7 +258,7 @@ WebIDL::ExceptionOr<void> MessagePort::message_port_post_message_steps(JS::GCPtr
|
||||||
// 6. If targetPort is null, or if doomed is true, then return.
|
// 6. If targetPort is null, or if doomed is true, then return.
|
||||||
// IMPLEMENTATION DEFINED: Actually check the socket here, not the target port.
|
// IMPLEMENTATION DEFINED: Actually check the socket here, not the target port.
|
||||||
// If there's no target message port in the same realm, we still want to send the message over IPC
|
// If there's no target message port in the same realm, we still want to send the message over IPC
|
||||||
if (!m_socket || doomed) {
|
if (!m_transport.has_value() || doomed) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,13 +268,13 @@ WebIDL::ExceptionOr<void> MessagePort::message_port_post_message_steps(JS::GCPtr
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> MessagePort::send_message_on_socket(SerializedTransferRecord const& serialize_with_transfer_result)
|
ErrorOr<void> MessagePort::send_message_on_transport(SerializedTransferRecord const& serialize_with_transfer_result)
|
||||||
{
|
{
|
||||||
IPC::MessageBuffer buffer;
|
IPC::MessageBuffer buffer;
|
||||||
IPC::Encoder encoder(buffer);
|
IPC::Encoder encoder(buffer);
|
||||||
MUST(encoder.encode(serialize_with_transfer_result));
|
MUST(encoder.encode(serialize_with_transfer_result));
|
||||||
|
|
||||||
TRY(buffer.transfer_message(*m_socket));
|
TRY(buffer.transfer_message(*m_transport));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,9 +282,9 @@ void MessagePort::post_port_message(SerializedTransferRecord serialize_with_tran
|
||||||
{
|
{
|
||||||
// FIXME: Use the correct task source?
|
// FIXME: Use the correct task source?
|
||||||
queue_global_task(Task::Source::PostedMessage, relevant_global_object(*this), JS::create_heap_function(heap(), [this, serialize_with_transfer_result = move(serialize_with_transfer_result)]() mutable {
|
queue_global_task(Task::Source::PostedMessage, relevant_global_object(*this), JS::create_heap_function(heap(), [this, serialize_with_transfer_result = move(serialize_with_transfer_result)]() mutable {
|
||||||
if (!m_socket || !m_socket->is_open())
|
if (!m_transport.has_value() || !m_transport->is_open())
|
||||||
return;
|
return;
|
||||||
if (auto result = send_message_on_socket(serialize_with_transfer_result); result.is_error()) {
|
if (auto result = send_message_on_transport(serialize_with_transfer_result); result.is_error()) {
|
||||||
dbgln("Failed to post message: {}", result.error());
|
dbgln("Failed to post message: {}", result.error());
|
||||||
disentangle();
|
disentangle();
|
||||||
}
|
}
|
||||||
|
@ -320,18 +335,13 @@ ErrorOr<MessagePort::ParseDecision> MessagePort::parse_message()
|
||||||
return ParseDecision::ParseNextMessage;
|
return ParseDecision::ParseNextMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagePort::read_from_socket()
|
void MessagePort::read_from_transport()
|
||||||
{
|
{
|
||||||
u8 buffer[4096] {};
|
auto&& [bytes, fds] = m_transport->read_as_much_as_possible_without_blocking([this] {
|
||||||
|
queue_global_task(Task::Source::PostedMessage, relevant_global_object(*this), JS::create_heap_function(heap(), [this] {
|
||||||
Vector<int> fds;
|
this->close();
|
||||||
// FIXME: What if pending bytes is > 4096? Should we loop here?
|
}));
|
||||||
auto maybe_bytes = m_socket->receive_message(buffer, MSG_NOSIGNAL, fds);
|
});
|
||||||
if (maybe_bytes.is_error()) {
|
|
||||||
dbgln("MessagePort::read_from_socket(): Failed to receive message: {}", maybe_bytes.error());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto bytes = maybe_bytes.release_value();
|
|
||||||
|
|
||||||
m_buffered_data.append(bytes.data(), bytes.size());
|
m_buffered_data.append(bytes.data(), bytes.size());
|
||||||
|
|
||||||
|
@ -406,7 +416,7 @@ void MessagePort::start()
|
||||||
if (!is_entangled())
|
if (!is_entangled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VERIFY(m_socket);
|
VERIFY(m_transport.has_value());
|
||||||
|
|
||||||
// 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.
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <AK/Weakable.h>
|
#include <AK/Weakable.h>
|
||||||
#include <LibCore/Socket.h>
|
#include <LibCore/Socket.h>
|
||||||
#include <LibIPC/File.h>
|
#include <LibIPC/File.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <LibWeb/Bindings/Transferable.h>
|
#include <LibWeb/Bindings/Transferable.h>
|
||||||
#include <LibWeb/DOM/EventTarget.h>
|
#include <LibWeb/DOM/EventTarget.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
@ -69,13 +70,13 @@ private:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
bool is_entangled() const { return static_cast<bool>(m_socket); }
|
bool is_entangled() const;
|
||||||
|
|
||||||
WebIDL::ExceptionOr<void> message_port_post_message_steps(JS::GCPtr<MessagePort> target_port, JS::Value message, StructuredSerializeOptions const& options);
|
WebIDL::ExceptionOr<void> message_port_post_message_steps(JS::GCPtr<MessagePort> target_port, JS::Value message, StructuredSerializeOptions const& options);
|
||||||
void post_message_task_steps(SerializedTransferRecord&);
|
void post_message_task_steps(SerializedTransferRecord&);
|
||||||
void post_port_message(SerializedTransferRecord);
|
void post_port_message(SerializedTransferRecord);
|
||||||
ErrorOr<void> send_message_on_socket(SerializedTransferRecord const&);
|
ErrorOr<void> send_message_on_transport(SerializedTransferRecord const&);
|
||||||
void read_from_socket();
|
void read_from_transport();
|
||||||
|
|
||||||
enum class ParseDecision {
|
enum class ParseDecision {
|
||||||
NotEnoughData,
|
NotEnoughData,
|
||||||
|
@ -89,7 +90,7 @@ private:
|
||||||
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
|
||||||
bool m_has_been_shipped { false };
|
bool m_has_been_shipped { false };
|
||||||
|
|
||||||
OwnPtr<Core::LocalSocket> m_socket;
|
Optional<IPC::Transport> m_transport;
|
||||||
|
|
||||||
enum class SocketState : u8 {
|
enum class SocketState : u8 {
|
||||||
Header,
|
Header,
|
||||||
|
|
|
@ -35,10 +35,14 @@ 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_socket_file = 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_socket_file.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));
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Handle other IPC::Transport types here");
|
||||||
|
|
||||||
m_worker_ipc = make_ref_counted<WebWorkerClient>(move(worker_socket));
|
auto transport = IPC::Transport(move(worker_socket));
|
||||||
|
|
||||||
|
m_worker_ipc = make_ref_counted<WebWorkerClient>(move(transport));
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@ void WebWorkerClient::did_close_worker()
|
||||||
on_worker_close();
|
on_worker_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
WebWorkerClient::WebWorkerClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
WebWorkerClient::WebWorkerClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionToServer<WebWorkerClientEndpoint, WebWorkerServerEndpoint>(*this, move(socket))
|
: IPC::ConnectionToServer<WebWorkerClientEndpoint, WebWorkerServerEndpoint>(*this, move(transport))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::File WebWorkerClient::dup_socket()
|
IPC::File WebWorkerClient::clone_transport()
|
||||||
{
|
{
|
||||||
return MUST(IPC::File::clone_fd(socket().fd().value()));
|
return MUST(m_transport.clone_for_transfer());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,13 @@ class WebWorkerClient final
|
||||||
IPC_CLIENT_CONNECTION(WebWorkerClient, "/tmp/session/%sid/portal/webworker"sv);
|
IPC_CLIENT_CONNECTION(WebWorkerClient, "/tmp/session/%sid/portal/webworker"sv);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WebWorkerClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit WebWorkerClient(IPC::Transport);
|
||||||
|
|
||||||
virtual void did_close_worker() override;
|
virtual void did_close_worker() override;
|
||||||
|
|
||||||
Function<void()> on_worker_close;
|
Function<void()> on_worker_close;
|
||||||
|
|
||||||
IPC::File dup_socket();
|
IPC::File clone_transport();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void die() override;
|
virtual void die() override;
|
||||||
|
|
|
@ -22,7 +22,7 @@ class UIProcessClient final
|
||||||
C_OBJECT(UIProcessClient);
|
C_OBJECT(UIProcessClient);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UIProcessClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit UIProcessClient(IPC::Transport);
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorOr<ChromeProcess::ProcessDisposition> ChromeProcess::connect(Vector<ByteString> const& raw_urls, NewWindow new_window)
|
ErrorOr<ChromeProcess::ProcessDisposition> ChromeProcess::connect(Vector<ByteString> const& raw_urls, NewWindow new_window)
|
||||||
|
@ -48,7 +48,8 @@ ErrorOr<ChromeProcess::ProcessDisposition> ChromeProcess::connect(Vector<ByteStr
|
||||||
ErrorOr<void> ChromeProcess::connect_as_client(ByteString const& socket_path, Vector<ByteString> const& raw_urls, NewWindow new_window)
|
ErrorOr<void> ChromeProcess::connect_as_client(ByteString const& socket_path, Vector<ByteString> const& raw_urls, NewWindow new_window)
|
||||||
{
|
{
|
||||||
auto socket = TRY(Core::LocalSocket::connect(socket_path));
|
auto socket = TRY(Core::LocalSocket::connect(socket_path));
|
||||||
auto client = UIProcessClient::construct(move(socket));
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
auto client = UIProcessClient::construct(IPC::Transport(move(socket)));
|
||||||
|
|
||||||
if (new_window == NewWindow::Yes) {
|
if (new_window == NewWindow::Yes) {
|
||||||
if (!client->send_sync_but_allow_failure<Messages::UIProcessServer::CreateNewWindow>(raw_urls))
|
if (!client->send_sync_but_allow_failure<Messages::UIProcessServer::CreateNewWindow>(raw_urls))
|
||||||
|
@ -63,10 +64,13 @@ ErrorOr<void> ChromeProcess::connect_as_client(ByteString const& socket_path, Ve
|
||||||
|
|
||||||
ErrorOr<void> ChromeProcess::connect_as_server(ByteString const& socket_path)
|
ErrorOr<void> ChromeProcess::connect_as_server(ByteString const& socket_path)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
auto socket_fd = TRY(Process::create_ipc_socket(socket_path));
|
auto socket_fd = TRY(Process::create_ipc_socket(socket_path));
|
||||||
m_socket_path = socket_path;
|
m_socket_path = socket_path;
|
||||||
auto local_server = TRY(Core::LocalServer::try_create());
|
auto local_server = TRY(Core::LocalServer::try_create());
|
||||||
TRY(local_server->take_over_fd(socket_fd));
|
TRY(local_server->take_over_fd(socket_fd));
|
||||||
|
|
||||||
m_server_connection = TRY(IPC::MultiServer<UIProcessConnectionFromClient>::try_create(move(local_server)));
|
m_server_connection = TRY(IPC::MultiServer<UIProcessConnectionFromClient>::try_create(move(local_server)));
|
||||||
|
|
||||||
m_server_connection->on_new_client = [this](auto& client) {
|
m_server_connection->on_new_client = [this](auto& client) {
|
||||||
|
@ -95,13 +99,13 @@ ChromeProcess::~ChromeProcess()
|
||||||
MUST(Core::System::unlink(m_socket_path));
|
MUST(Core::System::unlink(m_socket_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
UIProcessClient::UIProcessClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
UIProcessClient::UIProcessClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionToServer<UIProcessClientEndpoint, UIProcessServerEndpoint>(*this, move(socket))
|
: IPC::ConnectionToServer<UIProcessClientEndpoint, UIProcessServerEndpoint>(*this, move(transport))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
UIProcessConnectionFromClient::UIProcessConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket, int client_id)
|
UIProcessConnectionFromClient::UIProcessConnectionFromClient(IPC::Transport transport, int client_id)
|
||||||
: IPC::ConnectionFromClient<UIProcessClientEndpoint, UIProcessServerEndpoint>(*this, move(socket), client_id)
|
: IPC::ConnectionFromClient<UIProcessClientEndpoint, UIProcessServerEndpoint>(*this, move(transport), client_id)
|
||||||
{
|
{
|
||||||
s_connections.set(client_id, *this);
|
s_connections.set(client_id, *this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <LibCore/Socket.h>
|
|
||||||
#include <LibIPC/ConnectionFromClient.h>
|
#include <LibIPC/ConnectionFromClient.h>
|
||||||
#include <LibIPC/Forward.h>
|
#include <LibIPC/Forward.h>
|
||||||
#include <LibIPC/MultiServer.h>
|
#include <LibIPC/MultiServer.h>
|
||||||
|
@ -33,7 +32,7 @@ public:
|
||||||
Function<void(Vector<URL::URL> const&)> on_new_window;
|
Function<void(Vector<URL::URL> const&)> on_new_window;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UIProcessConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id);
|
UIProcessConnectionFromClient(IPC::Transport, int client_id);
|
||||||
|
|
||||||
virtual void create_new_tab(Vector<ByteString> const& urls) override;
|
virtual void create_new_tab(Vector<ByteString> const& urls) override;
|
||||||
virtual void create_new_window(Vector<ByteString> const& urls) override;
|
virtual void create_new_window(Vector<ByteString> const& urls) override;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <LibCore/Environment.h>
|
#include <LibCore/Environment.h>
|
||||||
#include <LibCore/Process.h>
|
#include <LibCore/Process.h>
|
||||||
|
#include <LibCore/Socket.h>
|
||||||
#include <LibCore/StandardPaths.h>
|
#include <LibCore/StandardPaths.h>
|
||||||
#include <LibWebView/Process.h>
|
#include <LibWebView/Process.h>
|
||||||
|
|
||||||
|
@ -24,8 +25,10 @@ Process::~Process()
|
||||||
m_connection->shutdown();
|
m_connection->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<Process::ProcessAndIPCSocket> Process::spawn_and_connect_to_process(Core::ProcessSpawnOptions const& options)
|
ErrorOr<Process::ProcessAndIPCTransport> Process::spawn_and_connect_to_process(Core::ProcessSpawnOptions const& options)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
|
@ -44,7 +47,7 @@ ErrorOr<Process::ProcessAndIPCSocket> Process::spawn_and_connect_to_process(Core
|
||||||
guard_fd_0.disarm();
|
guard_fd_0.disarm();
|
||||||
TRY(ipc_socket->set_blocking(true));
|
TRY(ipc_socket->set_blocking(true));
|
||||||
|
|
||||||
return ProcessAndIPCSocket { move(process), move(ipc_socket) };
|
return ProcessAndIPCTransport { move(process), IPC::Transport(move(ipc_socket)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<Optional<pid_t>> Process::get_process_pid(StringView process_name, StringView pid_path)
|
ErrorOr<Optional<pid_t>> Process::get_process_pid(StringView process_name, StringView pid_path)
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <LibCore/Process.h>
|
#include <LibCore/Process.h>
|
||||||
#include <LibCore/Socket.h>
|
|
||||||
#include <LibIPC/Connection.h>
|
#include <LibIPC/Connection.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <LibWebView/ProcessType.h>
|
#include <LibWebView/ProcessType.h>
|
||||||
|
|
||||||
namespace WebView {
|
namespace WebView {
|
||||||
|
@ -52,11 +52,11 @@ public:
|
||||||
static ErrorOr<int> create_ipc_socket(ByteString const& socket_path);
|
static ErrorOr<int> create_ipc_socket(ByteString const& socket_path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ProcessAndIPCSocket {
|
struct ProcessAndIPCTransport {
|
||||||
Core::Process process;
|
Core::Process process;
|
||||||
NonnullOwnPtr<Core::LocalSocket> socket;
|
IPC::Transport transport;
|
||||||
};
|
};
|
||||||
static ErrorOr<ProcessAndIPCSocket> spawn_and_connect_to_process(Core::ProcessSpawnOptions const& options);
|
static ErrorOr<ProcessAndIPCTransport> spawn_and_connect_to_process(Core::ProcessSpawnOptions const& options);
|
||||||
|
|
||||||
Core::Process m_process;
|
Core::Process m_process;
|
||||||
ProcessType m_type;
|
ProcessType m_type;
|
||||||
|
@ -73,8 +73,8 @@ struct Process::ProcessAndClient {
|
||||||
template<typename ClientType, typename... ClientArguments>
|
template<typename ClientType, typename... ClientArguments>
|
||||||
ErrorOr<Process::ProcessAndClient<ClientType>> Process::spawn(ProcessType type, Core::ProcessSpawnOptions const& options, ClientArguments&&... client_arguments)
|
ErrorOr<Process::ProcessAndClient<ClientType>> Process::spawn(ProcessType type, Core::ProcessSpawnOptions const& options, ClientArguments&&... client_arguments)
|
||||||
{
|
{
|
||||||
auto [core_process, socket] = TRY(spawn_and_connect_to_process(options));
|
auto [core_process, transport] = TRY(spawn_and_connect_to_process(options));
|
||||||
auto client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ClientType { move(socket), forward<ClientArguments>(client_arguments)... }));
|
auto client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ClientType { move(transport), forward<ClientArguments>(client_arguments)... }));
|
||||||
|
|
||||||
return ProcessAndClient { Process { type, client, move(core_process) }, client };
|
return ProcessAndClient { Process { type, client, move(core_process) }, client };
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ Optional<ViewImplementation&> WebContentClient::view_for_pid_and_page_id(pid_t p
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
WebContentClient::WebContentClient(NonnullOwnPtr<Core::LocalSocket> socket, ViewImplementation& view)
|
WebContentClient::WebContentClient(IPC::Transport transport, ViewImplementation& view)
|
||||||
: IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket))
|
: IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(transport))
|
||||||
{
|
{
|
||||||
s_clients.set(this);
|
s_clients.set(this);
|
||||||
m_views.set(0, &view);
|
m_views.set(0, &view);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/SourceLocation.h>
|
#include <AK/SourceLocation.h>
|
||||||
#include <LibIPC/ConnectionToServer.h>
|
#include <LibIPC/ConnectionToServer.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
#include <LibWeb/CSS/StyleSheetIdentifier.h>
|
||||||
#include <LibWeb/HTML/ActivateTab.h>
|
#include <LibWeb/HTML/ActivateTab.h>
|
||||||
#include <LibWeb/HTML/FileFilter.h>
|
#include <LibWeb/HTML/FileFilter.h>
|
||||||
|
@ -35,7 +36,7 @@ public:
|
||||||
|
|
||||||
static size_t client_count() { return s_clients.size(); }
|
static size_t client_count() { return s_clients.size(); }
|
||||||
|
|
||||||
WebContentClient(NonnullOwnPtr<Core::LocalSocket>, ViewImplementation&);
|
WebContentClient(IPC::Transport, ViewImplementation&);
|
||||||
~WebContentClient();
|
~WebContentClient();
|
||||||
|
|
||||||
void register_view(u64 page_id, ViewImplementation&);
|
void register_view(u64 page_id, ViewImplementation&);
|
||||||
|
|
|
@ -17,8 +17,8 @@ namespace ImageDecoder {
|
||||||
static HashMap<int, RefPtr<ConnectionFromClient>> s_connections;
|
static HashMap<int, RefPtr<ConnectionFromClient>> s_connections;
|
||||||
static IDAllocator s_client_ids;
|
static IDAllocator s_client_ids;
|
||||||
|
|
||||||
ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
ConnectionFromClient::ConnectionFromClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionFromClient<ImageDecoderClientEndpoint, ImageDecoderServerEndpoint>(*this, move(socket), s_client_ids.allocate())
|
: IPC::ConnectionFromClient<ImageDecoderClientEndpoint, ImageDecoderServerEndpoint>(*this, move(transport), s_client_ids.allocate())
|
||||||
{
|
{
|
||||||
s_connections.set(client_id(), *this);
|
s_connections.set(client_id(), *this);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ ErrorOr<IPC::File> ConnectionFromClient::connect_new_client()
|
||||||
|
|
||||||
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(IPC::Transport(move(client_socket))));
|
||||||
|
|
||||||
return IPC::File::adopt_fd(socket_fds[1]);
|
return IPC::File::adopt_fd(socket_fds[1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
private:
|
private:
|
||||||
using Job = Threading::BackgroundAction<DecodeResult>;
|
using Job = Threading::BackgroundAction<DecodeResult>;
|
||||||
|
|
||||||
explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit ConnectionFromClient(IPC::Transport);
|
||||||
|
|
||||||
virtual Messages::ImageDecoderServer::DecodeImageResponse decode_image(Core::AnonymousBuffer const&, Optional<Gfx::IntSize> const& ideal_size, Optional<ByteString> const& mime_type) override;
|
virtual Messages::ImageDecoderServer::DecodeImageResponse decode_image(Core::AnonymousBuffer const&, Optional<Gfx::IntSize> const& ideal_size, Optional<ByteString> const& mime_type) override;
|
||||||
virtual void cancel_decoding(i64 image_id) override;
|
virtual void cancel_decoding(i64 image_id) override;
|
||||||
|
|
|
@ -175,8 +175,8 @@ int ConnectionFromClient::on_timeout_callback(void*, long timeout_ms, void* user
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
ConnectionFromClient::ConnectionFromClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionFromClient<RequestClientEndpoint, RequestServerEndpoint>(*this, move(socket), s_client_ids.allocate())
|
: IPC::ConnectionFromClient<RequestClientEndpoint, RequestServerEndpoint>(*this, move(transport), s_client_ids.allocate())
|
||||||
{
|
{
|
||||||
s_connections.set(client_id(), *this);
|
s_connections.set(client_id(), *this);
|
||||||
|
|
||||||
|
@ -215,6 +215,8 @@ void ConnectionFromClient::die()
|
||||||
|
|
||||||
Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_new_client()
|
Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_new_client()
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
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());
|
||||||
|
@ -230,7 +232,7 @@ Messages::RequestServer::ConnectNewClientResponse ConnectionFromClient::connect_
|
||||||
}
|
}
|
||||||
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(IPC::Transport(move(client_socket))));
|
||||||
|
|
||||||
return IPC::File::adopt_fd(socket_fds[1]);
|
return IPC::File::adopt_fd(socket_fds[1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
void did_request_certificates(Badge<Request>, Request&);
|
void did_request_certificates(Badge<Request>, Request&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit ConnectionFromClient(IPC::Transport);
|
||||||
|
|
||||||
virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() override;
|
virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() override;
|
||||||
virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString const&) override;
|
virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString const&) override;
|
||||||
|
|
|
@ -53,8 +53,8 @@
|
||||||
|
|
||||||
namespace WebContent {
|
namespace WebContent {
|
||||||
|
|
||||||
ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
ConnectionFromClient::ConnectionFromClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionFromClient<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket), 1)
|
: IPC::ConnectionFromClient<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(transport), 1)
|
||||||
, m_page_host(PageHost::create(*this))
|
, m_page_host(PageHost::create(*this))
|
||||||
{
|
{
|
||||||
m_input_event_queue_timer = Web::Platform::Timer::create_single_shot(0, [this] { process_next_input_event(); });
|
m_input_event_queue_timer = Web::Platform::Timer::create_single_shot(0, [this] { process_next_input_event(); });
|
||||||
|
|
|
@ -42,15 +42,13 @@ public:
|
||||||
|
|
||||||
void request_file(u64 page_id, Web::FileRequest);
|
void request_file(u64 page_id, Web::FileRequest);
|
||||||
|
|
||||||
Optional<int> fd() { return socket().fd(); }
|
|
||||||
|
|
||||||
PageHost& page_host() { return *m_page_host; }
|
PageHost& page_host() { return *m_page_host; }
|
||||||
PageHost const& page_host() const { return *m_page_host; }
|
PageHost const& page_host() const { return *m_page_host; }
|
||||||
|
|
||||||
Function<void(IPC::File const&)> on_image_decoder_connection;
|
Function<void(IPC::File const&)> on_image_decoder_connection;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit ConnectionFromClient(IPC::Transport);
|
||||||
|
|
||||||
Optional<PageClient&> page(u64 index, SourceLocation = SourceLocation::current());
|
Optional<PageClient&> page(u64 index, SourceLocation = SourceLocation::current());
|
||||||
Optional<PageClient const&> page(u64 index, SourceLocation = SourceLocation::current()) const;
|
Optional<PageClient const&> page(u64 index, SourceLocation = SourceLocation::current()) const;
|
||||||
|
|
|
@ -184,6 +184,8 @@ static bool fire_an_event(FlyString name, Optional<Web::DOM::Element&> target)
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<WebDriverConnection>> WebDriverConnection::connect(Web::PageClient& page_client, ByteString const& webdriver_ipc_path)
|
ErrorOr<NonnullRefPtr<WebDriverConnection>> WebDriverConnection::connect(Web::PageClient& page_client, ByteString const& webdriver_ipc_path)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
dbgln_if(WEBDRIVER_DEBUG, "Trying to connect to {}", webdriver_ipc_path);
|
dbgln_if(WEBDRIVER_DEBUG, "Trying to connect to {}", webdriver_ipc_path);
|
||||||
auto socket = TRY(Core::LocalSocket::connect(webdriver_ipc_path));
|
auto socket = TRY(Core::LocalSocket::connect(webdriver_ipc_path));
|
||||||
|
|
||||||
|
@ -191,11 +193,11 @@ ErrorOr<NonnullRefPtr<WebDriverConnection>> WebDriverConnection::connect(Web::Pa
|
||||||
page_client.page().set_should_block_pop_ups(false);
|
page_client.page().set_should_block_pop_ups(false);
|
||||||
|
|
||||||
dbgln_if(WEBDRIVER_DEBUG, "Connected to WebDriver");
|
dbgln_if(WEBDRIVER_DEBUG, "Connected to WebDriver");
|
||||||
return adopt_nonnull_ref_or_enomem(new (nothrow) WebDriverConnection(move(socket), page_client));
|
return adopt_nonnull_ref_or_enomem(new (nothrow) WebDriverConnection(IPC::Transport(move(socket)), page_client));
|
||||||
}
|
}
|
||||||
|
|
||||||
WebDriverConnection::WebDriverConnection(NonnullOwnPtr<Core::LocalSocket> socket, Web::PageClient& page_client)
|
WebDriverConnection::WebDriverConnection(IPC::Transport transport, Web::PageClient& page_client)
|
||||||
: IPC::ConnectionToServer<WebDriverClientEndpoint, WebDriverServerEndpoint>(*this, move(socket))
|
: IPC::ConnectionToServer<WebDriverClientEndpoint, WebDriverServerEndpoint>(*this, move(transport))
|
||||||
{
|
{
|
||||||
set_current_top_level_browsing_context(page_client.page().top_level_browsing_context());
|
set_current_top_level_browsing_context(page_client.page().top_level_browsing_context());
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
#include <LibIPC/ConnectionToServer.h>
|
#include <LibIPC/ConnectionToServer.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
#include <LibJS/Heap/MarkedVector.h>
|
#include <LibJS/Heap/MarkedVector.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
@ -37,7 +38,7 @@ public:
|
||||||
void visit_edges(JS::Cell::Visitor&);
|
void visit_edges(JS::Cell::Visitor&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebDriverConnection(NonnullOwnPtr<Core::LocalSocket> socket, Web::PageClient& page_client);
|
WebDriverConnection(IPC::Transport transport, Web::PageClient& page_client);
|
||||||
|
|
||||||
virtual void die() override { }
|
virtual void die() override { }
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,8 @@ Session::~Session()
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<ServerPromise> promise)
|
ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<ServerPromise> promise)
|
||||||
{
|
{
|
||||||
|
static_assert(IsSame<IPC::Transport, IPC::TransportSocket>, "Need to handle other IPC transports here");
|
||||||
|
|
||||||
dbgln("Listening for WebDriver connection on {}", *m_web_content_socket_path);
|
dbgln("Listening for WebDriver connection on {}", *m_web_content_socket_path);
|
||||||
|
|
||||||
(void)Core::System::unlink(*m_web_content_socket_path);
|
(void)Core::System::unlink(*m_web_content_socket_path);
|
||||||
|
@ -64,7 +66,7 @@ ErrorOr<NonnullRefPtr<Core::LocalServer>> Session::create_server(NonnullRefPtr<S
|
||||||
server->listen(*m_web_content_socket_path);
|
server->listen(*m_web_content_socket_path);
|
||||||
|
|
||||||
server->on_accept = [this, promise](auto client_socket) {
|
server->on_accept = [this, promise](auto client_socket) {
|
||||||
auto maybe_connection = adopt_nonnull_ref_or_enomem(new (nothrow) WebContentConnection(move(client_socket)));
|
auto maybe_connection = adopt_nonnull_ref_or_enomem(new (nothrow) WebContentConnection(IPC::Transport(move(client_socket))));
|
||||||
if (maybe_connection.is_error()) {
|
if (maybe_connection.is_error()) {
|
||||||
promise->resolve(maybe_connection.release_error());
|
promise->resolve(maybe_connection.release_error());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
namespace WebDriver {
|
namespace WebDriver {
|
||||||
|
|
||||||
WebContentConnection::WebContentConnection(NonnullOwnPtr<Core::LocalSocket> socket)
|
WebContentConnection::WebContentConnection(IPC::Transport transport)
|
||||||
: IPC::ConnectionFromClient<WebDriverClientEndpoint, WebDriverServerEndpoint>(*this, move(socket), 1)
|
: IPC::ConnectionFromClient<WebDriverClientEndpoint, WebDriverServerEndpoint>(*this, move(transport), 1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibIPC/ConnectionFromClient.h>
|
#include <LibIPC/ConnectionFromClient.h>
|
||||||
|
#include <LibIPC/Transport.h>
|
||||||
#include <WebContent/WebDriverClientEndpoint.h>
|
#include <WebContent/WebDriverClientEndpoint.h>
|
||||||
#include <WebContent/WebDriverServerEndpoint.h>
|
#include <WebContent/WebDriverServerEndpoint.h>
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ class WebContentConnection
|
||||||
: public IPC::ConnectionFromClient<WebDriverClientEndpoint, WebDriverServerEndpoint> {
|
: public IPC::ConnectionFromClient<WebDriverClientEndpoint, WebDriverServerEndpoint> {
|
||||||
C_OBJECT_ABSTRACT(WebContentConnection)
|
C_OBJECT_ABSTRACT(WebContentConnection)
|
||||||
public:
|
public:
|
||||||
WebContentConnection(NonnullOwnPtr<Core::LocalSocket> socket);
|
explicit WebContentConnection(IPC::Transport transport);
|
||||||
|
|
||||||
Function<void()> on_close;
|
Function<void()> on_close;
|
||||||
Function<void(Web::WebDriver::Response)> on_script_executed;
|
Function<void(Web::WebDriver::Response)> on_script_executed;
|
||||||
|
|
|
@ -45,8 +45,8 @@ void ConnectionFromClient::request_file(Web::FileRequest request)
|
||||||
handle_file_return(0, IPC::File::adopt_file(file.release_value()), request_id);
|
handle_file_return(0, IPC::File::adopt_file(file.release_value()), request_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket)
|
ConnectionFromClient::ConnectionFromClient(IPC::Transport transport)
|
||||||
: IPC::ConnectionFromClient<WebWorkerClientEndpoint, WebWorkerServerEndpoint>(*this, move(socket), 1)
|
: IPC::ConnectionFromClient<WebWorkerClientEndpoint, WebWorkerServerEndpoint>(*this, move(transport), 1)
|
||||||
, m_page_host(PageHost::create(Web::Bindings::main_thread_vm(), *this))
|
, m_page_host(PageHost::create(Web::Bindings::main_thread_vm(), *this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
PageHost const& page_host() const { return *m_page_host; }
|
PageHost const& page_host() const { return *m_page_host; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
|
explicit ConnectionFromClient(IPC::Transport);
|
||||||
|
|
||||||
Web::Page& page();
|
Web::Page& page();
|
||||||
Web::Page const& page() const;
|
Web::Page const& page() const;
|
||||||
|
|
Loading…
Reference in a new issue