diff --git a/Userland/Applications/Browser/DownloadWidget.cpp b/Userland/Applications/Browser/DownloadWidget.cpp index cfd2c82f8b..cfc6df68dd 100644 --- a/Userland/Applications/Browser/DownloadWidget.cpp +++ b/Userland/Applications/Browser/DownloadWidget.cpp @@ -23,7 +23,6 @@ #include #include -#include namespace Browser { @@ -41,7 +40,7 @@ DownloadWidget::DownloadWidget(const URL& url) auto close_on_finish = Config::read_bool("Browser", "Preferences", "CloseDownloadWidgetOnFinish", false); m_elapsed_timer.start(); - m_download = Web::ResourceLoader::the().protocol_client().start_request("GET", url); + m_download = Web::ResourceLoader::the().connector().start_request("GET", url); VERIFY(m_download); m_download->on_progress = [this](Optional total_size, u32 downloaded_size) { did_progress(total_size.value(), downloaded_size); diff --git a/Userland/Applications/Browser/DownloadWidget.h b/Userland/Applications/Browser/DownloadWidget.h index c4b8604856..21fc7641ab 100644 --- a/Userland/Applications/Browser/DownloadWidget.h +++ b/Userland/Applications/Browser/DownloadWidget.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace Browser { @@ -31,7 +31,7 @@ private: URL m_url; String m_destination_path; - RefPtr m_download; + RefPtr m_download; RefPtr m_progressbar; RefPtr m_progress_label; RefPtr m_cancel_button; diff --git a/Userland/Applications/Browser/main.cpp b/Userland/Applications/Browser/main.cpp index 3d4665c209..65c9cd5aab 100644 --- a/Userland/Applications/Browser/main.cpp +++ b/Userland/Applications/Browser/main.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include namespace Browser { @@ -87,6 +89,8 @@ ErrorOr serenity_main(Main::Arguments arguments) TRY(Core::System::unveil("/bin/BrowserSettings", "x")); TRY(Core::System::unveil(nullptr, nullptr)); + Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create())); + auto app_icon = GUI::Icon::default_icon("app-browser"); Browser::g_home_url = Config::read_string("Browser", "Preferences", "Home", "file:///res/html/misc/welcome.html"); diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index c34632302a..9e10768eef 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -359,11 +359,6 @@ set(SOURCES XML/XMLDocumentBuilder.cpp ) -set(GENERATED_SOURCES - ../../Services/RequestServer/RequestClientEndpoint.h - ../../Services/RequestServer/RequestServerEndpoint.h -) - generate_css_implementation() set(GENERATED_SOURCES @@ -377,7 +372,7 @@ set(GENERATED_SOURCES ) serenity_lib(LibWeb web) -target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibProtocol LibWasm LibXML) +target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibWasm LibXML) link_with_unicode_data(LibWeb) generate_js_wrappers(LibWeb) diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp index e45ae44d27..c79b17ea8e 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2022, Dex♪ * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,8 +11,6 @@ #include #include #include -#include -#include #include #include #include @@ -24,35 +23,50 @@ namespace Web { +ResourceLoaderConnectorRequest::ResourceLoaderConnectorRequest() = default; + +ResourceLoaderConnectorRequest::~ResourceLoaderConnectorRequest() = default; + +ResourceLoaderConnector::ResourceLoaderConnector() = default; + +ResourceLoaderConnector::~ResourceLoaderConnector() = default; + +static RefPtr s_resource_loader; + +void ResourceLoader::initialize(RefPtr connector) +{ + if (connector) + s_resource_loader = ResourceLoader::try_create(connector.release_nonnull()).release_value_but_fixme_should_propagate_errors(); +} + ResourceLoader& ResourceLoader::the() { - static RefPtr s_the; - if (!s_the) - s_the = ResourceLoader::try_create().release_value_but_fixme_should_propagate_errors(); - return *s_the; + if (!s_resource_loader) { + dbgln("Web::ResourceLoader was not initialized"); + VERIFY_NOT_REACHED(); + } + return *s_resource_loader; } -ErrorOr> ResourceLoader::try_create() +ErrorOr> ResourceLoader::try_create(NonnullRefPtr connector) { - - auto protocol_client = TRY(Protocol::RequestClient::try_create()); - return adopt_nonnull_ref_or_enomem(new (nothrow) ResourceLoader(move(protocol_client))); + return adopt_nonnull_ref_or_enomem(new (nothrow) ResourceLoader(move(connector))); } -ResourceLoader::ResourceLoader(NonnullRefPtr protocol_client) - : m_protocol_client(move(protocol_client)) +ResourceLoader::ResourceLoader(NonnullRefPtr connector) + : m_connector(move(connector)) , m_user_agent(default_user_agent) { } void ResourceLoader::prefetch_dns(AK::URL const& url) { - m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly); + m_connector->prefetch_dns(url); } void ResourceLoader::preconnect(AK::URL const& url) { - m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::CreateConnection); + m_connector->preconnect(url); } static HashMap> s_resource_cache; @@ -217,7 +231,7 @@ void ResourceLoader::load(LoadRequest& request, Functionstart_request(request.method(), url, headers, request.body(), proxy); if (!protocol_request) { auto start_request_failure_msg = "Failed to initiate load"sv; log_failure(request, start_request_failure_msg); @@ -248,7 +262,7 @@ void ResourceLoader::load(LoadRequest& request, Functionset_should_buffer_all_input(true); - protocol_request->on_certificate_requested = []() -> Protocol::Request::CertificateAndKey { + protocol_request->on_certificate_requested = []() -> ResourceLoaderConnectorRequest::CertificateAndKey { return {}; }; ++m_pending_loads; diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h index 59cce5bd75..986447316a 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2022, Dex♪ * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,15 +8,13 @@ #pragma once #include +#include +#include #include #include +#include #include -namespace Protocol { -class RequestClient; -class Request; -} - namespace Web { #if ARCH(I386) @@ -26,9 +25,46 @@ namespace Web { constexpr auto default_user_agent = "Mozilla/5.0 (SerenityOS; " CPU_STRING ") LibWeb+LibJS/1.0 Browser/1.0"; +class ResourceLoaderConnectorRequest : public RefCounted { +public: + virtual ~ResourceLoaderConnectorRequest(); + + struct CertificateAndKey { + String certificate; + String key; + }; + + virtual void set_should_buffer_all_input(bool) = 0; + virtual bool stop() = 0; + + virtual void stream_into(Core::Stream::Stream&) = 0; + + Function const& response_headers, Optional response_code, ReadonlyBytes payload)> on_buffered_request_finish; + Function on_finish; + Function total_size, u32 downloaded_size)> on_progress; + Function on_certificate_requested; + +protected: + explicit ResourceLoaderConnectorRequest(); +}; + +class ResourceLoaderConnector : public RefCounted { +public: + virtual ~ResourceLoaderConnector(); + + virtual void prefetch_dns(AK::URL const&) = 0; + virtual void preconnect(AK::URL const&) = 0; + + virtual RefPtr start_request(String const& method, AK::URL const&, HashMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) = 0; + +protected: + explicit ResourceLoaderConnector(); +}; + class ResourceLoader : public Core::Object { C_OBJECT_ABSTRACT(ResourceLoader) public: + static void initialize(RefPtr); static ResourceLoader& the(); RefPtr load_resource(Resource::Type, LoadRequest&); @@ -36,6 +72,8 @@ public: void load(LoadRequest&, Function const& response_headers, Optional status_code)> success_callback, Function status_code)> error_callback = nullptr); void load(const AK::URL&, Function const& response_headers, Optional status_code)> success_callback, Function status_code)> error_callback = nullptr); + ResourceLoaderConnector& connector() { return *m_connector; } + void prefetch_dns(AK::URL const&); void preconnect(AK::URL const&); @@ -43,8 +81,6 @@ public: int pending_loads() const { return m_pending_loads; } - Protocol::RequestClient& protocol_client() { return *m_protocol_client; } - String const& user_agent() const { return m_user_agent; } void set_user_agent(String const& user_agent) { m_user_agent = user_agent; } @@ -52,15 +88,15 @@ public: void evict_from_cache(LoadRequest const&); private: - ResourceLoader(NonnullRefPtr protocol_client); - static ErrorOr> try_create(); + ResourceLoader(NonnullRefPtr); + static ErrorOr> try_create(NonnullRefPtr); static bool is_port_blocked(int port); int m_pending_loads { 0 }; - HashTable> m_active_requests; - RefPtr m_protocol_client; + HashTable> m_active_requests; + NonnullRefPtr m_connector; String m_user_agent; }; diff --git a/Userland/Libraries/LibWebView/CMakeLists.txt b/Userland/Libraries/LibWebView/CMakeLists.txt index 4fa461b816..77852b5ed6 100644 --- a/Userland/Libraries/LibWebView/CMakeLists.txt +++ b/Userland/Libraries/LibWebView/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES DOMTreeModel.cpp ImageDecoderClientAdapter.cpp OutOfProcessWebView.cpp + RequestServerAdapter.cpp StylePropertiesModel.cpp WebContentClient.cpp WebSocketClientAdapter.cpp diff --git a/Userland/Libraries/LibWebView/RequestServerAdapter.cpp b/Userland/Libraries/LibWebView/RequestServerAdapter.cpp new file mode 100644 index 0000000000..be2374d869 --- /dev/null +++ b/Userland/Libraries/LibWebView/RequestServerAdapter.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022, Dex♪ + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace WebView { + +ErrorOr> RequestServerRequestAdapter::try_create(NonnullRefPtr request) +{ + return adopt_nonnull_ref_or_enomem(new (nothrow) RequestServerRequestAdapter(move(request))); +} + +RequestServerRequestAdapter::RequestServerRequestAdapter(NonnullRefPtr request) + : m_request(request) +{ + request->on_buffered_request_finish = [weak_this = make_weak_ptr()](auto success, auto total_size, auto const& response_headers, auto response_code, auto payload) { + if (auto strong_this = weak_this.strong_ref()) + if (strong_this->on_buffered_request_finish) + strong_this->on_buffered_request_finish(success, total_size, response_headers, response_code, move(payload)); + }; + + request->on_finish = [weak_this = make_weak_ptr()](bool success, u32 total_size) { + if (auto strong_this = weak_this.strong_ref()) + if (strong_this->on_finish) + strong_this->on_finish(success, total_size); + }; + + request->on_progress = [weak_this = make_weak_ptr()](Optional total_size, u32 downloaded_size) { + if (auto strong_this = weak_this.strong_ref()) + if (strong_this->on_progress) + strong_this->on_progress(total_size, downloaded_size); + }; + + request->on_certificate_requested = [weak_this = make_weak_ptr()]() { + if (auto strong_this = weak_this.strong_ref()) { + if (strong_this->on_certificate_requested) { + auto certificate_and_key = strong_this->on_certificate_requested(); + return Protocol::Request::CertificateAndKey { + .certificate = move(certificate_and_key.certificate), + .key = move(certificate_and_key.key), + }; + } + } + + return Protocol::Request::CertificateAndKey {}; + }; +} + +RequestServerRequestAdapter::~RequestServerRequestAdapter() = default; + +void RequestServerRequestAdapter::set_should_buffer_all_input(bool should_buffer_all_input) +{ + m_request->set_should_buffer_all_input(should_buffer_all_input); +} + +bool RequestServerRequestAdapter::stop() +{ + return m_request->stop(); +} + +void RequestServerRequestAdapter::stream_into(Core::Stream::Stream& stream) +{ + m_request->stream_into(stream); +} + +ErrorOr> RequestServerAdapter::try_create() +{ + auto protocol_client = TRY(Protocol::RequestClient::try_create()); + return adopt_nonnull_ref_or_enomem(new (nothrow) RequestServerAdapter(move(protocol_client))); +} + +RequestServerAdapter::RequestServerAdapter(NonnullRefPtr protocol_client) + : m_protocol_client(protocol_client) +{ +} + +RequestServerAdapter::~RequestServerAdapter() = default; + +RefPtr RequestServerAdapter::start_request(String const& method, URL const& url, HashMap const& headers, ReadonlyBytes body, Core::ProxyData const& proxy) +{ + auto protocol_request = m_protocol_client->start_request(method, url, headers, body, proxy); + if (!protocol_request) + return {}; + return RequestServerRequestAdapter::try_create(protocol_request.release_nonnull()).release_value_but_fixme_should_propagate_errors(); +} + +void RequestServerAdapter::prefetch_dns(AK::URL const& url) +{ + m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly); +} + +void RequestServerAdapter::preconnect(AK::URL const& url) +{ + m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::CreateConnection); +} + +} diff --git a/Userland/Libraries/LibWebView/RequestServerAdapter.h b/Userland/Libraries/LibWebView/RequestServerAdapter.h new file mode 100644 index 0000000000..0aca3dbdcb --- /dev/null +++ b/Userland/Libraries/LibWebView/RequestServerAdapter.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Dex♪ + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Protocol { +class Request; +class RequestClient; +} + +namespace WebView { + +class RequestServerRequestAdapter + : public Web::ResourceLoaderConnectorRequest + , public Weakable { +public: + static ErrorOr> try_create(NonnullRefPtr); + virtual ~RequestServerRequestAdapter() override; + + virtual void set_should_buffer_all_input(bool) override; + virtual bool stop() override; + + virtual void stream_into(Core::Stream::Stream&) override; + +private: + RequestServerRequestAdapter(NonnullRefPtr); + NonnullRefPtr m_request; +}; + +class RequestServerAdapter : public Web::ResourceLoaderConnector { +public: + static ErrorOr> try_create(); + virtual ~RequestServerAdapter() override; + + virtual void prefetch_dns(AK::URL const& url) override; + virtual void preconnect(AK::URL const& url) override; + + virtual RefPtr start_request(String const& method, URL const&, HashMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) override; + +private: + RequestServerAdapter(NonnullRefPtr protocol_client); + + RefPtr m_protocol_client; +}; + +} diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp index b7bfccf6e4..290a34b9a2 100644 --- a/Userland/Services/WebContent/main.cpp +++ b/Userland/Services/WebContent/main.cpp @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -28,6 +30,7 @@ ErrorOr serenity_main(Main::Arguments) Web::ImageDecoding::Decoder::initialize(WebView::ImageDecoderClientAdapter::create()); Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create())); + Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create())); auto client = TRY(IPC::take_over_accepted_client_from_system_server()); return event_loop.exec();