From 6b014489d406c31a727e88ca304e60513f832021 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 8 Nov 2022 10:03:07 -0500 Subject: [PATCH] WebContent: Add a very-empty WebDriver IPC class to WebContent This just sets up the infrastructure for the WebContent process to house WebDriver IPCs, and adds an IPC for WebContent to create the WebDriver connection. The WebDriverConnection class inside WebContent ultimately will contain most of what is currently in WebDriver::Session (so the copyright attributions are copied here as well). The socket created by WebDriver is currently /tmp/browser_webdriver (formatted with some IDs). This will be moved to the /tmp/webdriver folder, as WebDriver will create multiple sockets to communicate with both Browser and WebContent as the IPCs are iteratively moved to WebContent. That path is unveiled here, though it is unused as of this commit. --- Userland/Services/WebContent/CMakeLists.txt | 6 +++ .../WebContent/ConnectionFromClient.cpp | 9 +++++ .../WebContent/ConnectionFromClient.h | 1 + Userland/Services/WebContent/Forward.h | 1 + Userland/Services/WebContent/PageHost.cpp | 10 +++++ Userland/Services/WebContent/PageHost.h | 7 +++- .../Services/WebContent/WebContentServer.ipc | 2 + .../Services/WebContent/WebDriverClient.ipc | 2 + .../WebContent/WebDriverConnection.cpp | 37 +++++++++++++++++++ .../Services/WebContent/WebDriverConnection.h | 35 ++++++++++++++++++ .../Services/WebContent/WebDriverServer.ipc | 2 + Userland/Services/WebContent/main.cpp | 6 +++ 12 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Userland/Services/WebContent/WebDriverClient.ipc create mode 100644 Userland/Services/WebContent/WebDriverConnection.cpp create mode 100644 Userland/Services/WebContent/WebDriverConnection.h create mode 100644 Userland/Services/WebContent/WebDriverServer.ipc diff --git a/Userland/Services/WebContent/CMakeLists.txt b/Userland/Services/WebContent/CMakeLists.txt index 89a35a0643..3ea9a981eb 100644 --- a/Userland/Services/WebContent/CMakeLists.txt +++ b/Userland/Services/WebContent/CMakeLists.txt @@ -7,18 +7,24 @@ serenity_component( compile_ipc(WebContentServer.ipc WebContentServerEndpoint.h) compile_ipc(WebContentClient.ipc WebContentClientEndpoint.h) +compile_ipc(WebDriverClient.ipc WebDriverClientEndpoint.h) +compile_ipc(WebDriverServer.ipc WebDriverServerEndpoint.h) + set(SOURCES ConnectionFromClient.cpp ConsoleGlobalObject.cpp ImageCodecPluginSerenity.cpp PageHost.cpp WebContentConsoleClient.cpp + WebDriverConnection.cpp main.cpp ) set(GENERATED_SOURCES WebContentClientEndpoint.h WebContentServerEndpoint.h + WebDriverClientEndpoint.h + WebDriverServerEndpoint.h ) serenity_bin(WebContent) diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index d75fbb7f31..f4ab796d12 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -69,6 +69,15 @@ Web::Page const& ConnectionFromClient::page() const return m_page_host->page(); } +void ConnectionFromClient::connect_to_webdriver(String const& webdriver_ipc_path) +{ + // FIXME: Propogate this error back to the browser. + if (auto result = m_page_host->connect_to_webdriver(webdriver_ipc_path); result.is_error()) + dbgln("Unable to connect to the WebDriver process: {}", result.error()); + else + set_is_webdriver_active(true); +} + void ConnectionFromClient::update_system_theme(Core::AnonymousBuffer const& theme_buffer) { Gfx::set_system_theme(theme_buffer); diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 51cb3c4126..d71afb0095 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -45,6 +45,7 @@ private: Web::Page& page(); Web::Page const& page() const; + virtual void connect_to_webdriver(String const& webdriver_ipc_path) override; virtual void update_system_theme(Core::AnonymousBuffer const&) override; virtual void update_system_fonts(String const&, String const&, String const&) override; virtual void update_screen_rects(Vector const&, u32) override; diff --git a/Userland/Services/WebContent/Forward.h b/Userland/Services/WebContent/Forward.h index 05f02df860..b5fedefa07 100644 --- a/Userland/Services/WebContent/Forward.h +++ b/Userland/Services/WebContent/Forward.h @@ -12,5 +12,6 @@ class ConnectionFromClient; class ConsoleGlobalObject; class PageHost; class WebContentConsoleClient; +class WebDriverConnection; } diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index e979432f08..3992df2a62 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace WebContent { @@ -30,6 +31,8 @@ PageHost::PageHost(ConnectionFromClient& client) }); } +PageHost::~PageHost() = default; + void PageHost::set_has_focus(bool has_focus) { m_has_focus = has_focus; @@ -86,6 +89,13 @@ void PageHost::set_window_size(Gfx::IntSize const& size) page().set_window_size(size); } +ErrorOr PageHost::connect_to_webdriver(String const& webdriver_ipc_path) +{ + VERIFY(!m_webdriver); + m_webdriver = TRY(WebDriverConnection::connect(*this, webdriver_ipc_path)); + return {}; +} + Web::Layout::InitialContainingBlock* PageHost::layout_root() { auto* document = page().top_level_browsing_context().active_document(); diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h index 455d47fb26..f40222f958 100644 --- a/Userland/Services/WebContent/PageHost.h +++ b/Userland/Services/WebContent/PageHost.h @@ -9,6 +9,7 @@ #include #include +#include namespace WebContent { @@ -20,7 +21,7 @@ class PageHost final : public Web::PageClient { public: static NonnullOwnPtr create(ConnectionFromClient& client) { return adopt_own(*new PageHost(client)); } - virtual ~PageHost() = default; + virtual ~PageHost(); Web::Page& page() { return *m_page; } Web::Page const& page() const { return *m_page; } @@ -40,6 +41,8 @@ public: Gfx::IntSize const& content_size() const { return m_content_size; } + ErrorOr connect_to_webdriver(String const& webdriver_ipc_path); + private: // ^PageClient virtual Gfx::Palette palette() const override; @@ -90,6 +93,8 @@ private: RefPtr m_invalidation_coalescing_timer; Gfx::IntRect m_invalidation_rect; Web::CSS::PreferredColorScheme m_preferred_color_scheme { Web::CSS::PreferredColorScheme::Auto }; + + RefPtr m_webdriver; }; } diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index ce182d721a..3e065edf69 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -9,6 +9,8 @@ endpoint WebContentServer { + connect_to_webdriver(String webdriver_ipc_path) =| + update_system_theme(Core::AnonymousBuffer theme_buffer) =| update_system_fonts(String default_font_query, String fixed_width_font_query, String window_title_font_query) =| update_screen_rects(Vector rects, u32 main_screen_index) =| diff --git a/Userland/Services/WebContent/WebDriverClient.ipc b/Userland/Services/WebContent/WebDriverClient.ipc new file mode 100644 index 0000000000..6c11180cf7 --- /dev/null +++ b/Userland/Services/WebContent/WebDriverClient.ipc @@ -0,0 +1,2 @@ +endpoint WebDriverClient { +} diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp new file mode 100644 index 0000000000..dbc42c471c --- /dev/null +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, Florent Castelli + * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022, Tobias Christiansen + * Copyright (c) 2022, Linus Groh + * Copyright (c) 2022, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WebContent { + +ErrorOr> WebDriverConnection::connect(PageHost& page_host, String const& webdriver_ipc_path) +{ + dbgln_if(WEBDRIVER_DEBUG, "Trying to connect to {}", webdriver_ipc_path); + auto socket = TRY(Core::Stream::LocalSocket::connect(webdriver_ipc_path)); + + dbgln_if(WEBDRIVER_DEBUG, "Connected to WebDriver"); + return adopt_nonnull_ref_or_enomem(new (nothrow) WebDriverConnection(move(socket), page_host)); +} + +WebDriverConnection::WebDriverConnection(NonnullOwnPtr socket, PageHost& page_host) + : IPC::ConnectionToServer(*this, move(socket)) + , m_page_host(page_host) +{ +} + +} diff --git a/Userland/Services/WebContent/WebDriverConnection.h b/Userland/Services/WebContent/WebDriverConnection.h new file mode 100644 index 0000000000..f35f4663b8 --- /dev/null +++ b/Userland/Services/WebContent/WebDriverConnection.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, Florent Castelli + * Copyright (c) 2022, Linus Groh + * Copyright (c) 2022, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace WebContent { + +class WebDriverConnection final + : public IPC::ConnectionToServer { + C_OBJECT_ABSTRACT(WebDriverConnection) + +public: + static ErrorOr> connect(PageHost& page_host, String const& webdriver_ipc_path); + virtual ~WebDriverConnection() = default; + +private: + WebDriverConnection(NonnullOwnPtr socket, PageHost& page_host); + + virtual void die() override { } + + PageHost& m_page_host; +}; + +} diff --git a/Userland/Services/WebContent/WebDriverServer.ipc b/Userland/Services/WebContent/WebDriverServer.ipc new file mode 100644 index 0000000000..9305610d5a --- /dev/null +++ b/Userland/Services/WebContent/WebDriverServer.ipc @@ -0,0 +1,2 @@ +endpoint WebDriverServer { +} diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp index 1b7e33dbf3..51bb3930a9 100644 --- a/Userland/Services/WebContent/main.cpp +++ b/Userland/Services/WebContent/main.cpp @@ -7,6 +7,7 @@ #include "ImageCodecPluginSerenity.h" #include #include +#include #include #include #include @@ -23,6 +24,11 @@ ErrorOr serenity_main(Main::Arguments) { Core::EventLoop event_loop; TRY(Core::System::pledge("stdio recvfd sendfd accept unix rpath")); + + // This must be first; we can't check if /tmp/webdriver exists once we've unveiled other paths. + if (Core::Stream::File::exists("/tmp/webdriver"sv)) + TRY(Core::System::unveil("/tmp/webdriver", "rw")); + TRY(Core::System::unveil("/sys/kernel/processes", "r")); TRY(Core::System::unveil("/res", "r")); TRY(Core::System::unveil("/etc/timezone", "r"));