| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2022, Dex♪ <dexes.ttp@gmail.com> | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |  * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #include <AK/Platform.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(AK_OS_SERENITY)
 | 
					
						
							|  |  |  | #    define AK_DONT_REPLACE_STD
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <AK/Badge.h>
 | 
					
						
							|  |  |  | #include <AK/DeprecatedString.h>
 | 
					
						
							| 
									
										
										
										
											2022-07-18 20:23:19 +02:00
										 |  |  | #include <AK/LexicalPath.h>
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | #include <AK/NonnullOwnPtr.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-13 07:50:26 -04:00
										 |  |  | #include <AK/String.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #include <AK/URL.h>
 | 
					
						
							|  |  |  | #include <AK/Vector.h>
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | #include <LibCore/ArgsParser.h>
 | 
					
						
							| 
									
										
										
										
											2023-02-08 21:08:01 +01:00
										 |  |  | #include <LibCore/DeprecatedFile.h>
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | #include <LibCore/EventLoop.h>
 | 
					
						
							|  |  |  | #include <LibCore/Timer.h>
 | 
					
						
							|  |  |  | #include <LibGfx/Bitmap.h>
 | 
					
						
							|  |  |  | #include <LibGfx/Font/FontDatabase.h>
 | 
					
						
							|  |  |  | #include <LibGfx/PNGWriter.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #include <LibGfx/Point.h>
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | #include <LibGfx/Rect.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #include <LibGfx/ShareableBitmap.h>
 | 
					
						
							|  |  |  | #include <LibGfx/Size.h>
 | 
					
						
							|  |  |  | #include <LibGfx/StandardCursor.h>
 | 
					
						
							|  |  |  | #include <LibGfx/SystemTheme.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Cookie/Cookie.h>
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | #include <LibWeb/Cookie/ParsedCookie.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #include <LibWeb/Loader/FrameLoader.h>
 | 
					
						
							|  |  |  | #include <LibWebView/ViewImplementation.h>
 | 
					
						
							|  |  |  | #include <LibWebView/WebContentClient.h>
 | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #if !defined(AK_OS_SERENITY)
 | 
					
						
							|  |  |  | #    include <Ladybird/HelperProcess.h>
 | 
					
						
							|  |  |  | #    include <QCoreApplication>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | class HeadlessWebContentView final : public WebView::ViewImplementation { | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     static ErrorOr<NonnullOwnPtr<HeadlessWebContentView>> create(Core::AnonymousBuffer theme, Gfx::IntSize const& window_size, StringView web_driver_ipc_path) | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |         auto view = TRY(adopt_nonnull_own_or_enomem(new (nothrow) HeadlessWebContentView())); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #if defined(AK_OS_SERENITY)
 | 
					
						
							|  |  |  |         view->m_client_state.client = TRY(WebView::WebContentClient::try_create(*view)); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:20:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |         if (!web_driver_ipc_path.is_empty()) | 
					
						
							|  |  |  |             view->client().async_connect_to_webdriver(web_driver_ipc_path); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         auto candidate_web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv)); | 
					
						
							|  |  |  |         view->m_client_state.client = TRY(view->launch_web_content_process(candidate_web_content_paths, web_driver_ipc_path)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:20:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |         view->client().async_update_system_theme(move(theme)); | 
					
						
							|  |  |  |         view->client().async_update_system_fonts(Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query()); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:20:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |         view->client().async_set_viewport_rect({ { 0, 0 }, window_size }); | 
					
						
							|  |  |  |         view->client().async_set_window_size(window_size); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:20:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |         return view; | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     RefPtr<Gfx::Bitmap> take_screenshot() | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |         return client().take_document_screenshot().bitmap(); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     HeadlessWebContentView() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void notify_server_did_layout(Badge<WebView::WebContentClient>, Gfx::IntSize) override { } | 
					
						
							|  |  |  |     void notify_server_did_paint(Badge<WebView::WebContentClient>, i32) override { } | 
					
						
							|  |  |  |     void notify_server_did_invalidate_content_rect(Badge<WebView::WebContentClient>, Gfx::IntRect const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_change_selection(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_cursor_change(Badge<WebView::WebContentClient>, Gfx::StandardCursor) override { } | 
					
						
							|  |  |  |     void notify_server_did_change_title(Badge<WebView::WebContentClient>, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_scroll(Badge<WebView::WebContentClient>, i32, i32) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_scroll_to(Badge<WebView::WebContentClient>, Gfx::IntPoint) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_scroll_into_view(Badge<WebView::WebContentClient>, Gfx::IntRect const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_enter_tooltip_area(Badge<WebView::WebContentClient>, Gfx::IntPoint, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_leave_tooltip_area(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_hover_link(Badge<WebView::WebContentClient>, const URL&) override { } | 
					
						
							|  |  |  |     void notify_server_did_unhover_link(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_click_link(Badge<WebView::WebContentClient>, const URL&, DeprecatedString const&, unsigned) override { } | 
					
						
							|  |  |  |     void notify_server_did_middle_click_link(Badge<WebView::WebContentClient>, const URL&, DeprecatedString const&, unsigned) override { } | 
					
						
							|  |  |  |     void notify_server_did_start_loading(Badge<WebView::WebContentClient>, const URL&, bool) override { } | 
					
						
							|  |  |  |     void notify_server_did_finish_loading(Badge<WebView::WebContentClient>, const URL&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_navigate_back(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_navigate_forward(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_refresh(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_context_menu(Badge<WebView::WebContentClient>, Gfx::IntPoint) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_link_context_menu(Badge<WebView::WebContentClient>, Gfx::IntPoint, const URL&, DeprecatedString const&, unsigned) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_image_context_menu(Badge<WebView::WebContentClient>, Gfx::IntPoint, const URL&, DeprecatedString const&, unsigned, Gfx::ShareableBitmap const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_alert(Badge<WebView::WebContentClient>, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_confirm(Badge<WebView::WebContentClient>, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_prompt(Badge<WebView::WebContentClient>, DeprecatedString const&, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_set_prompt_text(Badge<WebView::WebContentClient>, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_accept_dialog(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_dismiss_dialog(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_get_source(const URL&, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_get_dom_tree(DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_get_dom_node_properties(i32, DeprecatedString const&, DeprecatedString const&, DeprecatedString const&, DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_get_accessibility_tree(DeprecatedString const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_output_js_console_message(i32) override { } | 
					
						
							|  |  |  |     void notify_server_did_get_js_console_messages(i32, Vector<DeprecatedString> const&, Vector<DeprecatedString> const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_change_favicon(Gfx::Bitmap const&) override { } | 
					
						
							|  |  |  |     Vector<Web::Cookie::Cookie> notify_server_did_request_all_cookies(Badge<WebView::WebContentClient>, URL const&) override { return {}; } | 
					
						
							|  |  |  |     Optional<Web::Cookie::Cookie> notify_server_did_request_named_cookie(Badge<WebView::WebContentClient>, URL const&, DeprecatedString const&) override { return {}; } | 
					
						
							|  |  |  |     DeprecatedString notify_server_did_request_cookie(Badge<WebView::WebContentClient>, const URL&, Web::Cookie::Source) override { return {}; } | 
					
						
							|  |  |  |     void notify_server_did_set_cookie(Badge<WebView::WebContentClient>, const URL&, Web::Cookie::ParsedCookie const&, Web::Cookie::Source) override { } | 
					
						
							|  |  |  |     void notify_server_did_update_cookie(Badge<WebView::WebContentClient>, Web::Cookie::Cookie const&) override { } | 
					
						
							|  |  |  |     void notify_server_did_close_browsing_context(Badge<WebView::WebContentClient>) override { } | 
					
						
							|  |  |  |     void notify_server_did_update_resource_count(i32) override { } | 
					
						
							|  |  |  |     void notify_server_did_request_restore_window() override { } | 
					
						
							|  |  |  |     Gfx::IntPoint notify_server_did_request_reposition_window(Gfx::IntPoint) override { return {}; } | 
					
						
							|  |  |  |     Gfx::IntSize notify_server_did_request_resize_window(Gfx::IntSize) override { return {}; } | 
					
						
							|  |  |  |     Gfx::IntRect notify_server_did_request_maximize_window() override { return {}; } | 
					
						
							|  |  |  |     Gfx::IntRect notify_server_did_request_minimize_window() override { return {}; } | 
					
						
							|  |  |  |     Gfx::IntRect notify_server_did_request_fullscreen_window() override { return {}; } | 
					
						
							|  |  |  |     void notify_server_did_request_file(Badge<WebView::WebContentClient>, DeprecatedString const&, i32) override { } | 
					
						
							|  |  |  |     void notify_server_did_finish_handling_input_event(bool) override { } | 
					
						
							|  |  |  |     void update_zoom() override { } | 
					
						
							|  |  |  |     void create_client() override { } | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | static ErrorOr<NonnullRefPtr<Core::Timer>> load_page_for_screenshot_and_exit(Core::EventLoop& event_loop, HeadlessWebContentView& view, int screenshot_timeout) | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     // FIXME: Allow passing the output path as an argument.
 | 
					
						
							|  |  |  |     static constexpr auto output_file_path = "output.png"sv; | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     if (Core::DeprecatedFile::exists(output_file_path)) | 
					
						
							|  |  |  |         TRY(Core::DeprecatedFile::remove(output_file_path, Core::DeprecatedFile::RecursionMode::Disallowed)); | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     outln("Taking screenshot after {} seconds", screenshot_timeout); | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     auto timer = TRY(Core::Timer::create_single_shot( | 
					
						
							|  |  |  |         screenshot_timeout * 1000, | 
					
						
							|  |  |  |         [&]() { | 
					
						
							|  |  |  |             if (auto screenshot = view.take_screenshot()) { | 
					
						
							|  |  |  |                 outln("Saving screenshot to {}", output_file_path); | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |                 auto output_file = MUST(Core::File::open(output_file_path, Core::File::OpenMode::Write)); | 
					
						
							|  |  |  |                 auto image_buffer = MUST(Gfx::PNGWriter::encode(*screenshot)); | 
					
						
							|  |  |  |                 MUST(output_file->write(image_buffer.bytes())); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 warnln("No screenshot available"); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |             event_loop.quit(0); | 
					
						
							|  |  |  |         })); | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     timer->start(); | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     return timer; | 
					
						
							| 
									
										
										
										
											2022-11-21 20:03:45 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 07:50:26 -04:00
										 |  |  | static ErrorOr<URL> format_url(StringView url) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     URL formatted_url { url }; | 
					
						
							|  |  |  |     if (!formatted_url.is_valid()) | 
					
						
							|  |  |  |         formatted_url = TRY(String::formatted("http://{}", url)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return formatted_url; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | ErrorOr<int> serenity_main(Main::Arguments arguments) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  | #if !defined(AK_OS_SERENITY)
 | 
					
						
							|  |  |  |     QCoreApplication app(arguments.argc, arguments.argv); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     Core::EventLoop event_loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int screenshot_timeout = 1; | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     StringView url; | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     auto resources_folder = "/res"sv; | 
					
						
							|  |  |  |     StringView web_driver_ipc_path; | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Core::ArgsParser args_parser; | 
					
						
							|  |  |  |     args_parser.set_general_help("This utility runs the Browser in headless mode."); | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     args_parser.add_option(screenshot_timeout, "Take a screenshot after [n] seconds (default: 1)", "screenshot", 's', "n"); | 
					
						
							| 
									
										
										
										
											2022-07-18 20:23:19 +02:00
										 |  |  |     args_parser.add_option(resources_folder, "Path of the base resources folder (defaults to /res)", "resources", 'r', "resources-root-path"); | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     args_parser.add_option(web_driver_ipc_path, "Path to the WebDriver IPC socket", "webdriver-ipc-path", 0, "path"); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     args_parser.add_positional_argument(url, "URL to open", "url", Core::ArgsParser::Required::Yes); | 
					
						
							|  |  |  |     args_parser.parse(arguments); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Gfx::FontDatabase::set_default_font_query("Katica 10 400 0"); | 
					
						
							| 
									
										
										
										
											2022-07-31 18:41:07 +02:00
										 |  |  |     Gfx::FontDatabase::set_window_title_font_query("Katica 10 700 0"); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  |     Gfx::FontDatabase::set_fixed_width_font_query("Csilla 10 400 0"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     auto fonts_path = LexicalPath::join(resources_folder, "fonts"sv); | 
					
						
							|  |  |  |     Gfx::FontDatabase::set_default_fonts_lookup_path(fonts_path.string()); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     auto theme_path = LexicalPath::join(resources_folder, "themes"sv, "Default.ini"sv); | 
					
						
							|  |  |  |     auto theme = TRY(Gfx::load_system_theme(theme_path.string())); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     // FIXME: Allow passing the window size as an argument.
 | 
					
						
							|  |  |  |     static constexpr Gfx::IntSize window_size { 800, 600 }; | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     auto view = TRY(HeadlessWebContentView::create(move(theme), window_size, web_driver_ipc_path)); | 
					
						
							| 
									
										
										
										
											2023-03-13 07:50:26 -04:00
										 |  |  |     view->load(TRY(format_url(url))); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-12 12:38:15 -04:00
										 |  |  |     RefPtr<Core::Timer> timer; | 
					
						
							|  |  |  |     if (web_driver_ipc_path.is_empty()) | 
					
						
							|  |  |  |         timer = TRY(load_page_for_screenshot_and_exit(event_loop, *view, screenshot_timeout)); | 
					
						
							| 
									
										
										
										
											2022-04-03 18:15:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return event_loop.exec(); | 
					
						
							|  |  |  | } |