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"));