LibWebView+LibWeb: Remove ResourceLoader and WebSocket adapters

These were used to provide a layer of abstraction between ResourceLoader
and the networking backend. Now that we only have RequestServer, we can
remove these adapters to make the code a bit easier to follow.
This commit is contained in:
Timothy Flynn 2024-10-07 16:07:48 -04:00 committed by Andreas Kling
parent 3de86cf0fa
commit 00487a7b25
Notes: github-actions[bot] 2024-10-08 04:53:41 +00:00
12 changed files with 48 additions and 463 deletions

View file

@ -28,7 +28,6 @@
#include <LibWeb/PermissionsPolicy/AutoplayAllowlist.h>
#include <LibWeb/Platform/AudioCodecPluginAgnostic.h>
#include <LibWeb/Platform/EventLoopPluginSerenity.h>
#include <LibWebView/RequestServerAdapter.h>
#include <WebContent/ConnectionFromClient.h>
#include <WebContent/PageClient.h>
#include <WebContent/WebDriverConnection.h>
@ -48,7 +47,7 @@
static ErrorOr<void> load_content_filters(StringView config_path);
static ErrorOr<void> load_autoplay_allowlist(StringView config_path);
static ErrorOr<void> initialize_lagom_networking(int request_server_socket);
static ErrorOr<void> initialize_resource_loader(int request_server_socket);
static ErrorOr<void> initialize_image_decoder(int image_decoder_socket);
static ErrorOr<void> reinitialize_image_decoder(IPC::File const& image_decoder_socket);
@ -163,7 +162,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
}
#endif
TRY(initialize_lagom_networking(request_server_socket));
TRY(initialize_resource_loader(request_server_socket));
TRY(initialize_image_decoder(image_decoder_socket));
Web::HTML::Window::set_internals_object_exposed(expose_internals_object);
@ -248,14 +247,14 @@ static ErrorOr<void> load_autoplay_allowlist(StringView config_path)
return {};
}
ErrorOr<void> initialize_lagom_networking(int request_server_socket)
ErrorOr<void> initialize_resource_loader(int request_server_socket)
{
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket));
TRY(socket->set_blocking(true));
auto new_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(socket)));
auto request_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(socket)));
Web::ResourceLoader::initialize(move(request_client));
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(new_client))));
return {};
}

View file

@ -22,8 +22,6 @@
#include <LibWeb/Platform/EventLoopPlugin.h>
#include <LibWeb/Platform/EventLoopPluginSerenity.h>
#include <LibWeb/WebSockets/WebSocket.h>
#include <LibWebView/RequestServerAdapter.h>
#include <LibWebView/WebSocketClientAdapter.h>
#include <WebWorker/ConnectionFromClient.h>
#if defined(HAVE_QT)
@ -31,7 +29,7 @@
# include <QCoreApplication>
#endif
static ErrorOr<void> initialize_lagom_networking(int request_server_socket);
static ErrorOr<void> initialize_resource_loader(int request_server_socket);
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
@ -64,7 +62,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(false));
TRY(initialize_lagom_networking(request_server_socket));
TRY(initialize_resource_loader(request_server_socket));
TRY(Web::Bindings::initialize_main_thread_vm(Web::HTML::EventLoop::Type::Worker));
@ -73,14 +71,13 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return event_loop.exec();
}
static ErrorOr<void> initialize_lagom_networking(int request_server_socket)
static ErrorOr<void> initialize_resource_loader(int request_server_socket)
{
auto socket = TRY(Core::LocalSocket::adopt_fd(request_server_socket));
TRY(socket->set_blocking(true));
auto new_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(socket)));
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(new_client))));
auto request_client = TRY(try_make_ref_counted<Requests::RequestClient>(move(socket)));
Web::ResourceLoader::initialize(move(request_client));
return {};
}

View file

