2023-02-02 07:00:30 -03:00
/*
* Copyright ( c ) 2023 , Andrew Kaster < akaster @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2024-04-23 17:39:04 -03:00
# include <AK/Enumerate.h>
# include <LibCore/Process.h>
2025-12-04 11:59:18 -03:00
# include <LibCore/System.h>
2024-06-30 01:24:01 -03:00
# include <LibWebView/Application.h>
2026-05-22 11:02:42 -03:00
# include <LibWebView/CompositorClient.h>
2024-11-10 12:26:07 -03:00
# include <LibWebView/HelperProcess.h>
# include <LibWebView/Utilities.h>
namespace WebView {
2023-02-02 07:00:30 -03:00
2024-06-04 17:54:43 -03:00
template < typename ClientType , typename . . . ClientArguments >
static ErrorOr < NonnullRefPtr < ClientType > > launch_server_process (
2024-04-23 17:39:04 -03:00
StringView server_name ,
2024-04-27 09:47:02 -03:00
Vector < ByteString > arguments ,
2024-06-04 17:54:43 -03:00
ClientArguments & & . . . client_arguments )
2024-04-23 17:39:04 -03:00
{
2024-08-01 08:03:03 -03:00
auto process_type = WebView : : process_type_from_name ( server_name ) ;
2025-03-15 17:56:52 -03:00
auto const & browser_options = WebView : : Application : : browser_options ( ) ;
2024-08-01 08:03:03 -03:00
2024-11-13 18:04:33 -03:00
auto candidate_server_paths = TRY ( get_paths_for_helper_process ( server_name ) ) ;
2025-03-15 17:56:52 -03:00
if ( browser_options . profile_helper_process = = process_type ) {
2024-04-27 09:47:02 -03:00
arguments . prepend ( {
" --tool=callgrind " sv ,
" --instr-atstart=no " sv ,
" " sv , // Placeholder for the process path.
2024-04-23 17:39:04 -03:00
} ) ;
2024-04-27 09:47:02 -03:00
}
2026-04-09 05:41:02 -03:00
if ( browser_options . debug_helper_processes . contains_slow ( process_type ) )
2024-08-01 08:03:03 -03:00
arguments . append ( " --wait-for-debugger " sv ) ;
2024-04-27 09:47:02 -03:00
for ( auto [ i , path ] : enumerate ( candidate_server_paths ) ) {
Core : : ProcessSpawnOptions options { . name = server_name , . arguments = arguments } ;
2025-03-15 17:56:52 -03:00
if ( browser_options . profile_helper_process = = process_type ) {
2024-04-27 09:47:02 -03:00
options . executable = " valgrind " sv ;
options . search_for_executable_in_path = true ;
arguments [ 2 ] = path ;
} else {
options . executable = path ;
}
2026-01-13 07:23:09 -03:00
bool capture_output = WebView : : Application : : the ( ) . should_capture_web_content_output ( ) ;
auto result = WebView : : Process : : spawn < ClientType > ( process_type , move ( options ) , capture_output , forward < ClientArguments > ( client_arguments ) . . . ) ;
2024-04-23 17:39:04 -03:00
if ( ! result . is_error ( ) ) {
2024-10-22 16:27:15 -03:00
auto & & [ process , client ] = result . release_value ( ) ;
2024-04-23 17:39:04 -03:00
2024-10-22 16:27:15 -03:00
if constexpr ( requires { client - > set_pid ( pid_t { } ) ; } )
client - > set_pid ( process . pid ( ) ) ;
2024-06-18 13:11:51 -03:00
2026-05-21 13:11:05 -03:00
if constexpr ( requires { client - > transport ( ) . set_peer_pid ( 0 ) ; } & & ! IsSame < ClientType , WebWorkerClient > ) {
2025-01-03 13:19:46 -03:00
auto response = client - > template send_sync < typename ClientType : : InitTransport > ( Core : : System : : getpid ( ) ) ;
client - > transport ( ) . set_peer_pid ( response - > peer_pid ( ) ) ;
}
2024-10-22 16:27:15 -03:00
WebView : : Application : : the ( ) . add_child_process ( move ( process ) ) ;
2024-04-23 17:39:04 -03:00
2025-03-15 17:56:52 -03:00
if ( browser_options . profile_helper_process = = process_type ) {
2024-04-27 09:47:02 -03:00
dbgln ( ) ;
2025-05-08 09:06:17 -03:00
dbgln ( " \033 [1;34mLaunched {} process under callgrind! \033 [0m " , server_name ) ;
dbgln ( " \033 [1;36mRun ` \033 [4mcallgrind_control -i on \033 [24m` to start instrumentation and ` \033 [4mcallgrind_control -i off \033 [24m` stop it again. \033 [0m " ) ;
2024-04-27 09:47:02 -03:00
dbgln ( ) ;
}
2024-10-22 16:27:15 -03:00
return move ( client ) ;
2024-04-23 17:39:04 -03: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 ( ) ;
}
2026-05-30 11:58:13 -03:00
ErrorOr < NonnullRefPtr < WebView : : WebContentClient > > launch_web_content_process ( u64 initial_page_id )
2023-02-02 07:00:30 -03:00
{
2025-06-06 16:42:12 -03:00
auto const & browser_options = WebView : : Application : : browser_options ( ) ;
2024-07-30 15:01:05 -03:00
auto const & web_content_options = WebView : : Application : : web_content_options ( ) ;
2026-04-20 18:27:15 -03:00
Vector < ByteString > arguments ;
2023-08-01 14:56:10 -03:00
2025-06-06 16:42:12 -03:00
if ( browser_options . headless_mode . has_value ( ) )
arguments . append ( " --headless " sv ) ;
2024-07-16 13:52:12 -03:00
if ( web_content_options . config_path . has_value ( ) ) {
arguments . append ( " --config-path " sv ) ;
arguments . append ( web_content_options . config_path . value ( ) ) ;
}
2026-01-08 12:09:53 -03:00
if ( web_content_options . is_test_mode = = WebView : : IsTestMode : : Yes )
arguments . append ( " --test-mode " sv ) ;
2024-07-30 15:01:05 -03:00
if ( web_content_options . log_all_js_exceptions = = WebView : : LogAllJSExceptions : : Yes )
2024-04-23 17:39:04 -03:00
arguments . append ( " --log-all-js-exceptions " sv ) ;
2025-03-11 20:25:34 -03:00
if ( web_content_options . disable_site_isolation = = WebView : : DisableSiteIsolation : : Yes )
arguments . append ( " --disable-site-isolation " sv ) ;
2024-07-30 15:01:05 -03:00
if ( web_content_options . enable_idl_tracing = = WebView : : EnableIDLTracing : : Yes )
2024-04-23 17:39:04 -03:00
arguments . append ( " --enable-idl-tracing " sv ) ;
2025-12-01 17:11:27 -03:00
if ( web_content_options . enable_http_memory_cache = = WebView : : EnableMemoryHTTPCache : : Yes )
arguments . append ( " --enable-http-memory-cache " sv ) ;
2026-02-17 15:47:21 -03:00
if ( web_content_options . expose_experimental_interfaces = = WebView : : ExposeExperimentalInterfaces : : Yes )
arguments . append ( " --expose-experimental-interfaces " sv ) ;
2024-07-30 15:01:05 -03:00
if ( web_content_options . expose_internals_object = = WebView : : ExposeInternalsObject : : Yes )
2024-04-23 17:39:04 -03:00
arguments . append ( " --expose-internals-object " sv ) ;
2024-08-01 14:49:24 -03:00
if ( web_content_options . force_cpu_painting = = WebView : : ForceCPUPainting : : Yes )
arguments . append ( " --force-cpu-painting " sv ) ;
2024-08-19 15:35:49 -03:00
if ( web_content_options . force_fontconfig = = WebView : : ForceFontconfig : : Yes )
arguments . append ( " --force-fontconfig " sv ) ;
2024-10-31 12:06:01 -03:00
if ( web_content_options . collect_garbage_on_every_allocation = = WebView : : CollectGarbageOnEveryAllocation : : Yes )
arguments . append ( " --collect-garbage-on-every-allocation " sv ) ;
2024-12-16 08:23:10 -03:00
if ( web_content_options . paint_viewport_scrollbars = = PaintViewportScrollbars : : No )
arguments . append ( " --disable-scrollbar-painting " sv ) ;
2026-05-14 18:29:51 -03:00
if ( web_content_options . enable_async_scrolling = = EnableAsyncScrolling : : No )
arguments . append ( " --disable-async-scrolling " sv ) ;
2026-04-01 17:03:35 -03:00
if ( web_content_options . file_scheme_urls_have_tuple_origins = = FileSchemeUrlsHaveTupleOrigins : : Yes )
2026-02-19 12:41:58 -03:00
arguments . append ( " --tuple-file-origins " sv ) ;
2026-06-13 11:06:49 -03:00
if ( web_content_options . report_session_history_updates_in_test_mode = = ReportSessionHistoryUpdatesInTestMode : : Yes )
arguments . append ( " --report-session-history-updates-in-test-mode " sv ) ;
2026-06-16 10:06:48 -03:00
if ( browser_options . disable_sandbox = = DisableSandbox : : Yes )
arguments . append ( " --disable-sandbox " sv ) ;
2026-02-19 12:41:58 -03:00
2024-12-02 22:46:04 -03:00
if ( auto const maybe_echo_server_port = web_content_options . echo_server_port ; maybe_echo_server_port . has_value ( ) ) {
arguments . append ( " --echo-server-port " sv ) ;
arguments . append ( ByteString : : number ( maybe_echo_server_port . value ( ) ) ) ;
}
2025-10-15 09:17:37 -03:00
if ( web_content_options . default_time_zone . has_value ( ) ) {
arguments . append ( " --default-time-zone " ) ;
arguments . append ( web_content_options . default_time_zone . value ( ) ) ;
}
2026-04-29 14:34:24 -03:00
if ( web_content_options . style_invalidation_counter_dump_interval . has_value ( ) ) {
arguments . append ( " --dump-style-invalidation-counters " sv ) ;
arguments . append ( ByteString : : number ( * web_content_options . style_invalidation_counter_dump_interval ) ) ;
}
2025-10-15 09:17:37 -03:00
2024-04-23 17:39:04 -03:00
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2026-05-30 11:58:13 -03:00
return launch_server_process < WebView : : WebContentClient > ( " WebContent " sv , move ( arguments ) , initial_page_id ) ;
2023-08-01 17:39:19 -03:00
}
2023-08-02 21:13:23 -03:00
2024-11-13 18:04:33 -03:00
ErrorOr < NonnullRefPtr < ImageDecoderClient : : Client > > launch_image_decoder_process ( )
2023-09-08 07:30:50 -03:00
{
2026-05-20 12:19:06 -03:00
auto const & browser_options = WebView : : Application : : browser_options ( ) ;
2024-06-26 15:54:57 -03:00
Vector < ByteString > arguments ;
2026-06-16 10:06:48 -03:00
if ( browser_options . disable_sandbox = = DisableSandbox : : Yes )
arguments . append ( " --disable-sandbox " sv ) ;
2024-06-26 15:54:57 -03:00
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2024-11-13 18:04:33 -03:00
return launch_server_process < ImageDecoderClient : : Client > ( " ImageDecoder " sv , arguments ) ;
2023-09-08 07:30:50 -03:00
}
2026-05-22 11:02:42 -03:00
ErrorOr < NonnullRefPtr < WebView : : CompositorClient > > launch_compositor_process ( )
{
2026-06-09 06:08:46 -03:00
auto const & browser_options = WebView : : Application : : browser_options ( ) ;
2026-05-22 11:02:42 -03:00
auto const & web_content_options = WebView : : Application : : web_content_options ( ) ;
Vector < ByteString > arguments ;
2026-06-16 10:06:48 -03:00
if ( browser_options . disable_sandbox = = DisableSandbox : : Yes )
arguments . append ( " --disable-sandbox " sv ) ;
2026-05-22 11:02:42 -03:00
if ( web_content_options . force_cpu_painting = = WebView : : ForceCPUPainting : : Yes )
arguments . append ( " --force-cpu-painting " sv ) ;
if ( web_content_options . force_fontconfig = = WebView : : ForceFontconfig : : Yes )
arguments . append ( " --force-fontconfig " sv ) ;
if ( web_content_options . enable_async_scrolling = = EnableAsyncScrolling : : No )
arguments . append ( " --disable-async-scrolling " sv ) ;
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
return launch_server_process < WebView : : CompositorClient > ( " Compositor " sv , move ( arguments ) ) ;
}
2026-05-21 13:11:05 -03:00
ErrorOr < NonnullRefPtr < WebWorkerClient > > launch_web_worker_process ( Web : : Bindings : : AgentType type , Web : : HTML : : WorkerAgentId agent_id )
2024-01-06 17:13:59 -03:00
{
2026-06-09 08:26:47 -03:00
auto const & browser_options = WebView : : Application : : browser_options ( ) ;
2026-01-21 09:22:50 -03:00
auto const & web_content_options = WebView : : Application : : web_content_options ( ) ;
2024-07-05 23:41:07 -03:00
Vector < ByteString > arguments ;
2024-10-07 16:18:07 -03:00
2026-06-16 10:06:48 -03:00
if ( browser_options . disable_sandbox = = DisableSandbox : : Yes )
arguments . append ( " --disable-sandbox " sv ) ;
2026-02-17 15:47:21 -03:00
if ( web_content_options . expose_experimental_interfaces = = WebView : : ExposeExperimentalInterfaces : : Yes )
arguments . append ( " --expose-experimental-interfaces " sv ) ;
2026-01-21 09:22:50 -03:00
if ( web_content_options . enable_http_memory_cache = = WebView : : EnableMemoryHTTPCache : : Yes )
arguments . append ( " --enable-http-memory-cache " sv ) ;
2026-04-01 17:03:35 -03:00
if ( web_content_options . file_scheme_urls_have_tuple_origins = = FileSchemeUrlsHaveTupleOrigins : : Yes )
arguments . append ( " --tuple-file-origins " sv ) ;
2026-01-21 09:22:50 -03:00
2025-04-24 02:07:09 -03:00
arguments . append ( " --type " sv ) ;
switch ( type ) {
case Web : : Bindings : : AgentType : : DedicatedWorker :
arguments . append ( " dedicated " sv ) ;
break ;
case Web : : Bindings : : AgentType : : SharedWorker :
arguments . append ( " shared " sv ) ;
break ;
case Web : : Bindings : : AgentType : : ServiceWorker :
arguments . append ( " service " sv ) ;
break ;
default :
VERIFY_NOT_REACHED ( ) ;
}
2026-03-19 15:42:05 -03:00
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2026-05-21 13:11:05 -03:00
return launch_server_process < WebWorkerClient > ( " WebWorker " sv , move ( arguments ) , agent_id ) ;
2024-01-06 17:13:59 -03:00
}
2024-11-13 18:04:33 -03:00
ErrorOr < NonnullRefPtr < Requests : : RequestClient > > launch_request_server_process ( )
2023-08-02 21:13:23 -03:00
{
2026-06-09 06:47:04 -03:00
auto const & browser_options = Application : : browser_options ( ) ;
2025-10-08 22:17:05 -03:00
auto const & request_server_options = Application : : request_server_options ( ) ;
2024-04-23 17:39:04 -03:00
Vector < ByteString > arguments ;
2026-06-16 10:06:48 -03:00
if ( browser_options . disable_sandbox = = DisableSandbox : : Yes )
arguments . append ( " --disable-sandbox " sv ) ;
2025-10-08 22:17:05 -03:00
for ( auto const & certificate : request_server_options . certificates )
2024-04-23 17:39:04 -03:00
arguments . append ( ByteString : : formatted ( " --certificate={} " , certificate ) ) ;
2024-04-15 20:39:48 -03:00
2025-11-18 12:18:40 -03:00
arguments . append ( " --http-disk-cache-mode " sv ) ;
switch ( request_server_options . http_disk_cache_mode ) {
case HTTPDiskCacheMode : : Disabled :
arguments . append ( " disabled " sv ) ;
break ;
case HTTPDiskCacheMode : : Enabled :
arguments . append ( " enabled " sv ) ;
break ;
2026-01-11 13:00:00 -03:00
case HTTPDiskCacheMode : : Partitioned :
arguments . append ( " partitioned " sv ) ;
break ;
2025-11-18 12:18:40 -03:00
case HTTPDiskCacheMode : : Testing :
arguments . append ( " testing " sv ) ;
break ;
}
2025-10-08 22:17:05 -03:00
2024-04-22 13:57:38 -03:00
if ( auto server = mach_server_name ( ) ; server . has_value ( ) ) {
arguments . append ( " --mach-server-name " sv ) ;
arguments . append ( server . value ( ) ) ;
}
2026-01-18 06:13:24 -03:00
if ( request_server_options . resource_substitution_map_path . has_value ( ) )
arguments . append ( ByteString : : formatted ( " --resource-map={} " , * request_server_options . resource_substitution_map_path ) ) ;
2024-11-01 19:53:43 -03:00
auto client = TRY ( launch_server_process < Requests : : RequestClient > ( " RequestServer " sv , move ( arguments ) ) ) ;
2025-10-08 22:17:05 -03:00
2026-02-05 14:25:14 -03:00
auto const & browsing_data_settings = Application : : settings ( ) . browsing_data_settings ( ) ;
client - > async_set_disk_cache_settings ( browsing_data_settings . disk_cache_settings ) ;
Application : : settings ( ) . dns_settings ( ) . visit (
[ ] ( SystemDNS ) { } ,
[ & ] ( DNSOverTLS const & dns_over_tls ) {
2025-05-13 07:34:55 -03:00
dbgln ( " Setting DNS server to {}:{} with TLS ({} local dnssec) " , dns_over_tls . server_address , dns_over_tls . port , dns_over_tls . validate_dnssec_locally ? " with " : " without " ) ;
client - > async_set_dns_server ( dns_over_tls . server_address , dns_over_tls . port , true , dns_over_tls . validate_dnssec_locally ) ;
2024-11-01 19:53:43 -03:00
} ,
2026-02-05 14:25:14 -03:00
[ & ] ( DNSOverUDP const & dns_over_udp ) {
2025-05-13 07:34:55 -03:00
dbgln ( " Setting DNS server to {}:{} ({} local dnssec) " , dns_over_udp . server_address , dns_over_udp . port , dns_over_udp . validate_dnssec_locally ? " with " : " without " ) ;
client - > async_set_dns_server ( dns_over_udp . server_address , dns_over_udp . port , false , dns_over_udp . validate_dnssec_locally ) ;
2024-11-01 19:53:43 -03:00
} ) ;
return client ;
2024-04-15 20:39:48 -03:00
}
2026-03-11 16:10:08 -03:00
ErrorOr < IPC : : TransportHandle > connect_new_request_server_client ( )
2024-04-15 20:39:48 -03:00
{
2026-03-11 16:10:08 -03:00
auto response = Application : : request_server_client ( ) . send_sync_but_allow_failure < Messages : : RequestServer : : ConnectNewClient > ( ) ;
if ( ! response )
2024-04-15 20:39:48 -03:00
return Error : : from_string_literal ( " Failed to connect to RequestServer " ) ;
2026-03-12 10:18:49 -03:00
return response - > take_handle ( ) ;
2023-08-02 21:13:23 -03:00
}
2024-06-26 16:44:42 -03:00
2026-03-11 16:10:08 -03:00
ErrorOr < IPC : : TransportHandle > connect_new_image_decoder_client ( )
2024-06-26 16:44:42 -03:00
{
2026-03-11 16:10:08 -03:00
auto response = Application : : image_decoder_client ( ) . send_sync_but_allow_failure < Messages : : ImageDecoderServer : : ConnectNewClients > ( 1 ) ;
if ( ! response )
2024-06-26 16:44:42 -03:00
return Error : : from_string_literal ( " Failed to connect to ImageDecoder " ) ;
2026-03-11 16:10:08 -03:00
auto handles = response - > take_handles ( ) ;
if ( handles . size ( ) ! = 1 )
2024-06-26 16:44:42 -03:00
return Error : : from_string_literal ( " Failed to connect to ImageDecoder " ) ;
2026-03-12 10:18:49 -03:00
return handles . take_last ( ) ;
2024-06-26 16:44:42 -03:00
}
2024-11-10 12:26:07 -03:00
}