From 4ede2cdf18e33baf32e3e0f993a192b96a902b72 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Wed, 15 Oct 2025 13:17:37 +0100 Subject: [PATCH] LibWebView+WebContent: Allow setting the default time zone This is used by tests to set the default time zone to UTC. This is because certain tests create JavaScript Date objects, which are in the current timezone. --- Libraries/LibWebView/Application.cpp | 3 +++ Libraries/LibWebView/HelperProcess.cpp | 5 +++++ Libraries/LibWebView/Options.h | 1 + Meta/WPT.sh | 1 + Services/WebContent/main.cpp | 8 ++++++++ Services/WebDriver/main.cpp | 9 +++++++-- Tests/LibWeb/test-web/Application.cpp | 3 +++ 7 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index b3c45ed8743..6f3dd570a91 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -109,6 +109,7 @@ ErrorOr Application::initialize(Main::Arguments const& arguments) Optional webdriver_content_ipc_path; Optional user_agent_preset; Optional dns_server_address; + Optional default_time_zone; Optional dns_server_port; bool use_dns_over_tls = false; bool layout_test_mode = false; @@ -178,6 +179,7 @@ ErrorOr Application::initialize(Main::Arguments const& arguments) args_parser.add_option(dns_server_port, "Set the DNS server port", "dns-port", 0, "port (default: 53 or 853 if --dot)"); args_parser.add_option(use_dns_over_tls, "Use DNS over TLS", "dot"); args_parser.add_option(validate_dnssec_locally, "Validate DNSSEC locally", "dnssec"); + args_parser.add_option(default_time_zone, "Default time zone", "default-time-zone", 0, "time-zone-id"); args_parser.add_option(Core::ArgsParser::Option { .argument_mode = Core::ArgsParser::OptionArgumentMode::Optional, @@ -276,6 +278,7 @@ ErrorOr Application::initialize(Main::Arguments const& arguments) .enable_autoplay = enable_autoplay ? EnableAutoplay::Yes : EnableAutoplay::No, .collect_garbage_on_every_allocation = collect_garbage_on_every_allocation ? CollectGarbageOnEveryAllocation::Yes : CollectGarbageOnEveryAllocation::No, .paint_viewport_scrollbars = disable_scrollbar_painting ? PaintViewportScrollbars::No : PaintViewportScrollbars::Yes, + .default_time_zone = default_time_zone, }; create_platform_options(m_browser_options, m_web_content_options); diff --git a/Libraries/LibWebView/HelperProcess.cpp b/Libraries/LibWebView/HelperProcess.cpp index b97d0527f96..a72116ae2e3 100644 --- a/Libraries/LibWebView/HelperProcess.cpp +++ b/Libraries/LibWebView/HelperProcess.cpp @@ -128,6 +128,11 @@ static ErrorOr> launch_web_content_proc arguments.append(ByteString::number(maybe_echo_server_port.value())); } + if (web_content_options.default_time_zone.has_value()) { + arguments.append("--default-time-zone"); + arguments.append(web_content_options.default_time_zone.value()); + } + if (auto server = mach_server_name(); server.has_value()) { arguments.append("--mach-server-name"sv); arguments.append(server.value()); diff --git a/Libraries/LibWebView/Options.h b/Libraries/LibWebView/Options.h index 1b117185512..9776e628d1a 100644 --- a/Libraries/LibWebView/Options.h +++ b/Libraries/LibWebView/Options.h @@ -169,6 +169,7 @@ struct WebContentOptions { CollectGarbageOnEveryAllocation collect_garbage_on_every_allocation { CollectGarbageOnEveryAllocation::No }; Optional echo_server_port {}; PaintViewportScrollbars paint_viewport_scrollbars { PaintViewportScrollbars::Yes }; + Optional default_time_zone {}; }; } diff --git a/Meta/WPT.sh b/Meta/WPT.sh index 1ee4cfcbf9a..54f2a1dff6f 100755 --- a/Meta/WPT.sh +++ b/Meta/WPT.sh @@ -85,6 +85,7 @@ WPT_ARGS=( "--webdriver-binary=${WEBDRIVER_BINARY}" "--install-webdriver" "--webdriver-arg=--force-cpu-painting" + "--webdriver-arg=--default-time-zone=UTC" "--no-pause-after-test" "--install-fonts" "${EXTRA_WPT_ARGS[@]}" diff --git a/Services/WebContent/main.cpp b/Services/WebContent/main.cpp index 938f02317cc..60c61a31956 100644 --- a/Services/WebContent/main.cpp +++ b/Services/WebContent/main.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,7 @@ ErrorOr ladybird_main(Main::Arguments arguments) bool is_headless = false; bool disable_scrollbar_painting = false; StringView echo_server_port_string_view {}; + StringView default_time_zone {}; Core::ArgsParser args_parser; args_parser.add_option(command_line, "Browser process command line", "command-line", 0, "command_line"); @@ -129,6 +131,7 @@ ErrorOr ladybird_main(Main::Arguments arguments) args_parser.add_option(disable_scrollbar_painting, "Don't paint horizontal or vertical viewport scrollbars", "disable-scrollbar-painting"); 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.add_option(default_time_zone, "Default time zone", "default-time-zone", 0, "time-zone-id"); args_parser.parse(arguments); @@ -136,6 +139,11 @@ ErrorOr ladybird_main(Main::Arguments arguments) Core::Process::wait_for_debugger_and_break(); } + if (!default_time_zone.is_empty()) { + if (auto result = Unicode::set_current_time_zone(default_time_zone); result.is_error()) + dbgln("Failed to set default time zone: {}", result.error()); + } + auto& font_provider = static_cast(Gfx::FontDatabase::the().install_system_font_provider(make())); if (force_fontconfig) { font_provider.set_name_but_fixme_should_create_custom_system_font_provider("FontConfig"_string); diff --git a/Services/WebDriver/main.cpp b/Services/WebDriver/main.cpp index e28d2af9235..a363514db83 100644 --- a/Services/WebDriver/main.cpp +++ b/Services/WebDriver/main.cpp @@ -33,7 +33,7 @@ static ErrorOr launch_process(StringView application, ReadonlySpa return result; } -static Vector create_arguments(ByteString const& socket_path, bool headless, bool force_cpu_painting, Optional debug_process) +static Vector create_arguments(ByteString const& socket_path, bool headless, bool force_cpu_painting, Optional debug_process, Optional default_time_zone) { Vector arguments { "--webdriver-content-path"sv, @@ -59,6 +59,9 @@ static Vector create_arguments(ByteString const& socket_path, bool h if (debug_process.has_value()) arguments.append(ByteString::formatted("--debug-process={}", debug_process.value())); + if (default_time_zone.has_value()) + arguments.append(ByteString::formatted("--default-time-zone={}", default_time_zone.value())); + // FIXME: WebDriver does not yet handle the WebContent process switch brought by site isolation. arguments.append("--disable-site-isolation"sv); @@ -75,6 +78,7 @@ ErrorOr ladybird_main(Main::Arguments arguments) bool force_cpu_painting = false; bool headless = false; Optional debug_process; + Optional default_time_zone; Core::ArgsParser args_parser; args_parser.add_option(listen_address, "IP address to listen on", "listen-address", 'l', "listen_address"); @@ -83,6 +87,7 @@ ErrorOr ladybird_main(Main::Arguments arguments) args_parser.add_option(force_cpu_painting, "Launch browser with GPU painting disabled", "force-cpu-painting"); args_parser.add_option(debug_process, "Wait for a debugger to attach to the given process name (WebContent, RequestServer, etc.)", "debug-process", 0, "process-name"); args_parser.add_option(headless, "Launch browser without a graphical interface", "headless"); + args_parser.add_option(default_time_zone, "Default time zone", "default-time-zone", 0, "time-zone-id"); args_parser.parse(arguments); auto ipv4_address = IPv4Address::from_string(listen_address); @@ -123,7 +128,7 @@ ErrorOr ladybird_main(Main::Arguments arguments) } auto launch_browser_callback = [&](ByteString const& socket_path, bool headless) { - auto arguments = create_arguments(socket_path, headless, force_cpu_painting, debug_process); + auto arguments = create_arguments(socket_path, headless, force_cpu_painting, debug_process, default_time_zone); return launch_process("Ladybird"sv, arguments.span()); }; diff --git a/Tests/LibWeb/test-web/Application.cpp b/Tests/LibWeb/test-web/Application.cpp index fb7433f7538..ba047696df8 100644 --- a/Tests/LibWeb/test-web/Application.cpp +++ b/Tests/LibWeb/test-web/Application.cpp @@ -73,6 +73,9 @@ void Application::create_platform_options(WebView::BrowserOptions& browser_optio // Ensure tests are resilient to minor changes to the viewport scrollbar. web_content_options.paint_viewport_scrollbars = WebView::PaintViewportScrollbars::No; + // Ensure consistent time zone operations across different machine configurations. + web_content_options.default_time_zone = "UTC"sv; + if (dump_gc_graph) { // Force all tests to run in serial if we are interested in the GC graph. test_concurrency = 1;