From 5062ba347be5968108700a9bb5f855a3ac7a8ab8 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Tue, 1 Aug 2023 11:56:10 -0600 Subject: [PATCH] Ladybird+LibWebView: Move Lagom code to Ladybird, Qt code to Utilities Re-organize our helper files here a bit, to make a clearer distinction between Qt-specific helpers and generic non-serenity helpers. A future commit will move Lagom specific code from LibSQL to ladybird as well, so that we can see about future generic apis for spawning helper procesess. --- Ladybird/HelperProcess.cpp | 85 ++++++++++++++++--- Ladybird/HelperProcess.h | 11 ++- Ladybird/Utilities.cpp | 13 +++ Ladybird/Utilities.h | 3 + Ladybird/WebContentView.cpp | 2 +- Ladybird/WebDriver/CMakeLists.txt | 1 - Meta/gn/secondary/Ladybird/WebDriver/BUILD.gn | 1 - .../LibWebView/ViewImplementation.cpp | 78 ----------------- .../Libraries/LibWebView/ViewImplementation.h | 4 - Userland/Utilities/headless-browser.cpp | 3 +- 10 files changed, 101 insertions(+), 100 deletions(-) diff --git a/Ladybird/HelperProcess.cpp b/Ladybird/HelperProcess.cpp index 57116233c9..ee2fddcd7b 100644 --- a/Ladybird/HelperProcess.cpp +++ b/Ladybird/HelperProcess.cpp @@ -5,18 +5,81 @@ */ #include "HelperProcess.h" -#include "Utilities.h" -#include -ErrorOr> get_paths_for_helper_process(StringView process_name) +ErrorOr> launch_web_content_process(WebView::ViewImplementation& view, + ReadonlySpan candidate_web_content_paths, + WebView::EnableCallgrindProfiling enable_callgrind_profiling, + WebView::IsLayoutTestMode is_layout_test_mode, + WebView::UseJavaScriptBytecode use_javascript_bytecode) { - auto application_path = TRY(ak_string_from_qstring(QCoreApplication::applicationDirPath())); - Vector paths; + int socket_fds[2] {}; + TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds)); - TRY(paths.try_append(TRY(String::formatted("./{}/{}", process_name, process_name)))); - TRY(paths.try_append(TRY(String::formatted("{}/{}/{}", application_path, process_name, process_name)))); - TRY(paths.try_append(TRY(String::formatted("{}/{}", application_path, process_name)))); - TRY(paths.try_append(TRY(String::formatted("./{}", process_name)))); - // NOTE: Add platform-specific paths here - return paths; + int ui_fd = socket_fds[0]; + int wc_fd = socket_fds[1]; + + int fd_passing_socket_fds[2] {}; + TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds)); + + int ui_fd_passing_fd = fd_passing_socket_fds[0]; + int wc_fd_passing_fd = fd_passing_socket_fds[1]; + + if (auto child_pid = TRY(Core::System::fork()); child_pid == 0) { + TRY(Core::System::close(ui_fd_passing_fd)); + TRY(Core::System::close(ui_fd)); + + auto takeover_string = TRY(String::formatted("WebContent:{}", wc_fd)); + TRY(Core::System::setenv("SOCKET_TAKEOVER"sv, takeover_string, true)); + + auto webcontent_fd_passing_socket_string = TRY(String::number(wc_fd_passing_fd)); + + ErrorOr result; + for (auto const& path : candidate_web_content_paths) { + constexpr auto callgrind_prefix_length = 3; + + if (Core::System::access(path, X_OK).is_error()) + continue; + + auto arguments = Vector { + "valgrind"sv, + "--tool=callgrind"sv, + "--instr-atstart=no"sv, + path.bytes_as_string_view(), + "--webcontent-fd-passing-socket"sv, + webcontent_fd_passing_socket_string + }; + if (enable_callgrind_profiling == WebView::EnableCallgrindProfiling::No) + arguments.remove(0, callgrind_prefix_length); + if (is_layout_test_mode == WebView::IsLayoutTestMode::Yes) + arguments.append("--layout-test-mode"sv); + if (use_javascript_bytecode == WebView::UseJavaScriptBytecode::Yes) + arguments.append("--use-bytecode"sv); + + result = Core::System::exec(arguments[0], arguments.span(), Core::System::SearchInPath::Yes); + if (!result.is_error()) + break; + } + + if (result.is_error()) + warnln("Could not launch any of {}: {}", candidate_web_content_paths, result.error()); + VERIFY_NOT_REACHED(); + } + + TRY(Core::System::close(wc_fd_passing_fd)); + TRY(Core::System::close(wc_fd)); + + auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd)); + TRY(socket->set_blocking(true)); + + auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), view))); + new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd))); + + if (enable_callgrind_profiling == WebView::EnableCallgrindProfiling::Yes) { + dbgln(); + dbgln("\033[1;45mLaunched WebContent process under callgrind!\033[0m"); + dbgln("\033[100mRun `\033[4mcallgrind_control -i on\033[24m` to start instrumentation and `\033[4mcallgrind_control -i off\033[24m` stop it again.\033[0m"); + dbgln(); + } + + return new_client; } diff --git a/Ladybird/HelperProcess.h b/Ladybird/HelperProcess.h index 9ad4fe10ef..086e0cd439 100644 --- a/Ladybird/HelperProcess.h +++ b/Ladybird/HelperProcess.h @@ -7,9 +7,14 @@ #pragma once #include -#include #include #include -#include -ErrorOr> get_paths_for_helper_process(StringView process_name); +#include +#include + +ErrorOr> launch_web_content_process(WebView::ViewImplementation& view, + ReadonlySpan candidate_web_content_paths, + WebView::EnableCallgrindProfiling, + WebView::IsLayoutTestMode, + WebView::UseJavaScriptBytecode); diff --git a/Ladybird/Utilities.cpp b/Ladybird/Utilities.cpp index dbc9e9a48d..0e6a9c443c 100644 --- a/Ladybird/Utilities.cpp +++ b/Ladybird/Utilities.cpp @@ -58,3 +58,16 @@ void platform_init() }(); #endif } + +ErrorOr> get_paths_for_helper_process(StringView process_name) +{ + auto application_path = TRY(ak_string_from_qstring(QCoreApplication::applicationDirPath())); + Vector paths; + + TRY(paths.try_append(TRY(String::formatted("./{}/{}", process_name, process_name)))); + TRY(paths.try_append(TRY(String::formatted("{}/{}/{}", application_path, process_name, process_name)))); + TRY(paths.try_append(TRY(String::formatted("{}/{}", application_path, process_name)))); + TRY(paths.try_append(TRY(String::formatted("./{}", process_name)))); + // NOTE: Add platform-specific paths here + return paths; +} diff --git a/Ladybird/Utilities.h b/Ladybird/Utilities.h index a573651523..971254de94 100644 --- a/Ladybird/Utilities.h +++ b/Ladybird/Utilities.h @@ -7,7 +7,9 @@ #pragma once #include +#include #include +#include #include AK::DeprecatedString ak_deprecated_string_from_qstring(QString const&); @@ -15,5 +17,6 @@ ErrorOr ak_string_from_qstring(QString const&); QString qstring_from_ak_deprecated_string(AK::DeprecatedString const&); QString qstring_from_ak_string(String const&); void platform_init(); +ErrorOr> get_paths_for_helper_process(StringView process_name); extern DeprecatedString s_serenity_resource_root; diff --git a/Ladybird/WebContentView.cpp b/Ladybird/WebContentView.cpp index 73056ea275..53451dd38a 100644 --- a/Ladybird/WebContentView.cpp +++ b/Ladybird/WebContentView.cpp @@ -531,7 +531,7 @@ void WebContentView::create_client(WebView::EnableCallgrindProfiling enable_call m_client_state = {}; auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors(); - auto new_client = launch_web_content_process(candidate_web_content_paths, enable_callgrind_profiling, WebView::IsLayoutTestMode::No, use_javascript_bytecode()).release_value_but_fixme_should_propagate_errors(); + auto new_client = launch_web_content_process(*this, candidate_web_content_paths, enable_callgrind_profiling, WebView::IsLayoutTestMode::No, use_javascript_bytecode()).release_value_but_fixme_should_propagate_errors(); m_client_state.client = new_client; m_client_state.client->on_web_content_process_crash = [this] { diff --git a/Ladybird/WebDriver/CMakeLists.txt b/Ladybird/WebDriver/CMakeLists.txt index 11f36a1bbc..5f770c63f2 100644 --- a/Ladybird/WebDriver/CMakeLists.txt +++ b/Ladybird/WebDriver/CMakeLists.txt @@ -5,7 +5,6 @@ set(SOURCES ${WEBDRIVER_SOURCE_DIR}/Session.cpp ${WEBDRIVER_SOURCE_DIR}/WebContentConnection.cpp ../Utilities.cpp - ../HelperProcess.cpp main.cpp ) diff --git a/Meta/gn/secondary/Ladybird/WebDriver/BUILD.gn b/Meta/gn/secondary/Ladybird/WebDriver/BUILD.gn index bb5407c2f8..47397ca455 100644 --- a/Meta/gn/secondary/Ladybird/WebDriver/BUILD.gn +++ b/Meta/gn/secondary/Ladybird/WebDriver/BUILD.gn @@ -31,7 +31,6 @@ executable("WebDriver") { "//Userland/Libraries/LibWebView:WebDriverServerEndpoint", ] sources = [ - "../HelperProcess.cpp", "../Utilities.cpp", "//Userland/Services/WebDriver/Client.cpp", "//Userland/Services/WebDriver/Session.cpp", diff --git a/Userland/Libraries/LibWebView/ViewImplementation.cpp b/Userland/Libraries/LibWebView/ViewImplementation.cpp index 0d1a5e039e..63e67c2fcf 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.cpp +++ b/Userland/Libraries/LibWebView/ViewImplementation.cpp @@ -179,84 +179,6 @@ void ViewImplementation::handle_resize() m_backing_store_shrink_timer->restart(); } -#if !defined(AK_OS_SERENITY) - -ErrorOr> ViewImplementation::launch_web_content_process(ReadonlySpan candidate_web_content_paths, EnableCallgrindProfiling enable_callgrind_profiling, IsLayoutTestMode is_layout_test_mode, UseJavaScriptBytecode use_javascript_bytecode) -{ - int socket_fds[2] {}; - TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds)); - - int ui_fd = socket_fds[0]; - int wc_fd = socket_fds[1]; - - int fd_passing_socket_fds[2] {}; - TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds)); - - int ui_fd_passing_fd = fd_passing_socket_fds[0]; - int wc_fd_passing_fd = fd_passing_socket_fds[1]; - - if (auto child_pid = TRY(Core::System::fork()); child_pid == 0) { - TRY(Core::System::close(ui_fd_passing_fd)); - TRY(Core::System::close(ui_fd)); - - auto takeover_string = TRY(String::formatted("WebContent:{}", wc_fd)); - TRY(Core::System::setenv("SOCKET_TAKEOVER"sv, takeover_string, true)); - - auto webcontent_fd_passing_socket_string = TRY(String::number(wc_fd_passing_fd)); - - ErrorOr result; - for (auto const& path : candidate_web_content_paths) { - constexpr auto callgrind_prefix_length = 3; - - if (Core::System::access(path, X_OK).is_error()) - continue; - - auto arguments = Vector { - "valgrind"sv, - "--tool=callgrind"sv, - "--instr-atstart=no"sv, - path.bytes_as_string_view(), - "--webcontent-fd-passing-socket"sv, - webcontent_fd_passing_socket_string - }; - if (enable_callgrind_profiling == EnableCallgrindProfiling::No) - arguments.remove(0, callgrind_prefix_length); - if (is_layout_test_mode == IsLayoutTestMode::Yes) - arguments.append("--layout-test-mode"sv); - if (use_javascript_bytecode == UseJavaScriptBytecode::Yes) - arguments.append("--use-bytecode"sv); - - result = Core::System::exec(arguments[0], arguments.span(), Core::System::SearchInPath::Yes); - if (!result.is_error()) - break; - } - - if (result.is_error()) - warnln("Could not launch any of {}: {}", candidate_web_content_paths, result.error()); - VERIFY_NOT_REACHED(); - } - - TRY(Core::System::close(wc_fd_passing_fd)); - TRY(Core::System::close(wc_fd)); - - auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd)); - TRY(socket->set_blocking(true)); - - auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), *this))); - new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd))); - - if (enable_callgrind_profiling == EnableCallgrindProfiling::Yes) { - dbgln(); - dbgln("\033[1;45mLaunched WebContent process under callgrind!\033[0m"); - dbgln("\033[100mRun `\033[4mcallgrind_control -i on\033[24m` to start instrumentation and `\033[4mcallgrind_control -i off\033[24m` stop it again.\033[0m"); - dbgln(); - } - - return new_client; -} - -#endif - void ViewImplementation::resize_backing_stores_if_needed(WindowResizeInProgress window_resize_in_progress) { if (m_client_state.has_usable_bitmap) { diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h index cd9a0c861e..f14e058093 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.h +++ b/Userland/Libraries/LibWebView/ViewImplementation.h @@ -177,10 +177,6 @@ protected: virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No) { } -#if !defined(AK_OS_SERENITY) - ErrorOr> launch_web_content_process(ReadonlySpan candidate_web_content_paths, EnableCallgrindProfiling = EnableCallgrindProfiling::No, IsLayoutTestMode = IsLayoutTestMode::No, UseJavaScriptBytecode = UseJavaScriptBytecode::No); -#endif - void handle_web_content_process_crash(); struct SharedBitmap { diff --git a/Userland/Utilities/headless-browser.cpp b/Userland/Utilities/headless-browser.cpp index 58858ef559..dbe6213357 100644 --- a/Userland/Utilities/headless-browser.cpp +++ b/Userland/Utilities/headless-browser.cpp @@ -42,6 +42,7 @@ #if !defined(AK_OS_SERENITY) # include +# include # include #endif @@ -57,7 +58,7 @@ public: (void)use_javascript_bytecode; #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, WebView::EnableCallgrindProfiling::No, is_layout_test_mode, use_javascript_bytecode)); + view->m_client_state.client = TRY(launch_web_content_process(*view, candidate_web_content_paths, WebView::EnableCallgrindProfiling::No, is_layout_test_mode, use_javascript_bytecode)); #endif view->client().async_update_system_theme(move(theme));