From b1b218596f816821a51fd99c2e7ba9db4a637a39 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 9 Aug 2025 13:07:57 -0400 Subject: [PATCH] LibWeb+WebContent: Add IPC to re-establish RequestServer connections --- Libraries/LibWeb/Loader/ResourceLoader.cpp | 25 ++++++++++++++-- Libraries/LibWeb/Loader/ResourceLoader.h | 6 ++-- Libraries/LibWeb/WebSockets/WebSocket.cpp | 8 +++++- Services/WebContent/ConnectionFromClient.cpp | 6 ++++ Services/WebContent/ConnectionFromClient.h | 2 ++ Services/WebContent/WebContentServer.ipc | 1 + Services/WebContent/main.cpp | 30 ++++++++++++++------ 7 files changed, 65 insertions(+), 13 deletions(-) diff --git a/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Libraries/LibWeb/Loader/ResourceLoader.cpp index 9d3270d9153..df392b62fb2 100644 --- a/Libraries/LibWeb/Loader/ResourceLoader.cpp +++ b/Libraries/LibWeb/Loader/ResourceLoader.cpp @@ -53,6 +53,17 @@ ResourceLoader::ResourceLoader(GC::Heap& heap, NonnullRefPtron_request_server_died = [this]() { + m_request_client = nullptr; + }; +} + +void ResourceLoader::set_client(NonnullRefPtr request_client) +{ + m_request_client = move(request_client); + m_request_client->on_request_server_died = [this]() { + m_request_client = nullptr; + }; } void ResourceLoader::prefetch_dns(URL::URL const& url) @@ -65,7 +76,9 @@ void ResourceLoader::prefetch_dns(URL::URL const& url) return; } - m_request_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly); + // FIXME: We could put this request in a queue until the client connection is re-established. + if (m_request_client) + m_request_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly); } void ResourceLoader::preconnect(URL::URL const& url) @@ -78,7 +91,9 @@ void ResourceLoader::preconnect(URL::URL const& url) return; } - m_request_client->ensure_connection(url, RequestServer::CacheLevel::CreateConnection); + // FIXME: We could put this request in a queue until the client connection is re-established. + if (m_request_client) + m_request_client->ensure_connection(url, RequestServer::CacheLevel::CreateConnection); } static HashMap> s_resource_cache; @@ -531,6 +546,12 @@ RefPtr ResourceLoader::start_network_request(LoadRequest cons if (!headers.contains("User-Agent")) headers.set("User-Agent", m_user_agent.to_byte_string()); + // FIXME: We could put this request in a queue until the client connection is re-established. + if (!m_request_client) { + log_failure(request, "RequestServer is currently unavailable"sv); + return nullptr; + } + auto protocol_request = m_request_client->start_request(request.method(), request.url().value(), headers, request.body(), proxy); if (!protocol_request) { log_failure(request, "Failed to initiate load"sv); diff --git a/Libraries/LibWeb/Loader/ResourceLoader.h b/Libraries/LibWeb/Loader/ResourceLoader.h index 4e4e2a59a76..634280b578e 100644 --- a/Libraries/LibWeb/Loader/ResourceLoader.h +++ b/Libraries/LibWeb/Loader/ResourceLoader.h @@ -24,6 +24,8 @@ public: static void initialize(GC::Heap&, NonnullRefPtr); static ResourceLoader& the(); + void set_client(NonnullRefPtr); + RefPtr load_resource(Resource::Type, LoadRequest&); using SuccessCallback = GC::Function status_code, Optional const& reason_phrase)>; @@ -38,7 +40,7 @@ public: void load_unbuffered(LoadRequest&, GC::Root, GC::Root, GC::Root); - Requests::RequestClient& request_client() { return *m_request_client; } + RefPtr& request_client() { return m_request_client; } void prefetch_dns(URL::URL const&); void preconnect(URL::URL const&); @@ -81,7 +83,7 @@ private: int m_pending_loads { 0 }; GC::Heap& m_heap; - NonnullRefPtr m_request_client; + RefPtr m_request_client; HashTable> m_active_requests; String m_user_agent; diff --git a/Libraries/LibWeb/WebSockets/WebSocket.cpp b/Libraries/LibWeb/WebSockets/WebSocket.cpp index 0d22a31703c..d73f4e83c5a 100644 --- a/Libraries/LibWeb/WebSockets/WebSocket.cpp +++ b/Libraries/LibWeb/WebSockets/WebSocket.cpp @@ -215,7 +215,13 @@ ErrorOr WebSocket::establish_web_socket_connection(URL::URL const& url_rec additional_headers.set("User-Agent", ResourceLoader::the().user_agent().to_byte_string()); - m_websocket = ResourceLoader::the().request_client().websocket_connect(url_record, origin_string, protocol_byte_strings, {}, additional_headers); + auto request_client = ResourceLoader::the().request_client(); + + // FIXME: We could put this request in a queue until the client connection is re-established. + if (!request_client) + return Error::from_string_literal("RequestServer is currently unavailable"); + + m_websocket = request_client->websocket_connect(url_record, origin_string, protocol_byte_strings, {}, additional_headers); m_websocket->on_open = [weak_this = make_weak_ptr()] { if (!weak_this) diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index fffbff1d0f9..f1e2c5d05a1 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -140,6 +140,12 @@ void ConnectionFromClient::connect_to_image_decoder(IPC::File image_decoder_sock on_image_decoder_connection(image_decoder_socket); } +void ConnectionFromClient::connect_to_request_server(IPC::File request_server_socket) +{ + if (on_request_server_connection) + on_request_server_connection(request_server_socket); +} + void ConnectionFromClient::update_system_theme(u64 page_id, Core::AnonymousBuffer theme_buffer) { auto page = this->page(page_id); diff --git a/Services/WebContent/ConnectionFromClient.h b/Services/WebContent/ConnectionFromClient.h index fbed02794ea..a5a52857965 100644 --- a/Services/WebContent/ConnectionFromClient.h +++ b/Services/WebContent/ConnectionFromClient.h @@ -46,6 +46,7 @@ public: PageHost& page_host() { return *m_page_host; } PageHost const& page_host() const { return *m_page_host; } + Function on_request_server_connection; Function on_image_decoder_connection; Queue& input_event_queue() { return m_input_event_queue; } @@ -62,6 +63,7 @@ private: virtual void set_window_handle(u64 page_id, String handle) override; virtual void connect_to_webdriver(u64 page_id, ByteString webdriver_ipc_path) override; virtual void connect_to_web_ui(u64 page_id, IPC::File web_ui_socket) override; + virtual void connect_to_request_server(IPC::File request_server_socket) override; virtual void connect_to_image_decoder(IPC::File image_decoder_socket) override; virtual void update_system_theme(u64 page_id, Core::AnonymousBuffer) override; virtual void update_screen_rects(u64 page_id, Vector, u32) override; diff --git a/Services/WebContent/WebContentServer.ipc b/Services/WebContent/WebContentServer.ipc index 89c29d4c86c..e62d60c0136 100644 --- a/Services/WebContent/WebContentServer.ipc +++ b/Services/WebContent/WebContentServer.ipc @@ -26,6 +26,7 @@ endpoint WebContentServer connect_to_webdriver(u64 page_id, ByteString webdriver_ipc_path) =| connect_to_web_ui(u64 page_id, IPC::File socket_fd) =| + connect_to_request_server(IPC::File request_server_socket) =| connect_to_image_decoder(IPC::File socket_fd) =| update_system_theme(u64 page_id, Core::AnonymousBuffer theme_buffer) =| diff --git a/Services/WebContent/main.cpp b/Services/WebContent/main.cpp index e75df80b887..6d0d4a1cc80 100644 --- a/Services/WebContent/main.cpp +++ b/Services/WebContent/main.cpp @@ -47,7 +47,10 @@ #endif static ErrorOr load_content_filters(StringView config_path); + static ErrorOr initialize_resource_loader(GC::Heap&, int request_server_socket); +static ErrorOr reinitialize_resource_loader(IPC::File const& image_decoder_socket); + static ErrorOr initialize_image_decoder(int image_decoder_socket); static ErrorOr reinitialize_image_decoder(IPC::File const& image_decoder_socket); @@ -219,10 +222,13 @@ ErrorOr ladybird_main(Main::Arguments arguments) auto webcontent_socket = TRY(Core::take_over_socket_from_system_server("WebContent"sv)); auto webcontent_client = TRY(WebContent::ConnectionFromClient::try_create(make(move(webcontent_socket)))); - webcontent_client->on_image_decoder_connection = [&](auto& socket_file) { - auto maybe_error = reinitialize_image_decoder(socket_file); - if (maybe_error.is_error()) - dbgln("Failed to reinitialize image decoder: {}", maybe_error.error()); + webcontent_client->on_request_server_connection = [&](auto const& socket_file) { + if (auto result = reinitialize_resource_loader(socket_file); result.is_error()) + dbgln("Failed to reinitialize resource loader: {}", result.error()); + }; + webcontent_client->on_image_decoder_connection = [&](auto const& socket_file) { + if (auto result = reinitialize_image_decoder(socket_file); result.is_error()) + dbgln("Failed to reinitialize image decoder: {}", result.error()); }; return event_loop.exec(); @@ -255,7 +261,6 @@ static ErrorOr load_content_filters(StringView config_path) ErrorOr initialize_resource_loader(GC::Heap& heap, int request_server_socket) { // TODO: Mach IPC - auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket)); TRY(socket->set_blocking(true)); @@ -264,7 +269,19 @@ ErrorOr initialize_resource_loader(GC::Heap& heap, int request_server_sock auto response = request_client->send_sync(Core::System::getpid()); request_client->transport().set_peer_pid(response->peer_pid()); #endif + Web::ResourceLoader::initialize(heap, move(request_client)); + return {}; +} + +ErrorOr reinitialize_resource_loader(IPC::File const& request_server_socket) +{ + // TODO: Mach IPC + auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket.take_fd())); + TRY(socket->set_blocking(true)); + + auto request_client = TRY(try_make_ref_counted(make(move(socket)))); + Web::ResourceLoader::the().set_client(move(request_client)); return {}; } @@ -282,19 +299,16 @@ ErrorOr initialize_image_decoder(int image_decoder_socket) #endif Web::Platform::ImageCodecPlugin::install(*new WebView::ImageCodecPlugin(move(new_client))); - return {}; } ErrorOr reinitialize_image_decoder(IPC::File const& image_decoder_socket) { // TODO: Mach IPC - auto socket = TRY(Core::LocalSocket::adopt_fd(image_decoder_socket.take_fd())); TRY(socket->set_blocking(true)); auto new_client = TRY(try_make_ref_counted(make(move(socket)))); - static_cast(Web::Platform::ImageCodecPlugin::the()).set_client(move(new_client)); return {};