2023-02-02 05:00:30 -05:00
/*
* Copyright ( c ) 2023 , Andrew Kaster < akaster @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include "HelperProcess.h"
2024-04-04 16:13:14 -04:00
# include "Utilities.h"
2024-04-23 16:39:04 -04:00
# include <AK/Enumerate.h>
# include <LibCore/Process.h>
2024-03-25 20:29:14 -04:00
# include <LibWebView/ProcessManager.h>
2023-02-02 05:00:30 -05:00
2024-04-23 16:39:04 -04:00
enum class RegisterWithProcessManager {
No ,
Yes ,
} ;
template < typename ClientType , typename SpawnFunction >
static ErrorOr < NonnullRefPtr < ClientType > > launch_server_process_impl (
StringView server_name ,
ReadonlySpan < ByteString > candidate_server_paths ,
2024-04-27 08:47:02 -04:00
Vector < ByteString > arguments ,
2024-04-23 16:39:04 -04:00
RegisterWithProcessManager register_with_process_manager ,
2024-04-27 08:47:02 -04:00
Ladybird : : EnableCallgrindProfiling enable_callgrind_profiling ,
2024-04-23 16:39:04 -04:00
SpawnFunction & & spawn_function )
{
2024-04-27 08:47:02 -04:00
if ( enable_callgrind_profiling = = Ladybird : : EnableCallgrindProfiling : : Yes ) {
arguments . prepend ( {
" --tool=callgrind " sv ,
" --instr-atstart=no " sv ,
" " sv , // Placeholder for the process path.
2024-04-23 16:39:04 -04:00
} ) ;
2024-04-27 08:47:02 -04:00
}
for ( auto [ i , path ] : enumerate ( candidate_server_paths ) ) {
Core : : ProcessSpawnOptions options { . name = server_name , . arguments = arguments } ;
if ( enable_callgrind_profiling = = Ladybird : : EnableCallgrindProfiling : : Yes ) {
options . executable = " valgrind " sv ;
options . search_for_executable_in_path = true ;
arguments [ 2 ] = path ;
} else {
options . executable = path ;
}
auto result = spawn_function ( options ) ;
2024-04-23 16:39:04 -04:00
if ( ! result . is_error ( ) ) {
auto process = result . release_value ( ) ;
2024-06-18 12:11:51 -04:00
if constexpr ( requires { process . client - > set_pid ( pid_t { } ) ; } )
process . client - > set_pid ( process . process . pid ( ) ) ;
2024-04-23 16:39:04 -04:00
if ( register_with_process_manager = = RegisterWithProcessManager : : Yes )
WebView : : ProcessManager : : the ( ) . add_process ( WebView : : process_type_from_name ( server_name ) , process . process . pid ( ) ) ;
2024-04-27 08:47:02 -04:00
if ( enable_callgrind_profiling = = Ladybird : : EnableCallgrindProfiling : : Yes ) {
dbgln ( ) ;
dbgln ( " \033 [1;45mLaunched {} process under callgrind! \033 [0m " , server_name ) ;
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 ( ) ;
}
2024-04-23 16:39:04 -04:00
return move ( process . client ) ;
}
if ( i = = candidate_server_paths . size ( ) - 1 ) {
warnln ( " Could not launch any of {}: {} " , candidate_server_paths , result . error ( ) ) ;
return result . release_error ( ) ;
}
}
VERIFY_NOT_REACHED ( ) ;
}
template < typename ClientType , typename . . . ClientArguments >
static ErrorOr < NonnullRefPtr < ClientType > > launch_generic_server_process (
StringView server_name ,
ReadonlySpan < ByteString > candidate_server_paths ,
2024-04-27 08:47:02 -04:00
Vector < ByteString > arguments ,
2024-04-23 16:39:04 -04:00
RegisterWithProcessManager register_with_process_manager ,
2024-04-27 08:47:02 -04:00
Ladybird : : EnableCallgrindProfiling enable_callgrind_profiling ,
2024-04-23 16:39:04 -04:00
ClientArguments & & . . . client_arguments )
{
2024-04-27 08:47:02 -04:00
return launch_server_process_impl < ClientType > ( server_name , candidate_server_paths , move ( arguments ) , register_with_process_manager , enable_callgrind_profiling , [ & ] ( auto options ) {
2024-04-23 16:39:04 -04:00
return Core : : IPCProcess : : spawn < ClientType > ( move ( options ) , forward < ClientArguments > ( client_arguments ) . . . ) ;
} ) ;
}
2024-04-23 18:55:41 -04:00
template < typename ClientType , typename . . . ClientArguments >
static ErrorOr < NonnullRefPtr < ClientType > > launch_singleton_server_process (
StringView server_name ,
ReadonlySpan < ByteString > candidate_server_paths ,
2024-04-27 08:47:02 -04:00
Vector < ByteString > arguments ,
2024-04-23 18:55:41 -04:00
RegisterWithProcessManager register_with_process_manager ,
ClientArguments & & . . . client_arguments )
{
2024-04-27 08:47:02 -04:00
return launch_server_process_impl < ClientType > ( server_name , candidate_server_paths , move ( arguments ) , register_with_process_manager , Ladybird : : EnableCallgrindProfiling : : No , [ & ] ( auto options ) {
2024-04-23 18:55:41 -04:00
return Core : : IPCProcess : : spawn_singleton < ClientType > ( move ( options ) , forward < ClientArguments > ( client_arguments ) . . . ) ;
} ) ;
}
2023-12-01 12:18:40 -05:00
ErrorOr < NonnullRefPtr < WebView : : WebContentClient > > launch_web_content_process (
WebView : : ViewImplementation & view ,
2024-02-21 20:27:05 -05:00
ReadonlySpan < ByteString > candidate_web_content_paths ,
2024-04-15 19:39:48 -04:00
Ladybird : : WebContentOptions const & web_content_options ,
2024-04-17 20:44:39 -04:00
Optional < IPC : : File > request_server_socket )
2023-02-02 05:00:30 -05:00
{
2024-04-23 16:39:04 -04:00
Vector < ByteString > arguments {
" --command-line " sv ,
web_content_options . command_line . to_byte_string ( ) ,
" --executable-path " sv ,
web_content_options . executable_path . to_byte_string ( ) ,
} ;
2023-08-01 13:56:10 -04:00
2024-04-23 16:39:04 -04:00
if ( web_content_options . is_layout_test_mode = = Ladybird : : IsLayoutTestMode : : Yes )
arguments . append ( " --layout-test-mode " sv ) ;
if ( web_content_options . use_lagom_networking = = Ladybird : : UseLagomNetworking : : Yes )
arguments . append ( " --use-lagom-networking " sv ) ;
if ( web_content_options . enable_gpu_painting = = Ladybird : : EnableGPUPainting : : Yes )
arguments . append ( " --use-gpu-painting " sv ) ;
2024-05-27 14:28:05 -04:00
if ( web_content_options . enable_experimental_cpu_transforms = = Ladybird : : EnableExperimentalCPUTransforms : : Yes )
arguments . append ( " --experimental-cpu-transforms " sv ) ;
2024-04-23 16:39:04 -04:00
if ( web_content_options . wait_for_debugger = = Ladybird : : WaitForDebugger : : Yes )
arguments . append ( " --wait-for-debugger " sv ) ;
if ( web_content_options . log_all_js_exceptions = = Ladybird : : LogAllJSExceptions : : Yes )
arguments . append ( " --log-all-js-exceptions " sv ) ;
if ( web_content_options . enable_idl_tracing = = Ladybird : : EnableIDLTracing : : Yes )
arguments . append ( " --enable-idl-tracing " sv ) ;
2024-06-22 12:53:11 -04:00
if ( web_content_options . enable_http_cache = = Ladybird : : EnableHTTPCache : : Yes )
arguments . append ( " --enable-http-cache " sv ) ;
2024-04-23 16:39:04 -04:00
if ( web_content_options . expose_internals_object = = Ladybird : : ExposeInternalsObject : : Yes )
arguments . append ( " --expose-internals-object " sv ) ;
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
if ( request_server_socket . has_value ( ) ) {
arguments . append ( " --request-server-socket " sv ) ;
arguments . append ( ByteString : : number ( request_server_socket - > fd ( ) ) ) ;
2023-08-01 13:56:10 -04:00
}
2024-04-27 08:47:02 -04:00
return launch_generic_server_process < WebView : : WebContentClient > ( " WebContent " sv , candidate_web_content_paths , move ( arguments ) , RegisterWithProcessManager : : No , web_content_options . enable_callgrind_profiling , view ) ;
2023-08-01 16:39:19 -04:00
}
2023-08-02 20:13:23 -04:00
2024-02-21 20:27:05 -05:00
ErrorOr < NonnullRefPtr < ImageDecoderClient : : Client > > launch_image_decoder_process ( ReadonlySpan < ByteString > candidate_image_decoder_paths )
2023-09-08 06:30:50 -04:00
{
2024-04-27 08:47:02 -04:00
return launch_generic_server_process < ImageDecoderClient : : Client > ( " ImageDecoder " sv , candidate_image_decoder_paths , { } , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
2023-09-08 06:30:50 -04:00
}
2024-07-05 22:41:07 -04:00
ErrorOr < NonnullRefPtr < Web : : HTML : : WebWorkerClient > > launch_web_worker_process ( ReadonlySpan < ByteString > candidate_web_worker_paths , RefPtr < Protocol : : RequestClient > request_client )
2024-01-06 15:13:59 -05:00
{
2024-07-05 22:41:07 -04:00
Vector < ByteString > arguments ;
if ( request_client ) {
auto socket = TRY ( connect_new_request_server_client ( * request_client ) ) ;
arguments . append ( " --request-server-socket " sv ) ;
arguments . append ( ByteString : : number ( socket . fd ( ) ) ) ;
arguments . append ( " --use-lagom-networking " sv ) ;
return launch_generic_server_process < Web : : HTML : : WebWorkerClient > ( " WebWorker " sv , candidate_web_worker_paths , move ( arguments ) , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
}
2024-04-15 19:39:48 -04:00
2024-04-27 08:47:02 -04:00
return launch_generic_server_process < Web : : HTML : : WebWorkerClient > ( " WebWorker " sv , candidate_web_worker_paths , move ( arguments ) , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
2024-01-06 15:13:59 -05:00
}
2024-02-21 20:27:05 -05:00
ErrorOr < NonnullRefPtr < Protocol : : RequestClient > > launch_request_server_process ( ReadonlySpan < ByteString > candidate_request_server_paths , StringView serenity_resource_root , Vector < ByteString > const & certificates )
2023-08-02 20:13:23 -04:00
{
2024-04-23 16:39:04 -04:00
Vector < ByteString > arguments ;
2024-04-15 19:39:48 -04:00
if ( ! serenity_resource_root . is_empty ( ) ) {
arguments . append ( " --serenity-resource-root " sv ) ;
arguments . append ( serenity_resource_root ) ;
}
2024-04-22 12:57:38 -04:00
2024-04-23 16:39:04 -04:00
for ( auto const & certificate : certificates )
arguments . append ( ByteString : : formatted ( " --certificate={} " , certificate ) ) ;
2024-04-15 19:39:48 -04:00
2024-04-22 12:57:38 -04:00
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2024-04-27 08:47:02 -04:00
return launch_generic_server_process < Protocol : : RequestClient > ( " RequestServer " sv , candidate_request_server_paths , move ( arguments ) , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
2024-04-15 19:39:48 -04:00
}
2024-04-22 12:31:29 -04:00
ErrorOr < NonnullRefPtr < SQL : : SQLClient > > launch_sql_server_process ( ReadonlySpan < ByteString > candidate_sql_server_paths )
{
2024-04-22 12:34:54 -04:00
Vector < ByteString > arguments ;
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2024-04-23 18:55:41 -04:00
return launch_singleton_server_process < SQL : : SQLClient > ( " SQLServer " sv , candidate_sql_server_paths , arguments , RegisterWithProcessManager : : Yes ) ;
2024-04-22 12:31:29 -04:00
}
2024-04-17 20:44:39 -04:00
ErrorOr < IPC : : File > connect_new_request_server_client ( Protocol : : RequestClient & client )
2024-04-15 19:39:48 -04:00
{
2024-04-17 20:44:39 -04:00
auto new_socket = client . send_sync_but_allow_failure < Messages : : RequestServer : : ConnectNewClient > ( ) ;
if ( ! new_socket )
2024-04-15 19:39:48 -04:00
return Error : : from_string_literal ( " Failed to connect to RequestServer " ) ;
2024-04-17 20:44:39 -04:00
auto socket = new_socket - > take_client_socket ( ) ;
2024-06-25 16:57:16 -04:00
TRY ( socket . clear_close_on_exec ( ) ) ;
2024-04-15 19:39:48 -04:00
2024-04-17 20:44:39 -04:00
return socket ;
2023-08-02 20:13:23 -04:00
}