2023-02-02 10:00:30 +00:00
/*
* Copyright ( c ) 2023 , Andrew Kaster < akaster @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include "HelperProcess.h"
2024-04-04 20:13:14 +00:00
# include "Utilities.h"
2024-04-23 20:39:04 +00:00
# include <AK/Enumerate.h>
# include <LibCore/Process.h>
2024-03-26 00:29:14 +00:00
# include <LibWebView/ProcessManager.h>
2023-02-02 10:00:30 +00:00
2024-04-23 20:39:04 +00:00
enum class RegisterWithProcessManager {
No ,
Yes ,
} ;
2024-06-04 20:54:43 +00:00
template < typename ClientType , typename . . . ClientArguments >
static ErrorOr < NonnullRefPtr < ClientType > > launch_server_process (
2024-04-23 20:39:04 +00:00
StringView server_name ,
ReadonlySpan < ByteString > candidate_server_paths ,
2024-04-27 12:47:02 +00:00
Vector < ByteString > arguments ,
2024-04-23 20:39:04 +00:00
RegisterWithProcessManager register_with_process_manager ,
2024-04-27 12:47:02 +00:00
Ladybird : : EnableCallgrindProfiling enable_callgrind_profiling ,
2024-06-04 20:54:43 +00:00
ClientArguments & & . . . client_arguments )
2024-04-23 20:39:04 +00:00
{
2024-04-27 12:47:02 +00: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 20:39:04 +00:00
} ) ;
2024-04-27 12:47:02 +00: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 ;
}
2024-06-04 20:54:43 +00:00
auto result = Core : : IPCProcess : : spawn < ClientType > ( move ( options ) , forward < ClientArguments > ( client_arguments ) . . . ) ;
2024-04-23 20:39:04 +00:00
if ( ! result . is_error ( ) ) {
auto process = result . release_value ( ) ;
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 12:47:02 +00: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 20:39:04 +00: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 ( ) ;
}
2023-12-01 17:18:40 +00:00
ErrorOr < NonnullRefPtr < WebView : : WebContentClient > > launch_web_content_process (
WebView : : ViewImplementation & view ,
2024-02-22 01:27:05 +00:00
ReadonlySpan < ByteString > candidate_web_content_paths ,
2024-04-15 23:39:48 +00:00
Ladybird : : WebContentOptions const & web_content_options ,
2024-04-18 00:44:39 +00:00
Optional < IPC : : File > request_server_socket )
2023-02-02 10:00:30 +00:00
{
2024-04-23 20:39:04 +00: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 17:56:10 +00:00
2024-04-23 20:39:04 +00: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-06-14 21:18:04 +00:00
if ( web_content_options . enable_skia_painting = = Ladybird : : EnableSkiaPainting : : Yes )
arguments . append ( " --use-skia-painting " sv ) ;
2024-04-23 20:39:04 +00: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 ) ;
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 17:56:10 +00:00
}
2024-06-04 20:54:43 +00:00
return launch_server_process < WebView : : WebContentClient > ( " WebContent " sv , candidate_web_content_paths , move ( arguments ) , RegisterWithProcessManager : : No , web_content_options . enable_callgrind_profiling , view ) ;
2023-08-01 20:39:19 +00:00
}
2023-08-03 00:13:23 +00:00
2024-02-22 01:27:05 +00:00
ErrorOr < NonnullRefPtr < ImageDecoderClient : : Client > > launch_image_decoder_process ( ReadonlySpan < ByteString > candidate_image_decoder_paths )
2023-09-08 10:30:50 +00:00
{
2024-06-04 20:54:43 +00:00
return launch_server_process < ImageDecoderClient : : Client > ( " ImageDecoder " sv , candidate_image_decoder_paths , { } , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
2023-09-08 10:30:50 +00:00
}
2024-04-15 23:39:48 +00:00
ErrorOr < NonnullRefPtr < Web : : HTML : : WebWorkerClient > > launch_web_worker_process ( ReadonlySpan < ByteString > candidate_web_worker_paths , NonnullRefPtr < Protocol : : RequestClient > request_client )
2024-01-06 20:13:59 +00:00
{
2024-04-18 00:44:39 +00:00
auto socket = TRY ( connect_new_request_server_client ( move ( request_client ) ) ) ;
2024-04-15 23:39:48 +00:00
2024-04-23 20:39:04 +00:00
Vector < ByteString > arguments {
" --request-server-socket " sv ,
ByteString : : number ( socket . fd ( ) ) ,
} ;
2024-04-15 23:39:48 +00:00
2024-06-04 20:54:43 +00:00
return launch_server_process < Web : : HTML : : WebWorkerClient > ( " WebWorker " sv , candidate_web_worker_paths , move ( arguments ) , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
2024-01-06 20:13:59 +00:00
}
2024-02-22 01:27:05 +00: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-03 00:13:23 +00:00
{
2024-04-23 20:39:04 +00:00
Vector < ByteString > arguments ;
2024-04-15 23:39:48 +00:00
if ( ! serenity_resource_root . is_empty ( ) ) {
arguments . append ( " --serenity-resource-root " sv ) ;
arguments . append ( serenity_resource_root ) ;
}
2024-04-22 16:57:38 +00:00
2024-04-23 20:39:04 +00:00
for ( auto const & certificate : certificates )
arguments . append ( ByteString : : formatted ( " --certificate={} " , certificate ) ) ;
2024-04-15 23:39:48 +00:00
2024-04-22 16:57:38 +00:00
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2024-06-04 20:54:43 +00:00
return launch_server_process < Protocol : : RequestClient > ( " RequestServer " sv , candidate_request_server_paths , move ( arguments ) , RegisterWithProcessManager : : Yes , Ladybird : : EnableCallgrindProfiling : : No ) ;
2024-04-15 23:39:48 +00:00
}
2024-04-18 00:44:39 +00:00
ErrorOr < IPC : : File > connect_new_request_server_client ( Protocol : : RequestClient & client )
2024-04-15 23:39:48 +00:00
{
2024-04-18 00:44:39 +00:00
auto new_socket = client . send_sync_but_allow_failure < Messages : : RequestServer : : ConnectNewClient > ( ) ;
if ( ! new_socket )
2024-04-15 23:39:48 +00:00
return Error : : from_string_literal ( " Failed to connect to RequestServer " ) ;
2024-04-18 00:44:39 +00:00
auto socket = new_socket - > take_client_socket ( ) ;
2024-04-15 23:39:48 +00:00
// FIXME: IPC::Files transferred over the wire are always set O_CLOEXEC during decoding.
// Perhaps we should add an option to IPC::File to allow the receiver to decide whether to
// make it O_CLOEXEC or not. Or an attribute in the .ipc file?
2024-04-18 00:44:39 +00:00
auto fd = socket . fd ( ) ;
auto fd_flags = MUST ( Core : : System : : fcntl ( fd , F_GETFD ) ) ;
fd_flags & = ~ FD_CLOEXEC ;
MUST ( Core : : System : : fcntl ( fd , F_SETFD , fd_flags ) ) ;
2024-04-15 23:39:48 +00:00
2024-04-18 00:44:39 +00:00
return socket ;
2023-08-03 00:13:23 +00:00
}