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 89a35a0643c..3ea9a981ebf 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 d75fbb7f31b..f4ab796d124 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 51cb3c41267..d71afb00950 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 05f02df860c..b5fedefa072 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 e979432f08e..3992df2a622 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 455d47fb26b..f40222f9586 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 ce182d721a7..3e065edf690 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 00000000000..6c11180cf72 --- /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 00000000000..dbc42c471c6 --- /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 00000000000..f35f4663b81 --- /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 00000000000..9305610d5a0 --- /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 1b7e33dbf38..51bb3930a96 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"));