1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 14:07:42 +00:00

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.
This commit is contained in:
Andrew Kaster 2023-08-01 11:56:10 -06:00 committed by Andreas Kling
parent 3be71a81bb
commit 5062ba347b
10 changed files with 101 additions and 100 deletions

View file

@ -5,18 +5,81 @@
*/
#include "HelperProcess.h"
#include "Utilities.h"
#include <QCoreApplication>
ErrorOr<Vector<String>> get_paths_for_helper_process(StringView process_name)
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(WebView::ViewImplementation& view,
ReadonlySpan<String> 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<String> 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<void> 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;
}

View file

@ -7,9 +7,14 @@
#pragma once
#include <AK/Error.h>
#include <AK/Optional.h>
#include <AK/Span.h>
#include <AK/StringView.h>
#include <LibCore/System.h>
ErrorOr<Vector<String>> get_paths_for_helper_process(StringView process_name);
#include <LibWebView/ViewImplementation.h>
#include <LibWebView/WebContentClient.h>
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(WebView::ViewImplementation& view,
ReadonlySpan<String> candidate_web_content_paths,
WebView::EnableCallgrindProfiling,
WebView::IsLayoutTestMode,
WebView::UseJavaScriptBytecode);

View file

@ -58,3 +58,16 @@ void platform_init()
}();
#endif
}
ErrorOr<Vector<String>> get_paths_for_helper_process(StringView process_name)
{
auto application_path = TRY(ak_string_from_qstring(QCoreApplication::applicationDirPath()));
Vector<String> 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;
}

View file

@ -7,7 +7,9 @@
#pragma once
#include <AK/DeprecatedString.h>
#include <AK/Error.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <QString>
AK::DeprecatedString ak_deprecated_string_from_qstring(QString const&);
@ -15,5 +17,6 @@ ErrorOr<String> 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<Vector<String>> get_paths_for_helper_process(StringView process_name);
extern DeprecatedString s_serenity_resource_root;

View file

@ -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] {

View file

@ -5,7 +5,6 @@ set(SOURCES
${WEBDRIVER_SOURCE_DIR}/Session.cpp
${WEBDRIVER_SOURCE_DIR}/WebContentConnection.cpp
../Utilities.cpp
../HelperProcess.cpp
main.cpp
)

View file

@ -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",

View file

@ -179,84 +179,6 @@ void ViewImplementation::handle_resize()
m_backing_store_shrink_timer->restart();
}
#if !defined(AK_OS_SERENITY)
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web_content_process(ReadonlySpan<String> 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<void> 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) {

View file

@ -177,10 +177,6 @@ protected:
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No) { }
#if !defined(AK_OS_SERENITY)
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling = EnableCallgrindProfiling::No, IsLayoutTestMode = IsLayoutTestMode::No, UseJavaScriptBytecode = UseJavaScriptBytecode::No);
#endif
void handle_web_content_process_crash();
struct SharedBitmap {

View file

@ -42,6 +42,7 @@
#if !defined(AK_OS_SERENITY)
# include <Ladybird/HelperProcess.h>
# include <Ladybird/Utilities.h>
# include <QCoreApplication>
#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));