From e764df15eb5271e19507a8a345e139d4012cb620 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Mon, 9 Dec 2024 21:51:19 +0000 Subject: [PATCH] LibWebView+WebContent: Inform WebContent process if browser is headless --- Libraries/LibWeb/Page/Page.h | 2 ++ Libraries/LibWeb/SVG/SVGDecodedImageData.h | 1 + Libraries/LibWebView/HelperProcess.cpp | 2 ++ Libraries/LibWebView/Options.h | 6 ++++++ Services/WebContent/PageClient.cpp | 11 +++++++++++ Services/WebContent/PageClient.h | 3 +++ Services/WebContent/main.cpp | 4 ++++ Services/WebWorker/PageHost.h | 1 + UI/Headless/Application.cpp | 1 + 9 files changed, 31 insertions(+) diff --git a/Libraries/LibWeb/Page/Page.h b/Libraries/LibWeb/Page/Page.h index 4e0f7dfa915..36999ca1159 100644 --- a/Libraries/LibWeb/Page/Page.h +++ b/Libraries/LibWeb/Page/Page.h @@ -407,6 +407,8 @@ public: virtual DisplayListPlayerType display_list_player_type() const = 0; + virtual bool is_headless() const = 0; + protected: virtual ~PageClient() = default; }; diff --git a/Libraries/LibWeb/SVG/SVGDecodedImageData.h b/Libraries/LibWeb/SVG/SVGDecodedImageData.h index cabe0683739..f11fafbcfba 100644 --- a/Libraries/LibWeb/SVG/SVGDecodedImageData.h +++ b/Libraries/LibWeb/SVG/SVGDecodedImageData.h @@ -82,6 +82,7 @@ public: virtual bool is_ready_to_paint() const override { return true; } virtual DisplayListPlayerType display_list_player_type() const override { return m_host_page->client().display_list_player_type(); } + virtual bool is_headless() const override { return m_host_page->client().is_headless(); } private: explicit SVGPageClient(Page& host_page) diff --git a/Libraries/LibWebView/HelperProcess.cpp b/Libraries/LibWebView/HelperProcess.cpp index a40b060bd52..a22cabba501 100644 --- a/Libraries/LibWebView/HelperProcess.cpp +++ b/Libraries/LibWebView/HelperProcess.cpp @@ -108,6 +108,8 @@ ErrorOr> launch_web_content_process( arguments.append("--force-fontconfig"sv); if (web_content_options.collect_garbage_on_every_allocation == WebView::CollectGarbageOnEveryAllocation::Yes) arguments.append("--collect-garbage-on-every-allocation"sv); + if (web_content_options.is_headless == WebView::IsHeadless::Yes) + arguments.append("--headless"sv); if (auto const maybe_echo_server_port = web_content_options.echo_server_port; maybe_echo_server_port.has_value()) { arguments.append("--echo-server-port"sv); diff --git a/Libraries/LibWebView/Options.h b/Libraries/LibWebView/Options.h index 75fc8b4447d..bea15cd8ba8 100644 --- a/Libraries/LibWebView/Options.h +++ b/Libraries/LibWebView/Options.h @@ -113,6 +113,11 @@ enum class CollectGarbageOnEveryAllocation { Yes, }; +enum class IsHeadless { + No, + Yes, +}; + struct WebContentOptions { String command_line; String executable_path; @@ -128,6 +133,7 @@ struct WebContentOptions { EnableAutoplay enable_autoplay { EnableAutoplay::No }; CollectGarbageOnEveryAllocation collect_garbage_on_every_allocation { CollectGarbageOnEveryAllocation::No }; Optional echo_server_port {}; + IsHeadless is_headless { IsHeadless::No }; }; } diff --git a/Services/WebContent/PageClient.cpp b/Services/WebContent/PageClient.cpp index 05091c8a7e3..8b12b251ec7 100644 --- a/Services/WebContent/PageClient.cpp +++ b/Services/WebContent/PageClient.cpp @@ -32,6 +32,7 @@ namespace WebContent { static PageClient::UseSkiaPainter s_use_skia_painter = PageClient::UseSkiaPainter::GPUBackendIfAvailable; +static bool s_is_headless { false }; GC_DEFINE_ALLOCATOR(PageClient); @@ -40,6 +41,16 @@ void PageClient::set_use_skia_painter(UseSkiaPainter use_skia_painter) s_use_skia_painter = use_skia_painter; } +bool PageClient::is_headless() const +{ + return s_is_headless; +} + +void PageClient::set_is_headless(bool is_headless) +{ + s_is_headless = is_headless; +} + GC::Ref PageClient::create(JS::VM& vm, PageHost& page_host, u64 id) { return vm.heap().allocate(page_host, id); diff --git a/Services/WebContent/PageClient.h b/Services/WebContent/PageClient.h index f8680b11d5b..28d8e052708 100644 --- a/Services/WebContent/PageClient.h +++ b/Services/WebContent/PageClient.h @@ -34,6 +34,9 @@ public: }; static void set_use_skia_painter(UseSkiaPainter); + virtual bool is_headless() const override; + static void set_is_headless(bool); + virtual bool is_ready_to_paint() const override; virtual Web::Page& page() override { return *m_page; } diff --git a/Services/WebContent/main.cpp b/Services/WebContent/main.cpp index 2a8ca2a2f10..92eb07f9198 100644 --- a/Services/WebContent/main.cpp +++ b/Services/WebContent/main.cpp @@ -107,6 +107,7 @@ ErrorOr serenity_main(Main::Arguments arguments) bool force_cpu_painting = false; bool force_fontconfig = false; bool collect_garbage_on_every_allocation = false; + bool is_headless = false; StringView echo_server_port_string_view {}; Core::ArgsParser args_parser; @@ -127,6 +128,7 @@ ErrorOr serenity_main(Main::Arguments arguments) args_parser.add_option(force_fontconfig, "Force using fontconfig for font loading", "force-fontconfig"); args_parser.add_option(collect_garbage_on_every_allocation, "Collect garbage after every JS heap allocation", "collect-garbage-on-every-allocation"); args_parser.add_option(echo_server_port_string_view, "Echo server port used in test internals", "echo-server-port", 0, "echo_server_port"); + args_parser.add_option(is_headless, "Report that the browser is running in headless mode", "headless"); args_parser.parse(arguments); @@ -152,6 +154,8 @@ ErrorOr serenity_main(Main::Arguments arguments) // Always use the CPU backend for layout tests, as the GPU backend is not deterministic WebContent::PageClient::set_use_skia_painter(force_cpu_painting ? WebContent::PageClient::UseSkiaPainter::CPUBackend : WebContent::PageClient::UseSkiaPainter::GPUBackendIfAvailable); + WebContent::PageClient::set_is_headless(is_headless); + if (enable_http_cache) { Web::Fetch::Fetching::g_http_cache_enabled = true; } diff --git a/Services/WebWorker/PageHost.h b/Services/WebWorker/PageHost.h index dc2ea373b72..86a008e1aad 100644 --- a/Services/WebWorker/PageHost.h +++ b/Services/WebWorker/PageHost.h @@ -37,6 +37,7 @@ public: virtual void request_file(Web::FileRequest) override; virtual bool is_ready_to_paint() const override { return true; } virtual Web::DisplayListPlayerType display_list_player_type() const override { VERIFY_NOT_REACHED(); } + virtual bool is_headless() const override { VERIFY_NOT_REACHED(); } private: explicit PageHost(ConnectionFromClient&); diff --git a/UI/Headless/Application.cpp b/UI/Headless/Application.cpp index 35f5ab0db6e..cd1103825d2 100644 --- a/UI/Headless/Application.cpp +++ b/UI/Headless/Application.cpp @@ -85,6 +85,7 @@ void Application::create_platform_options(WebView::ChromeOptions& chrome_options } web_content_options.is_layout_test_mode = is_layout_test_mode ? WebView::IsLayoutTestMode::Yes : WebView::IsLayoutTestMode::No; + web_content_options.is_headless = WebView::IsHeadless::Yes; } ErrorOr Application::launch_test_fixtures()