Files
ladybird/Services/WebDriver/Session.h
Aliaksandr Kalenik 1d025620e3 Everywhere: Move Mach bootstrap listener into LibIPC
Move MachPortServer from LibWebView into LibIPC as MachBootstrapListener
and move the Mach message structs from MachMessageTypes.h into LibIPC.

These types are IPC infrastructure, not UI or platform concerns.
Consolidating them in LibIPC keeps the Mach bootstrap handshake
self-contained in a single library and removes LibWebView's dependency
on LibThreading.
2026-03-24 19:51:52 +01:00

130 lines
4.4 KiB
C++

/*
* Copyright (c) 2022, Florent Castelli <florent.castelli@gmail.com>
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022-2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/JsonValue.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <AK/ScopeGuard.h>
#include <AK/String.h>
#include <LibCore/EventLoop.h>
#if !defined(AK_OS_MACOS)
# include <LibCore/LocalServer.h>
#else
# include <LibIPC/MachBootstrapListener.h>
# include <LibIPC/TransportBootstrapMach.h>
#endif
#include <LibCore/Process.h>
#include <LibCore/Promise.h>
#include <LibWeb/WebDriver/Capabilities.h>
#include <LibWeb/WebDriver/Error.h>
#include <LibWeb/WebDriver/Response.h>
#include <WebDriver/Client.h>
#include <WebDriver/WebContentConnection.h>
namespace WebDriver {
class Session : public RefCounted<Session> {
public:
static ErrorOr<NonnullRefPtr<Session>> create(NonnullRefPtr<Client> client, JsonObject& capabilities, Web::WebDriver::SessionFlags flags);
~Session();
enum class AllowInvalidWindowHandle {
No,
Yes,
};
static ErrorOr<NonnullRefPtr<Session>, Web::WebDriver::Error> find_session(StringView session_id, Web::WebDriver::SessionFlags = Web::WebDriver::SessionFlags::Default, AllowInvalidWindowHandle = AllowInvalidWindowHandle::No);
static size_t session_count(Web::WebDriver::SessionFlags);
struct Window {
String handle;
NonnullRefPtr<WebContentConnection> web_content_connection;
};
WebContentConnection& web_content_connection() const
{
auto current_window = m_windows.get(m_current_window_handle);
VERIFY(current_window.has_value());
return current_window->web_content_connection;
}
void close();
String session_id() const { return m_session_id; }
Web::WebDriver::SessionFlags session_flags() const { return m_session_flags; }
String const& current_window_handle() const { return m_current_window_handle; }
bool has_window_handle(StringView handle) const { return m_windows.contains(handle); }
Web::WebDriver::Response set_timeouts(JsonValue);
Web::WebDriver::Response close_window();
Web::WebDriver::Response switch_to_window(StringView);
Web::WebDriver::Response get_window_handles() const;
ErrorOr<void, Web::WebDriver::Error> ensure_current_window_handle_is_valid() const;
template<typename Action>
Web::WebDriver::Response perform_async_action(Action&& action)
{
Optional<Web::WebDriver::Response> response;
auto& connection = web_content_connection();
ScopeGuard guard { [&]() { connection.on_driver_execution_complete = nullptr; } };
connection.on_driver_execution_complete = [&](auto result) { response = move(result); };
TRY(action(connection));
Core::EventLoop::current().spin_until([&]() {
return response.has_value();
});
return response.release_value();
}
private:
Session(NonnullRefPtr<Client> client, JsonObject const& capabilities, String session_id, Web::WebDriver::SessionFlags flags);
using ServerPromise = Core::Promise<ErrorOr<void>>;
ErrorOr<void> start(LaunchBrowserCallback const&);
ErrorOr<void> accept_web_content_transport(NonnullOwnPtr<IPC::Transport>, NonnullRefPtr<ServerPromise> promise);
ErrorOr<void> create_server(NonnullRefPtr<ServerPromise> promise);
NonnullRefPtr<Client> m_client;
Web::WebDriver::LadybirdOptions m_options;
String m_session_id;
Web::WebDriver::SessionFlags m_session_flags { Web::WebDriver::SessionFlags::Default };
HashMap<String, Window> m_windows;
String m_current_window_handle;
HashMap<u64, NonnullRefPtr<WebContentConnection>> m_pending_connections;
u64 m_next_pending_connection_id { 0 };
ByteString m_web_content_endpoint;
Optional<Core::Process> m_browser_process;
NonnullRefPtr<Core::WeakEventLoopReference> m_event_loop;
#if defined(AK_OS_MACOS)
OwnPtr<IPC::MachBootstrapListener> m_web_content_mach_port_server;
IPC::TransportBootstrapMachServer m_transport_bootstrap_server;
#else
RefPtr<Core::LocalServer> m_web_content_server;
#endif
Web::WebDriver::PageLoadStrategy m_page_load_strategy { Web::WebDriver::PageLoadStrategy::Normal };
Optional<JsonValue> m_timeouts_configuration;
bool m_strict_file_interactiblity { false };
};
}