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-06-30 04:24:01 +00:00
# include <LibWebView/Application.h>
2023-02-02 10:00:30 +00:00
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-06-04 20:54:43 +00:00
ClientArguments & & . . . client_arguments )
2024-04-23 20:39:04 +00:00
{
2024-08-01 11:03:03 +00:00
auto process_type = WebView : : process_type_from_name ( server_name ) ;
auto const & chrome_options = WebView : : Application : : chrome_options ( ) ;
2024-08-01 11:13:09 +00:00
if ( chrome_options . profile_helper_process = = process_type ) {
2024-04-27 12:47:02 +00:00
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
}
2024-08-01 11:03:03 +00:00
if ( chrome_options . debug_helper_process = = process_type )
arguments . append ( " --wait-for-debugger " sv ) ;
2024-04-27 12:47:02 +00:00
for ( auto [ i , path ] : enumerate ( candidate_server_paths ) ) {
Core : : ProcessSpawnOptions options { . name = server_name , . arguments = arguments } ;
2024-08-01 11:13:09 +00:00
if ( chrome_options . profile_helper_process = = process_type ) {
2024-04-27 12:47:02 +00:00
options . executable = " valgrind " sv ;
options . search_for_executable_in_path = true ;
arguments [ 2 ] = path ;
} else {
options . executable = path ;
}
2024-10-22 19:27:15 +00:00
auto result = WebView : : Process : : spawn < ClientType > ( process_type , move ( options ) , forward < ClientArguments > ( client_arguments ) . . . ) ;
2024-04-23 20:39:04 +00:00
if ( ! result . is_error ( ) ) {
2024-10-22 19:27:15 +00:00
auto & & [ process , client ] = result . release_value ( ) ;
2024-04-23 20:39:04 +00:00
2024-10-22 19:27:15 +00:00
if constexpr ( requires { client - > set_pid ( pid_t { } ) ; } )
client - > set_pid ( process . pid ( ) ) ;
2024-06-18 16:11:51 +00:00
2024-10-22 19:27:15 +00:00
WebView : : Application : : the ( ) . add_child_process ( move ( process ) ) ;
2024-04-23 20:39:04 +00:00
2024-08-01 11:13:09 +00:00
if ( chrome_options . profile_helper_process = = process_type ) {
2024-04-27 12:47:02 +00:00
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-10-22 19:27:15 +00:00
return move ( client ) ;
2024-04-23 20:39:04 +00:00
}
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-06-26 19:44:42 +00:00
IPC : : File image_decoder_socket ,
2024-04-18 00:44:39 +00:00
Optional < IPC : : File > request_server_socket )
2023-02-02 10:00:30 +00:00
{
2024-07-30 18:01:05 +00:00
auto const & web_content_options = WebView : : Application : : web_content_options ( ) ;
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-07-16 16:52:12 +00:00
if ( web_content_options . config_path . has_value ( ) ) {
arguments . append ( " --config-path " sv ) ;
arguments . append ( web_content_options . config_path . value ( ) ) ;
}
2024-07-30 18:01:05 +00:00
if ( web_content_options . is_layout_test_mode = = WebView : : IsLayoutTestMode : : Yes )
2024-04-23 20:39:04 +00:00
arguments . append ( " --layout-test-mode " sv ) ;
2024-07-30 18:01:05 +00:00
if ( web_content_options . log_all_js_exceptions = = WebView : : LogAllJSExceptions : : Yes )
2024-04-23 20:39:04 +00:00
arguments . append ( " --log-all-js-exceptions " sv ) ;
2024-07-30 18:01:05 +00:00
if ( web_content_options . enable_idl_tracing = = WebView : : EnableIDLTracing : : Yes )
2024-04-23 20:39:04 +00:00
arguments . append ( " --enable-idl-tracing " sv ) ;
2024-07-30 18:01:05 +00:00
if ( web_content_options . enable_http_cache = = WebView : : EnableHTTPCache : : Yes )
2024-06-22 16:53:11 +00:00
arguments . append ( " --enable-http-cache " sv ) ;
2024-07-30 18:01:05 +00:00
if ( web_content_options . expose_internals_object = = WebView : : ExposeInternalsObject : : Yes )
2024-04-23 20:39:04 +00:00
arguments . append ( " --expose-internals-object " sv ) ;
2024-08-01 17:49:24 +00:00
if ( web_content_options . force_cpu_painting = = WebView : : ForceCPUPainting : : Yes )
arguments . append ( " --force-cpu-painting " sv ) ;
2024-08-19 18:35:49 +00:00
if ( web_content_options . force_fontconfig = = WebView : : ForceFontconfig : : Yes )
arguments . append ( " --force-fontconfig " sv ) ;
2024-10-31 15:06:01 +00:00
if ( web_content_options . collect_garbage_on_every_allocation = = WebView : : CollectGarbageOnEveryAllocation : : Yes )
arguments . append ( " --collect-garbage-on-every-allocation " sv ) ;
2024-04-23 20:39:04 +00:00
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-26 19:44:42 +00:00
arguments . append ( " --image-decoder-socket " sv ) ;
arguments . append ( ByteString : : number ( image_decoder_socket . fd ( ) ) ) ;
2024-08-01 11:13:09 +00:00
return launch_server_process < WebView : : WebContentClient > ( " WebContent " sv , candidate_web_content_paths , move ( arguments ) , 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-26 18:54:57 +00:00
Vector < ByteString > arguments ;
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2024-08-01 11:13:09 +00:00
return launch_server_process < ImageDecoderClient : : Client > ( " ImageDecoder " sv , candidate_image_decoder_paths , arguments ) ;
2023-09-08 10:30:50 +00:00
}
2024-10-07 19:18:07 +00:00
ErrorOr < NonnullRefPtr < Web : : HTML : : WebWorkerClient > > launch_web_worker_process ( ReadonlySpan < ByteString > candidate_web_worker_paths , NonnullRefPtr < Requests : : RequestClient > request_client )
2024-01-06 20:13:59 +00:00
{
2024-07-06 02:41:07 +00:00
Vector < ByteString > arguments ;
2024-10-07 19:18:07 +00:00
auto socket = TRY ( connect_new_request_server_client ( * request_client ) ) ;
arguments . append ( " --request-server-socket " sv ) ;
arguments . append ( ByteString : : number ( socket . fd ( ) ) ) ;
2024-04-15 23:39:48 +00:00
2024-08-01 11:13:09 +00:00
return launch_server_process < Web : : HTML : : WebWorkerClient > ( " WebWorker " sv , candidate_web_worker_paths , move ( arguments ) ) ;
2024-01-06 20:13:59 +00:00
}
2024-08-07 03:51:20 +00:00
ErrorOr < NonnullRefPtr < Requests : : RequestClient > > launch_request_server_process ( ReadonlySpan < ByteString > candidate_request_server_paths , StringView serenity_resource_root )
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-07-30 18:01:05 +00:00
for ( auto const & certificate : WebView : : Application : : chrome_options ( ) . certificates )
2024-04-23 20:39:04 +00:00
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-08-07 03:51:20 +00:00
return launch_server_process < Requests : : RequestClient > ( " RequestServer " sv , candidate_request_server_paths , move ( arguments ) ) ;
2024-04-15 23:39:48 +00:00
}
2024-08-07 03:51:20 +00:00
ErrorOr < IPC : : File > connect_new_request_server_client ( Requests : : 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-06-25 20:57:16 +00:00
TRY ( socket . clear_close_on_exec ( ) ) ;
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
}
2024-06-26 19:44:42 +00:00
ErrorOr < IPC : : File > connect_new_image_decoder_client ( ImageDecoderClient : : Client & client )
{
auto new_socket = client . send_sync_but_allow_failure < Messages : : ImageDecoderServer : : ConnectNewClients > ( 1 ) ;
if ( ! new_socket )
return Error : : from_string_literal ( " Failed to connect to ImageDecoder " ) ;
auto sockets = new_socket - > take_sockets ( ) ;
if ( sockets . size ( ) ! = 1 )
return Error : : from_string_literal ( " Failed to connect to ImageDecoder " ) ;
auto socket = sockets . take_last ( ) ;
TRY ( socket . clear_close_on_exec ( ) ) ;
return socket ;
}