@ -152,14 +152,12 @@ shared_library("LibWebView") {
"Process.cpp",
"ProcessHandle.cpp",
"ProcessManager.cpp",
"RequestServerAdapter.cpp",
"SearchEngine.cpp",
"SourceHighlighter.cpp",
"URL.cpp",
"UserAgent.cpp",
"ViewImplementation.cpp",
"WebContentClient.cpp",
"WebSocketClientAdapter.cpp",
]
sources += get_target_outputs(":WebContentClientEndpoint") +
get_target_outputs(":WebContentServerEndpoint") +

View file

@ -8,9 +8,10 @@
#include <AK/Debug.h>
#include <LibCore/DateTime.h>
#include <LibCore/Directory.h>
#include <LibCore/ElapsedTimer.h>
#include <LibCore/MimeData.h>
#include <LibCore/Resource.h>
#include <LibRequests/Request.h>
#include <LibRequests/RequestClient.h>
#include <LibWeb/Cookie/Cookie.h>
#include <LibWeb/Cookie/ParsedCookie.h>
#include <LibWeb/Fetch/Infrastructure/URL.h>
@ -20,25 +21,17 @@
#include <LibWeb/Loader/ProxyMappings.h>
#include <LibWeb/Loader/Resource.h>
#include <LibWeb/Loader/ResourceLoader.h>
#include <LibWeb/Page/Page.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
#include <LibWeb/Platform/Timer.h>
namespace Web {
ResourceLoaderConnectorRequest::ResourceLoaderConnectorRequest() = default;
ResourceLoaderConnectorRequest::~ResourceLoaderConnectorRequest() = default;
ResourceLoaderConnector::ResourceLoaderConnector() = default;
ResourceLoaderConnector::~ResourceLoaderConnector() = default;
static RefPtr<ResourceLoader> s_resource_loader;
void ResourceLoader::initialize(RefPtr<ResourceLoaderConnector> connector)
void ResourceLoader::initialize(NonnullRefPtr<Requests::RequestClient> request_client)
{
if (connector)
s_resource_loader = ResourceLoader::try_create(connector.release_nonnull()).release_value_but_fixme_should_propagate_errors();
s_resource_loader = adopt_ref(*new ResourceLoader(move(request_client)));
}
ResourceLoader& ResourceLoader::the()
@ -50,13 +43,8 @@ ResourceLoader& ResourceLoader::the()
return *s_resource_loader;
}
ErrorOr<NonnullRefPtr<ResourceLoader>> ResourceLoader::try_create(NonnullRefPtr<ResourceLoaderConnector> connector)
{
return adopt_nonnull_ref_or_enomem(new (nothrow) ResourceLoader(move(connector)));
}
ResourceLoader::ResourceLoader(NonnullRefPtr<ResourceLoaderConnector> connector)
: m_connector(move(connector))
ResourceLoader::ResourceLoader(NonnullRefPtr<Requests::RequestClient> request_client)
: m_request_client(move(request_client))
, m_user_agent(MUST(String::from_utf8(default_user_agent)))
, m_platform(MUST(String::from_utf8(default_platform)))
, m_preferred_languages({ "en-US"_string })
@ -74,7 +62,7 @@ void ResourceLoader::prefetch_dns(URL::URL const& url)
return;
}
m_connector->prefetch_dns(url);
m_request_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly);
}
void ResourceLoader::preconnect(URL::URL const& url)
@ -87,7 +75,7 @@ void ResourceLoader::preconnect(URL::URL const& url)
return;
}
m_connector->preconnect(url);
m_request_client->ensure_connection(url, RequestServer::CacheLevel::CreateConnection);
}
static HashMap<LoadRequest, NonnullRefPtr<Resource>> s_resource_cache;
@ -487,7 +475,7 @@ void ResourceLoader::load_unbuffered(LoadRequest& request, OnHeadersReceived on_
protocol_request->set_unbuffered_request_callbacks(move(protocol_headers_received), move(protocol_data_received), move(protocol_complete));
}
RefPtr<ResourceLoaderConnectorRequest> ResourceLoader::start_network_request(LoadRequest const& request)
RefPtr<Requests::Request> ResourceLoader::start_network_request(LoadRequest const& request)
{
auto proxy = ProxyMappings::the().proxy_for_url(request.url());
@ -500,13 +488,13 @@ RefPtr<ResourceLoaderConnectorRequest> ResourceLoader::start_network_request(Loa
if (!headers.contains("User-Agent"))
headers.set("User-Agent", m_user_agent.to_byte_string());
auto protocol_request = m_connector->start_request(request.method(), request.url(), headers, request.body(), proxy);
auto protocol_request = m_request_client->start_request(request.method(), request.url(), headers, request.body(), proxy);
if (!protocol_request) {
log_failure(request, "Failed to initiate load"sv);
return nullptr;
}
protocol_request->on_certificate_requested = []() -> ResourceLoaderConnectorRequest::CertificateAndKey {
protocol_request->on_certificate_requested = []() -> Requests::Request::CertificateAndKey {
return {};
};
@ -535,7 +523,7 @@ void ResourceLoader::handle_network_response_headers(LoadRequest const& request,
}
}
void ResourceLoader::finish_network_request(NonnullRefPtr<ResourceLoaderConnectorRequest> const& protocol_request)
void ResourceLoader::finish_network_request(NonnullRefPtr<Requests::Request> const& protocol_request)
{
--m_pending_loads;
if (on_load_counter_change)

View file

@ -9,66 +9,20 @@
#include <AK/ByteString.h>
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/HashTable.h>
#include <LibCore/EventReceiver.h>
#include <LibCore/Proxy.h>
#include <LibJS/SafeFunction.h>
#include <LibRequests/Request.h>
#include <LibRequests/Forward.h>
#include <LibURL/URL.h>
#include <LibWeb/Loader/Resource.h>
#include <LibWeb/Loader/UserAgent.h>
#include <LibWeb/Page/Page.h>
namespace Web {
namespace WebSockets {
class WebSocketClientSocket;
}
class ResourceLoaderConnectorRequest : public RefCounted<ResourceLoaderConnectorRequest> {
public:
virtual ~ResourceLoaderConnectorRequest();
struct CertificateAndKey {
ByteString certificate;
ByteString key;
};
// Configure the request such that the entirety of the response data is buffered. The callback receives that data and
// the response headers all at once. Using this method is mutually exclusive with `set_unbuffered_data_received_callback`.
virtual void set_buffered_request_finished_callback(Requests::Request::BufferedRequestFinished) = 0;
// Configure the request such that the response data is provided unbuffered as it is received. Using this method is
// mutually exclusive with `set_buffered_request_finished_callback`.
virtual void set_unbuffered_request_callbacks(Requests::Request::HeadersReceived, Requests::Request::DataReceived, Requests::Request::RequestFinished) = 0;
virtual bool stop() = 0;
Function<void(Optional<u64> total_size, u64 downloaded_size)> on_progress;
Function<CertificateAndKey()> on_certificate_requested;
protected:
explicit ResourceLoaderConnectorRequest();
};
class ResourceLoaderConnector : public RefCounted<ResourceLoaderConnector> {
public:
virtual ~ResourceLoaderConnector();
virtual void prefetch_dns(URL::URL const&) = 0;
virtual void preconnect(URL::URL const&) = 0;
virtual RefPtr<ResourceLoaderConnectorRequest> start_request(ByteString const& method, URL::URL const&, HTTP::HeaderMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) = 0;
virtual RefPtr<Web::WebSockets::WebSocketClientSocket> websocket_connect(const URL::URL&, ByteString const& origin, Vector<ByteString> const& protocols) = 0;
protected:
explicit ResourceLoaderConnector();
};
class ResourceLoader : public Core::EventReceiver {
C_OBJECT_ABSTRACT(ResourceLoader)
public:
static void initialize(RefPtr<ResourceLoaderConnector>);
static void initialize(NonnullRefPtr<Requests::RequestClient>);
static ResourceLoader& the();
RefPtr<Resource> load_resource(Resource::Type, LoadRequest&);
@ -85,7 +39,7 @@ public:
void load_unbuffered(LoadRequest&, OnHeadersReceived, OnDataReceived, OnComplete);
ResourceLoaderConnector& connector() { return *m_connector; }
Requests::RequestClient& request_client() { return *m_request_client; }
void prefetch_dns(URL::URL const&);
void preconnect(URL::URL const&);
@ -121,17 +75,17 @@ public:
void evict_from_cache(LoadRequest const&);
private:
ResourceLoader(NonnullRefPtr<ResourceLoaderConnector>);
static ErrorOr<NonnullRefPtr<ResourceLoader>> try_create(NonnullRefPtr<ResourceLoaderConnector>);
explicit ResourceLoader(NonnullRefPtr<Requests::RequestClient>);
RefPtr<ResourceLoaderConnectorRequest> start_network_request(LoadRequest const&);
RefPtr<Requests::Request> start_network_request(LoadRequest const&);
void handle_network_response_headers(LoadRequest const&, HTTP::HeaderMap const&);
void finish_network_request(NonnullRefPtr<ResourceLoaderConnectorRequest> const&);
void finish_network_request(NonnullRefPtr<Requests::Request> const&);
int m_pending_loads { 0 };
HashTable<NonnullRefPtr<ResourceLoaderConnectorRequest>> m_active_requests;
NonnullRefPtr<ResourceLoaderConnector> m_connector;
NonnullRefPtr<Requests::RequestClient> m_request_client;
HashTable<NonnullRefPtr<Requests::Request>> m_active_requests;
String m_user_agent;
String m_platform;
Vector<String> m_preferred_languages = { "en"_string };

View file

@ -8,6 +8,7 @@
#include <AK/QuickSort.h>
#include <LibJS/Runtime/ArrayBuffer.h>
#include <LibJS/Runtime/FunctionObject.h>
#include <LibRequests/RequestClient.h>
#include <LibURL/Origin.h>
#include <LibWeb/Bindings/WebSocketPrototype.h>
#include <LibWeb/DOM/Document.h>
@ -32,8 +33,6 @@ namespace Web::WebSockets {
JS_DEFINE_ALLOCATOR(WebSocket);
WebSocketClientSocket::~WebSocketClientSocket() = default;
// https://websockets.spec.whatwg.org/#dom-websocket-websocket
WebIDL::ExceptionOr<JS::NonnullGCPtr<WebSocket>> WebSocket::construct_impl(JS::Realm& realm, String const& url, Optional<Variant<String, Vector<String>>> const& protocols)
{
@ -131,7 +130,8 @@ ErrorOr<void> WebSocket::establish_web_socket_connection(URL::URL& url_record, V
for (auto const& protocol : protocols)
TRY(protcol_byte_strings.try_append(protocol.to_byte_string()));
m_websocket = ResourceLoader::the().connector().websocket_connect(url_record, origin_string, protcol_byte_strings);
m_websocket = ResourceLoader::the().request_client().websocket_connect(url_record, origin_string, protcol_byte_strings);
m_websocket->on_open = [weak_this = make_weak_ptr<WebSocket>()] {
if (!weak_this)
return;
@ -161,11 +161,11 @@ ErrorOr<void> WebSocket::establish_web_socket_connection(URL::URL& url_record, V
}
// https://websockets.spec.whatwg.org/#dom-websocket-readystate
WebSocket::ReadyState WebSocket::ready_state() const
Requests::WebSocket::ReadyState WebSocket::ready_state() const
{
if (!m_websocket)
return WebSocket::ReadyState::Closed;
return const_cast<WebSocketClientSocket&>(*m_websocket).ready_state();
if (m_websocket)
return m_websocket->ready_state();
return Requests::WebSocket::ReadyState::Closed;
}
// https://websockets.spec.whatwg.org/#dom-websocket-extensions
@ -202,7 +202,7 @@ WebIDL::ExceptionOr<void> WebSocket::close(Optional<u16> code, Optional<String>
// 3. Run the first matching steps from the following list:
auto state = ready_state();
// -> If this's ready state is CLOSING (2) or CLOSED (3)
if (state == WebSocket::ReadyState::Closing || state == WebSocket::ReadyState::Closed)
if (state == Requests::WebSocket::ReadyState::Closing || state == Requests::WebSocket::ReadyState::Closed)
return {};
// -> If the WebSocket connection is not yet established [WSP]
// -> If the WebSocket closing handshake has not yet been started [WSP]
@ -217,9 +217,9 @@ WebIDL::ExceptionOr<void> WebSocket::close(Optional<u16> code, Optional<String>
WebIDL::ExceptionOr<void> WebSocket::send(Variant<JS::Handle<WebIDL::BufferSource>, JS::Handle<FileAPI::Blob>, String> const& data)
{
auto state = ready_state();
if (state == WebSocket::ReadyState::Connecting)
if (state == Requests::WebSocket::ReadyState::Connecting)
return WebIDL::InvalidStateError::create(realm(), "Websocket is still CONNECTING"_fly_string);
if (state == WebSocket::ReadyState::Open) {
if (state == Requests::WebSocket::ReadyState::Open) {
TRY_OR_THROW_OOM(vm(),
data.visit(
[this](String const& string) -> ErrorOr<void> {
@ -274,7 +274,7 @@ void WebSocket::on_close(u16 code, String reason, bool was_clean)
// https://websockets.spec.whatwg.org/#feedback-from-the-protocol
void WebSocket::on_message(ByteBuffer message, bool is_text)
{
if (m_websocket->ready_state() != WebSocket::ReadyState::Open)
if (m_websocket->ready_state() != Requests::WebSocket::ReadyState::Open)
return;
if (is_text) {
auto text_message = ByteString(ReadonlyBytes(message));

View file

@ -9,6 +9,8 @@
#include <AK/ByteBuffer.h>
#include <LibCore/EventReceiver.h>
#include <LibRequests/Forward.h>
#include <LibRequests/WebSocket.h>
#include <LibURL/URL.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/DOM/EventTarget.h>
@ -24,21 +26,11 @@
namespace Web::WebSockets {
class WebSocketClientSocket;
class WebSocketClientManager;
class WebSocket final : public DOM::EventTarget {
WEB_PLATFORM_OBJECT(WebSocket, DOM::EventTarget);
JS_DECLARE_ALLOCATOR(WebSocket);
public:
enum class ReadyState : u16 {
Connecting = 0,
Open = 1,
Closing = 2,
Closed = 3,
};
static WebIDL::ExceptionOr<JS::NonnullGCPtr<WebSocket>> construct_impl(JS::Realm&, String const& url, Optional<Variant<String, Vector<String>>> const& protocols);
virtual ~WebSocket() override;
@ -53,7 +45,7 @@ public:
ENUMERATE_WEBSOCKET_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE
ReadyState ready_state() const;
Requests::WebSocket::ReadyState ready_state() const;
String extensions() const;
WebIDL::ExceptionOr<String> protocol() const;
@ -77,44 +69,7 @@ private:
URL::URL m_url;
String m_binary_type { "blob"_string };
RefPtr<WebSocketClientSocket> m_websocket;
};
class WebSocketClientSocket : public RefCounted<WebSocketClientSocket> {
public:
virtual ~WebSocketClientSocket();
struct CertificateAndKey {
ByteString certificate;
ByteString key;
};
struct Message {
ByteBuffer data;
bool is_text { false };
};
enum class Error {
CouldNotEstablishConnection,
ConnectionUpgradeFailed,
ServerClosedSocket,
};
virtual Web::WebSockets::WebSocket::ReadyState ready_state() = 0;
virtual ByteString subprotocol_in_use() = 0;
virtual void send(ByteBuffer binary_or_text_message, bool is_text) = 0;
virtual void send(StringView text_message) = 0;
virtual void close(u16 code = 1005, ByteString reason = {}) = 0;
Function<void()> on_open;
Function<void(Message)> on_message;
Function<void(Error)> on_error;
Function<void(u16 code, ByteString reason, bool was_clean)> on_close;
Function<CertificateAndKey()> on_certificate_requested;
protected:
explicit WebSocketClientSocket() = default;
RefPtr<Requests::WebSocket> m_websocket;
};
}

View file

@ -10,14 +10,12 @@ set(SOURCES
ProcessHandle.cpp
Process.cpp
ProcessManager.cpp
RequestServerAdapter.cpp
SearchEngine.cpp
SourceHighlighter.cpp
URL.cpp
UserAgent.cpp
ViewImplementation.cpp
WebContentClient.cpp
WebSocketClientAdapter.cpp
${PUBLIC_SUFFIX_SOURCES}
)

View file

@ -1,98 +0,0 @@
/*
* Copyright (c) 2022, Dex <dexes.ttp@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "WebSocketClientAdapter.h"
#include <LibRequests/Request.h>
#include <LibRequests/RequestClient.h>
#include <LibWebView/RequestServerAdapter.h>
namespace WebView {
ErrorOr<NonnullRefPtr<RequestServerRequestAdapter>> RequestServerRequestAdapter::try_create(NonnullRefPtr<Requests::Request> request)
{
return adopt_nonnull_ref_or_enomem(new (nothrow) RequestServerRequestAdapter(move(request)));
}
RequestServerRequestAdapter::RequestServerRequestAdapter(NonnullRefPtr<Requests::Request> request)
: m_request(request)
{
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 Requests::Request::CertificateAndKey {
.certificate = move(certificate_and_key.certificate),
.key = move(certificate_and_key.key),
};
}
}
return Requests::Request::CertificateAndKey {};
};
}
RequestServerRequestAdapter::~RequestServerRequestAdapter() = default;
void RequestServerRequestAdapter::set_buffered_request_finished_callback(Requests::Request::BufferedRequestFinished on_buffered_request_finished)
{
m_request->set_buffered_request_finished_callback(move(on_buffered_request_finished));
}
void RequestServerRequestAdapter::set_unbuffered_request_callbacks(Requests::Request::HeadersReceived on_headers_received, Requests::Request::DataReceived on_data_received, Requests::Request::RequestFinished on_finished)
{
m_request->set_unbuffered_request_callbacks(move(on_headers_received), move(on_data_received), move(on_finished));
}
bool RequestServerRequestAdapter::stop()
{
return m_request->stop();
}
ErrorOr<NonnullRefPtr<RequestServerAdapter>> RequestServerAdapter::try_create(NonnullRefPtr<Requests::RequestClient> protocol_client)
{
return try_make_ref_counted<RequestServerAdapter>(move(protocol_client));
}
ErrorOr<NonnullRefPtr<RequestServerAdapter>> RequestServerAdapter::try_create()
{
auto protocol_client = TRY(Requests::RequestClient::try_create());
return try_make_ref_counted<RequestServerAdapter>(move(protocol_client));
}
RequestServerAdapter::RequestServerAdapter(NonnullRefPtr<Requests::RequestClient> protocol_client)
: m_protocol_client(protocol_client)
{
}
RequestServerAdapter::~RequestServerAdapter() = default;
RefPtr<Web::ResourceLoaderConnectorRequest> RequestServerAdapter::start_request(ByteString const& method, URL::URL const& url, HTTP::HeaderMap 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();
}
RefPtr<Web::WebSockets::WebSocketClientSocket> RequestServerAdapter::websocket_connect(URL::URL const& url, AK::ByteString const& origin, Vector<AK::ByteString> const& protocols)
{
auto underlying_websocket = m_protocol_client->websocket_connect(url, origin, protocols);
if (!underlying_websocket)
return {};
return WebSocketClientSocketAdapter::create(underlying_websocket.release_nonnull());
}
void RequestServerAdapter::prefetch_dns(URL::URL const& url)
{
m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly);
}
void RequestServerAdapter::preconnect(URL::URL const& url)
{
m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::CreateConnection);
}
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (c) 2022, Dex <dexes.ttp@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Function.h>
#include <LibURL/URL.h>
#include <LibWeb/Loader/ResourceLoader.h>
#include <LibWeb/WebSockets/WebSocket.h>
namespace Requests {
class Request;
class RequestClient;
}
namespace WebView {
class RequestServerRequestAdapter
: public Web::ResourceLoaderConnectorRequest
, public Weakable<RequestServerRequestAdapter> {
public:
static ErrorOr<NonnullRefPtr<RequestServerRequestAdapter>> try_create(NonnullRefPtr<Requests::Request>);
virtual ~RequestServerRequestAdapter() override;
virtual void set_buffered_request_finished_callback(Requests::Request::BufferedRequestFinished) override;
virtual void set_unbuffered_request_callbacks(Requests::Request::HeadersReceived, Requests::Request::DataReceived, Requests::Request::RequestFinished) override;
virtual bool stop() override;
private:
RequestServerRequestAdapter(NonnullRefPtr<Requests::Request>);
NonnullRefPtr<Requests::Request> m_request;
};
class RequestServerAdapter : public Web::ResourceLoaderConnector {
public:
explicit RequestServerAdapter(NonnullRefPtr<Requests::RequestClient> protocol_client);
static ErrorOr<NonnullRefPtr<RequestServerAdapter>> try_create(NonnullRefPtr<Requests::RequestClient>);
static ErrorOr<NonnullRefPtr<RequestServerAdapter>> try_create();
virtual ~RequestServerAdapter() override;
virtual void prefetch_dns(URL::URL const& url) override;
virtual void preconnect(URL::URL const& url) override;
virtual RefPtr<Web::ResourceLoaderConnectorRequest> start_request(ByteString const& method, URL::URL const&, HTTP::HeaderMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) override;
virtual RefPtr<Web::WebSockets::WebSocketClientSocket> websocket_connect(const URL::URL&, ByteString const& origin, Vector<ByteString> const& protocols) override;
private:
RefPtr<Requests::RequestClient> m_protocol_client;
};
}

View file

@ -1,110 +0,0 @@
/*
* Copyright (c) 2022, Dex <dexes.ttp@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibRequests/RequestClient.h>
#include <LibRequests/WebSocket.h>
#include <LibWebView/WebSocketClientAdapter.h>
namespace WebView {
RefPtr<WebSocketClientSocketAdapter> WebSocketClientSocketAdapter::create(NonnullRefPtr<Requests::WebSocket> websocket)
{
return adopt_ref(*new WebSocketClientSocketAdapter(move(websocket)));
}
WebSocketClientSocketAdapter::WebSocketClientSocketAdapter(NonnullRefPtr<Requests::WebSocket> websocket)
: m_websocket(move(websocket))
{
m_websocket->on_open = [weak_this = make_weak_ptr()] {
if (auto strong_this = weak_this.strong_ref())
if (strong_this->on_open)
strong_this->on_open();
};
m_websocket->on_message = [weak_this = make_weak_ptr()](auto message) {
if (auto strong_this = weak_this.strong_ref()) {
if (strong_this->on_message) {
strong_this->on_message(Web::WebSockets::WebSocketClientSocket::Message {
.data = move(message.data),
.is_text = message.is_text,
});
}
}
};
m_websocket->on_error = [weak_this = make_weak_ptr()](auto error) {
if (auto strong_this = weak_this.strong_ref()) {
if (strong_this->on_error) {
switch (error) {
case Requests::WebSocket::Error::CouldNotEstablishConnection:
strong_this->on_error(Web::WebSockets::WebSocketClientSocket::Error::CouldNotEstablishConnection);
return;
case Requests::WebSocket::Error::ConnectionUpgradeFailed:
strong_this->on_error(Web::WebSockets::WebSocketClientSocket::Error::ConnectionUpgradeFailed);
return;
case Requests::WebSocket::Error::ServerClosedSocket:
strong_this->on_error(Web::WebSockets::WebSocketClientSocket::Error::ServerClosedSocket);
return;
}
VERIFY_NOT_REACHED();
}
}
};
m_websocket->on_close = [weak_this = make_weak_ptr()](u16 code, ByteString reason, bool was_clean) {
if (auto strong_this = weak_this.strong_ref())
if (strong_this->on_close)
strong_this->on_close(code, move(reason), was_clean);
};
m_websocket->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 = weak_this->on_certificate_requested();
return Requests::WebSocket::CertificateAndKey {
.certificate = move(certificate_and_key.certificate),
.key = move(certificate_and_key.key),
};
}
}
return Requests::WebSocket::CertificateAndKey {};
};
}
WebSocketClientSocketAdapter::~WebSocketClientSocketAdapter() = default;
Web::WebSockets::WebSocket::ReadyState WebSocketClientSocketAdapter::ready_state()
{
switch (m_websocket->ready_state()) {
case Requests::WebSocket::ReadyState::Connecting:
return Web::WebSockets::WebSocket::ReadyState::Connecting;
case Requests::WebSocket::ReadyState::Open:
return Web::WebSockets::WebSocket::ReadyState::Open;
case Requests::WebSocket::ReadyState::Closing:
return Web::WebSockets::WebSocket::ReadyState::Closing;
case Requests::WebSocket::ReadyState::Closed:
return Web::WebSockets::WebSocket::ReadyState::Closed;
}
VERIFY_NOT_REACHED();
}
ByteString WebSocketClientSocketAdapter::subprotocol_in_use()
{
return m_websocket->subprotocol_in_use();
}
void WebSocketClientSocketAdapter::send(ByteBuffer binary_or_text_message, bool is_text)
{
m_websocket->send(binary_or_text_message, is_text);
}
void WebSocketClientSocketAdapter::send(StringView text_message)
{
m_websocket->send(text_message);
}
void WebSocketClientSocketAdapter::close(u16 code, ByteString reason)
{
m_websocket->close(code, reason);
}
}

View file

@ -1,41 +0,0 @@
/*
* Copyright (c) 2022, Dex <dexes.ttp@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/NonnullRefPtr.h>
#include <AK/Weakable.h>
#include <LibWeb/WebSockets/WebSocket.h>
namespace Requests {
class WebSocket;
class RequestClient;
};
namespace WebView {
class WebSocketClientSocketAdapter
: public Web::WebSockets::WebSocketClientSocket
, public Weakable<WebSocketClientSocketAdapter> {
public:
static RefPtr<WebSocketClientSocketAdapter> create(NonnullRefPtr<Requests::WebSocket>);
virtual ~WebSocketClientSocketAdapter() override;
virtual Web::WebSockets::WebSocket::ReadyState ready_state() override;
virtual ByteString subprotocol_in_use() override;
virtual void send(ByteBuffer binary_or_text_message, bool is_text) override;
virtual void send(StringView text_message) override;
virtual void close(u16 code = 1005, ByteString reason = {}) override;
private:
WebSocketClientSocketAdapter(NonnullRefPtr<Requests::WebSocket>);
NonnullRefPtr<Requests::WebSocket> m_websocket;
};
}