mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibWebView+UI: Remove Qt networking infrastructure
Now that we use libcurl, there's no reason to keep Qt networking around. Further, it doesn't support all features we need anyways, such as non- buffered request handling for SSE.
This commit is contained in:
parent
fd8d350b47
commit
1b324f3ae1
Notes:
github-actions[bot]
2024-10-08 04:53:53 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/1b324f3ae11 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1671
20 changed files with 19 additions and 551 deletions
|
@ -132,7 +132,7 @@ static ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_new_image_decod
|
|||
- (ErrorOr<IPC::File>)launchWebWorker
|
||||
{
|
||||
auto web_worker_paths = TRY(get_paths_for_helper_process("WebWorker"sv));
|
||||
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, m_request_server_client));
|
||||
auto worker_client = TRY(launch_web_worker_process(web_worker_paths, *m_request_server_client));
|
||||
|
||||
return worker_client->dup_socket();
|
||||
}
|
||||
|
|
|
@ -92,8 +92,6 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
|||
}
|
||||
if (web_content_options.is_layout_test_mode == WebView::IsLayoutTestMode::Yes)
|
||||
arguments.append("--layout-test-mode"sv);
|
||||
if (web_content_options.use_lagom_networking == WebView::UseLagomNetworking::Yes)
|
||||
arguments.append("--use-lagom-networking"sv);
|
||||
if (web_content_options.log_all_js_exceptions == WebView::LogAllJSExceptions::Yes)
|
||||
arguments.append("--log-all-js-exceptions"sv);
|
||||
if (web_content_options.enable_idl_tracing == WebView::EnableIDLTracing::Yes)
|
||||
|
@ -132,16 +130,13 @@ ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process(
|
|||
return launch_server_process<ImageDecoderClient::Client>("ImageDecoder"sv, candidate_image_decoder_paths, arguments);
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, RefPtr<Requests::RequestClient> request_client)
|
||||
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, NonnullRefPtr<Requests::RequestClient> request_client)
|
||||
{
|
||||
Vector<ByteString> arguments;
|
||||
if (request_client) {
|
||||
auto socket = TRY(connect_new_request_server_client(*request_client));
|
||||
arguments.append("--request-server-socket"sv);
|
||||
arguments.append(ByteString::number(socket.fd()));
|
||||
arguments.append("--use-lagom-networking"sv);
|
||||
return launch_server_process<Web::HTML::WebWorkerClient>("WebWorker"sv, candidate_web_worker_paths, move(arguments));
|
||||
}
|
||||
|
||||
auto socket = TRY(connect_new_request_server_client(*request_client));
|
||||
arguments.append("--request-server-socket"sv);
|
||||
arguments.append(ByteString::number(socket.fd()));
|
||||
|
||||
return launch_server_process<Web::HTML::WebWorkerClient>("WebWorker"sv, candidate_web_worker_paths, move(arguments));
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(
|
|||
Optional<IPC::File> request_server_socket = {});
|
||||
|
||||
ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>> launch_image_decoder_process(ReadonlySpan<ByteString> candidate_image_decoder_paths);
|
||||
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, RefPtr<Requests::RequestClient>);
|
||||
ErrorOr<NonnullRefPtr<Web::HTML::WebWorkerClient>> launch_web_worker_process(ReadonlySpan<ByteString> candidate_web_worker_paths, NonnullRefPtr<Requests::RequestClient>);
|
||||
ErrorOr<NonnullRefPtr<Requests::RequestClient>> launch_request_server_process(ReadonlySpan<ByteString> candidate_request_server_paths, StringView serenity_resource_root);
|
||||
|
||||
ErrorOr<IPC::File> connect_new_request_server_client(Requests::RequestClient&);
|
||||
|
|
|
@ -22,15 +22,9 @@ Application::Application(Badge<WebView::Application>, Main::Arguments& arguments
|
|||
{
|
||||
}
|
||||
|
||||
void Application::create_platform_arguments(Core::ArgsParser& args_parser)
|
||||
{
|
||||
args_parser.add_option(m_enable_qt_networking, "Enable Qt as the backend networking service", "enable-qt-networking");
|
||||
}
|
||||
|
||||
void Application::create_platform_options(WebView::ChromeOptions&, WebView::WebContentOptions& web_content_options)
|
||||
{
|
||||
web_content_options.config_path = Settings::the()->directory();
|
||||
web_content_options.use_lagom_networking = m_enable_qt_networking ? WebView::UseLagomNetworking::No : WebView::UseLagomNetworking::Yes;
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
|
|
|
@ -43,13 +43,10 @@ public:
|
|||
void set_active_window(BrowserWindow& w) { m_active_window = &w; }
|
||||
|
||||
private:
|
||||
virtual void create_platform_arguments(Core::ArgsParser&) override;
|
||||
virtual void create_platform_options(WebView::ChromeOptions&, WebView::WebContentOptions&) override;
|
||||
|
||||
virtual Optional<ByteString> ask_user_for_download_folder() const override;
|
||||
|
||||
bool m_enable_qt_networking { false };
|
||||
|
||||
TaskManagerWindow* m_task_manager_window { nullptr };
|
||||
BrowserWindow* m_active_window { nullptr };
|
||||
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "RequestManagerQt.h"
|
||||
#include "StringUtils.h"
|
||||
#include "WebSocketImplQt.h"
|
||||
#include "WebSocketQt.h"
|
||||
#include <QNetworkCookie>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
RequestManagerQt::RequestManagerQt(Vector<ByteString> const& certificate_paths)
|
||||
{
|
||||
m_qnam = new QNetworkAccessManager(this);
|
||||
auto ssl_configuration = QSslConfiguration::defaultConfiguration();
|
||||
ssl_configuration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
for (auto const& certificate_path : certificate_paths) {
|
||||
auto certificates = QSslCertificate::fromPath(qstring_from_ak_string(certificate_path));
|
||||
for (auto const& certificate : certificates)
|
||||
ssl_configuration.addCaCertificate(certificate);
|
||||
}
|
||||
QSslConfiguration::setDefaultConfiguration(ssl_configuration);
|
||||
|
||||
QObject::connect(m_qnam, &QNetworkAccessManager::finished, this, &RequestManagerQt::reply_finished);
|
||||
}
|
||||
|
||||
void RequestManagerQt::reply_finished(QNetworkReply* reply)
|
||||
{
|
||||
auto request = m_pending.get(reply).value();
|
||||
m_pending.remove(reply);
|
||||
request->did_finish();
|
||||
}
|
||||
|
||||
RefPtr<Web::ResourceLoaderConnectorRequest> RequestManagerQt::start_request(ByteString const& method, URL::URL const& url, HTTP::HeaderMap const& request_headers, ReadonlyBytes request_body, Core::ProxyData const& proxy)
|
||||
{
|
||||
if (!url.scheme().bytes_as_string_view().is_one_of_ignoring_ascii_case("http"sv, "https"sv)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto request_or_error = Request::create(*m_qnam, method, url, request_headers, request_body, proxy);
|
||||
if (request_or_error.is_error()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto request = request_or_error.release_value();
|
||||
m_pending.set(&request->reply(), *request);
|
||||
return request;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<RequestManagerQt::Request>> RequestManagerQt::Request::create(QNetworkAccessManager& qnam, ByteString const& method, URL::URL const& url, HTTP::HeaderMap const& request_headers, ReadonlyBytes request_body, Core::ProxyData const&)
|
||||
{
|
||||
QNetworkRequest request { QString(url.to_byte_string().characters()) };
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
|
||||
request.setAttribute(QNetworkRequest::CookieLoadControlAttribute, QNetworkRequest::Manual);
|
||||
request.setAttribute(QNetworkRequest::CookieSaveControlAttribute, QNetworkRequest::Manual);
|
||||
|
||||
// NOTE: We disable HTTP2 as it's significantly slower (up to 5x, possibly more)
|
||||
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
|
||||
|
||||
QNetworkReply* reply = nullptr;
|
||||
|
||||
for (auto const& it : request_headers.headers()) {
|
||||
// FIXME: We currently strip the Accept-Encoding header on outgoing requests from LibWeb
|
||||
// since otherwise it'll ask for compression without Qt being aware of it.
|
||||
// This is very hackish and I'm sure we can do it in concert with Qt somehow.
|
||||
if (it.name == "Accept-Encoding")
|
||||
continue;
|
||||
request.setRawHeader(QByteArray(it.name.characters()), QByteArray(it.value.characters()));
|
||||
}
|
||||
|
||||
if (method.equals_ignoring_ascii_case("head"sv)) {
|
||||
reply = qnam.head(request);
|
||||
} else if (method.equals_ignoring_ascii_case("get"sv)) {
|
||||
reply = qnam.get(request);
|
||||
} else if (method.equals_ignoring_ascii_case("post"sv)) {
|
||||
reply = qnam.post(request, QByteArray((char const*)request_body.data(), request_body.size()));
|
||||
} else if (method.equals_ignoring_ascii_case("put"sv)) {
|
||||
reply = qnam.put(request, QByteArray((char const*)request_body.data(), request_body.size()));
|
||||
} else if (method.equals_ignoring_ascii_case("delete"sv)) {
|
||||
reply = qnam.deleteResource(request);
|
||||
} else {
|
||||
reply = qnam.sendCustomRequest(request, QByteArray(method.characters()), QByteArray((char const*)request_body.data(), request_body.size()));
|
||||
}
|
||||
|
||||
return adopt_ref(*new Request(*reply));
|
||||
}
|
||||
|
||||
RefPtr<Web::WebSockets::WebSocketClientSocket> RequestManagerQt::websocket_connect(URL::URL const& url, AK::ByteString const& origin, Vector<AK::ByteString> const& protocols)
|
||||
{
|
||||
WebSocket::ConnectionInfo connection_info(url);
|
||||
connection_info.set_origin(origin);
|
||||
connection_info.set_protocols(protocols);
|
||||
|
||||
auto impl = adopt_ref(*new WebSocketImplQt);
|
||||
auto web_socket = WebSocket::WebSocket::create(move(connection_info), move(impl));
|
||||
web_socket->start();
|
||||
return WebSocketQt::create(web_socket);
|
||||
}
|
||||
|
||||
RequestManagerQt::Request::Request(QNetworkReply& reply)
|
||||
: m_reply(reply)
|
||||
{
|
||||
}
|
||||
|
||||
RequestManagerQt::Request::~Request() = default;
|
||||
|
||||
void RequestManagerQt::Request::set_buffered_request_finished_callback(Requests::Request::BufferedRequestFinished on_buffered_request_finished)
|
||||
{
|
||||
this->on_buffered_request_finish = move(on_buffered_request_finished);
|
||||
}
|
||||
|
||||
void RequestManagerQt::Request::set_unbuffered_request_callbacks(Requests::Request::HeadersReceived, Requests::Request::DataReceived, Requests::Request::RequestFinished on_request_finished)
|
||||
{
|
||||
dbgln("Unbuffered requests are not yet supported with Qt networking");
|
||||
on_request_finished(false, 0);
|
||||
}
|
||||
|
||||
void RequestManagerQt::Request::did_finish()
|
||||
{
|
||||
auto buffer = m_reply.readAll();
|
||||
auto http_status_code = m_reply.attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt();
|
||||
HTTP::HeaderMap response_headers;
|
||||
for (auto& it : m_reply.rawHeaderPairs()) {
|
||||
auto name = ByteString(it.first.data(), it.first.length());
|
||||
auto value = ByteString(it.second.data(), it.second.length());
|
||||
if (name.equals_ignoring_ascii_case("set-cookie"sv)) {
|
||||
// NOTE: Qt may have bundled multiple Set-Cookie headers into a single one.
|
||||
// We have to extract the full list of cookies via QNetworkReply::header().
|
||||
auto set_cookie_list = m_reply.header(QNetworkRequest::SetCookieHeader).value<QList<QNetworkCookie>>();
|
||||
for (auto const& cookie : set_cookie_list) {
|
||||
response_headers.set(name, cookie.toRawForm().data());
|
||||
}
|
||||
} else {
|
||||
response_headers.set(name, value);
|
||||
}
|
||||
}
|
||||
bool success = http_status_code != 0;
|
||||
on_buffered_request_finish(success, buffer.length(), response_headers, http_status_code, ReadonlyBytes { buffer.data(), (size_t)buffer.size() });
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/Loader/ResourceLoader.h>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class RequestManagerQt
|
||||
: public QObject
|
||||
, public Web::ResourceLoaderConnector {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static NonnullRefPtr<RequestManagerQt> create(Vector<ByteString> const& certificate_paths)
|
||||
{
|
||||
return adopt_ref(*new RequestManagerQt(certificate_paths));
|
||||
}
|
||||
|
||||
virtual ~RequestManagerQt() override { }
|
||||
|
||||
virtual void prefetch_dns(URL::URL const&) override { }
|
||||
virtual void preconnect(URL::URL const&) 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 slots:
|
||||
void reply_finished(QNetworkReply*);
|
||||
|
||||
private:
|
||||
explicit RequestManagerQt(Vector<ByteString> const& certificate_paths);
|
||||
|
||||
class Request
|
||||
: public Web::ResourceLoaderConnectorRequest {
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<Request>> create(QNetworkAccessManager& qnam, ByteString const& method, URL::URL const& url, HTTP::HeaderMap const& request_headers, ReadonlyBytes request_body, Core::ProxyData const&);
|
||||
|
||||
virtual ~Request() 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 { return false; }
|
||||
|
||||
void did_finish();
|
||||
|
||||
QNetworkReply& reply() { return m_reply; }
|
||||
|
||||
private:
|
||||
Request(QNetworkReply&);
|
||||
|
||||
QNetworkReply& m_reply;
|
||||
|
||||
Requests::Request::BufferedRequestFinished on_buffered_request_finish;
|
||||
};
|
||||
|
||||
HashMap<QNetworkReply*, NonnullRefPtr<Request>> m_pending;
|
||||
QNetworkAccessManager* m_qnam { nullptr };
|
||||
};
|
||||
|
||||
}
|
|
@ -135,11 +135,8 @@ WebContentView::WebContentView(QWidget* window, RefPtr<WebView::WebContentClient
|
|||
};
|
||||
|
||||
on_request_worker_agent = [&]() {
|
||||
RefPtr<Requests::RequestClient> request_server_client {};
|
||||
if (WebView::Application::web_content_options().use_lagom_networking == WebView::UseLagomNetworking::Yes)
|
||||
request_server_client = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
||||
|
||||
auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), request_server_client));
|
||||
auto& request_server_client = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
||||
auto worker_client = MUST(launch_web_worker_process(MUST(get_paths_for_helper_process("WebWorker"sv)), *request_server_client));
|
||||
return worker_client->dup_socket();
|
||||
};
|
||||
|
||||
|
@ -647,14 +644,10 @@ void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewCli
|
|||
if (create_new_client == CreateNewClient::Yes) {
|
||||
m_client_state = {};
|
||||
|
||||
Optional<IPC::File> request_server_socket;
|
||||
if (WebView::Application::web_content_options().use_lagom_networking == WebView::UseLagomNetworking::Yes) {
|
||||
auto& protocol = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
||||
auto& request_server_client = static_cast<Ladybird::Application*>(QApplication::instance())->request_server_client;
|
||||
|
||||
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
|
||||
auto socket = connect_new_request_server_client(*protocol).release_value_but_fixme_should_propagate_errors();
|
||||
request_server_socket = AK::move(socket);
|
||||
}
|
||||
// FIXME: Fail to open the tab, rather than crashing the whole application if this fails
|
||||
auto request_server_socket = connect_new_request_server_client(*request_server_client).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
auto image_decoder = static_cast<Ladybird::Application*>(QApplication::instance())->image_decoder_client();
|
||||
auto image_decoder_socket = connect_new_image_decoder_client(*image_decoder).release_value_but_fixme_should_propagate_errors();
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
* Copyright (c) 2022, the SerenityOS developers.
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "WebSocketImplQt.h"
|
||||
#include "StringUtils.h"
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <QSslSocket>
|
||||
#include <QTcpSocket>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
WebSocketImplQt::~WebSocketImplQt() = default;
|
||||
WebSocketImplQt::WebSocketImplQt() = default;
|
||||
|
||||
bool WebSocketImplQt::can_read_line()
|
||||
{
|
||||
return m_socket->canReadLine();
|
||||
}
|
||||
|
||||
bool WebSocketImplQt::send(ReadonlyBytes bytes)
|
||||
{
|
||||
auto bytes_written = m_socket->write(reinterpret_cast<char const*>(bytes.data()), bytes.size());
|
||||
if (bytes_written == -1)
|
||||
return false;
|
||||
VERIFY(static_cast<size_t>(bytes_written) == bytes.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketImplQt::eof()
|
||||
{
|
||||
return m_socket->state() == QTcpSocket::SocketState::UnconnectedState
|
||||
&& !m_socket->bytesAvailable();
|
||||
}
|
||||
|
||||
void WebSocketImplQt::discard_connection()
|
||||
{
|
||||
m_socket = nullptr;
|
||||
}
|
||||
|
||||
void WebSocketImplQt::connect(WebSocket::ConnectionInfo const& connection_info)
|
||||
{
|
||||
VERIFY(!m_socket);
|
||||
VERIFY(on_connected);
|
||||
VERIFY(on_connection_error);
|
||||
VERIFY(on_ready_to_read);
|
||||
|
||||
if (connection_info.is_secure()) {
|
||||
auto ssl_socket = make<QSslSocket>();
|
||||
ssl_socket->connectToHostEncrypted(
|
||||
qstring_from_ak_string(MUST(connection_info.url().serialized_host())),
|
||||
connection_info.url().port_or_default());
|
||||
QObject::connect(ssl_socket.ptr(), &QSslSocket::alertReceived, [this](QSsl::AlertLevel level, QSsl::AlertType, QString const&) {
|
||||
if (level == QSsl::AlertLevel::Fatal)
|
||||
on_connection_error();
|
||||
});
|
||||
m_socket = move(ssl_socket);
|
||||
} else {
|
||||
m_socket = make<QTcpSocket>();
|
||||
m_socket->connectToHost(
|
||||
qstring_from_ak_string(MUST(connection_info.url().serialized_host())),
|
||||
connection_info.url().port_or_default());
|
||||
}
|
||||
|
||||
QObject::connect(m_socket.ptr(), &QTcpSocket::readyRead, [this] {
|
||||
on_ready_to_read();
|
||||
});
|
||||
|
||||
QObject::connect(m_socket.ptr(), &QTcpSocket::connected, [this] {
|
||||
on_connected();
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> WebSocketImplQt::read(int max_size)
|
||||
{
|
||||
auto buffer = TRY(ByteBuffer::create_uninitialized(max_size));
|
||||
auto bytes_read = m_socket->read(reinterpret_cast<char*>(buffer.data()), buffer.size());
|
||||
if (bytes_read == -1)
|
||||
return Error::from_string_literal("WebSocketImplQt::read(): Error reading from socket");
|
||||
return buffer.slice(0, bytes_read);
|
||||
}
|
||||
|
||||
ErrorOr<ByteString> WebSocketImplQt::read_line(size_t size)
|
||||
{
|
||||
auto buffer = TRY(ByteBuffer::create_uninitialized(size));
|
||||
auto bytes_read = m_socket->readLine(reinterpret_cast<char*>(buffer.data()), buffer.size());
|
||||
if (bytes_read == -1)
|
||||
return Error::from_string_literal("WebSocketImplQt::read_line(): Error reading from socket");
|
||||
return ByteString::copy(buffer.span().slice(0, bytes_read));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
* Copyright (c) 2022, the SerenityOS developers.
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWebSocket/Impl/WebSocketImpl.h>
|
||||
|
||||
class QTcpSocket;
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class WebSocketImplQt final : public WebSocket::WebSocketImpl {
|
||||
public:
|
||||
explicit WebSocketImplQt();
|
||||
virtual ~WebSocketImplQt() override;
|
||||
|
||||
virtual void connect(WebSocket::ConnectionInfo const&) override;
|
||||
virtual bool can_read_line() override;
|
||||
virtual ErrorOr<ByteString> read_line(size_t) override;
|
||||
virtual ErrorOr<ByteBuffer> read(int max_size) override;
|
||||
virtual bool send(ReadonlyBytes) override;
|
||||
virtual bool eof() override;
|
||||
virtual void discard_connection() override;
|
||||
|
||||
private:
|
||||
OwnPtr<QTcpSocket> m_socket;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Dex♪ <dexes.ttp@gmail.com>
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "WebSocketQt.h"
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
NonnullRefPtr<WebSocketQt> WebSocketQt::create(NonnullRefPtr<WebSocket::WebSocket> underlying_socket)
|
||||
{
|
||||
return adopt_ref(*new WebSocketQt(move(underlying_socket)));
|
||||
}
|
||||
|
||||
WebSocketQt::WebSocketQt(NonnullRefPtr<WebSocket::WebSocket> underlying_socket)
|
||||
: m_websocket(move(underlying_socket))
|
||||
{
|
||||
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 WebSocket::WebSocket::Error::CouldNotEstablishConnection:
|
||||
strong_this->on_error(Web::WebSockets::WebSocketClientSocket::Error::CouldNotEstablishConnection);
|
||||
return;
|
||||
case WebSocket::WebSocket::Error::ConnectionUpgradeFailed:
|
||||
strong_this->on_error(Web::WebSockets::WebSocketClientSocket::Error::ConnectionUpgradeFailed);
|
||||
return;
|
||||
case WebSocket::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);
|
||||
};
|
||||
}
|
||||
|
||||
WebSocketQt::~WebSocketQt() = default;
|
||||
|
||||
Web::WebSockets::WebSocket::ReadyState WebSocketQt::ready_state()
|
||||
{
|
||||
switch (m_websocket->ready_state()) {
|
||||
case WebSocket::ReadyState::Connecting:
|
||||
return Web::WebSockets::WebSocket::ReadyState::Connecting;
|
||||
case WebSocket::ReadyState::Open:
|
||||
return Web::WebSockets::WebSocket::ReadyState::Open;
|
||||
case WebSocket::ReadyState::Closing:
|
||||
return Web::WebSockets::WebSocket::ReadyState::Closing;
|
||||
case WebSocket::ReadyState::Closed:
|
||||
return Web::WebSockets::WebSocket::ReadyState::Closed;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ByteString WebSocketQt::subprotocol_in_use()
|
||||
{
|
||||
return m_websocket->subprotocol_in_use();
|
||||
}
|
||||
|
||||
void WebSocketQt::send(ByteBuffer binary_or_text_message, bool is_text)
|
||||
{
|
||||
m_websocket->send(WebSocket::Message(binary_or_text_message, is_text));
|
||||
}
|
||||
|
||||
void WebSocketQt::send(StringView message)
|
||||
{
|
||||
m_websocket->send(WebSocket::Message(message));
|
||||
}
|
||||
|
||||
void WebSocketQt::close(u16 code, ByteString reason)
|
||||
{
|
||||
m_websocket->close(code, reason);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Dex♪ <dexes.ttp@gmail.com>
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/WebSockets/WebSocket.h>
|
||||
#include <LibWebSocket/WebSocket.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class WebSocketQt
|
||||
: public Web::WebSockets::WebSocketClientSocket
|
||||
, public Weakable<WebSocketQt> {
|
||||
public:
|
||||
static NonnullRefPtr<WebSocketQt> create(NonnullRefPtr<WebSocket::WebSocket>);
|
||||
|
||||
virtual ~WebSocketQt() 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 message) override;
|
||||
virtual void close(u16 code, ByteString reason) override;
|
||||
|
||||
private:
|
||||
explicit WebSocketQt(NonnullRefPtr<WebSocket::WebSocket>);
|
||||
|
||||
NonnullRefPtr<WebSocket::WebSocket> m_websocket;
|
||||
};
|
||||
|
||||
}
|
|
@ -114,11 +114,9 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
copy_default_config_files(Ladybird::Settings::the()->directory());
|
||||
|
||||
// FIXME: Create an abstraction to re-spawn the RequestServer and re-hook up its client hooks to each tab on crash
|
||||
if (app->web_content_options().use_lagom_networking == WebView::UseLagomNetworking::Yes) {
|
||||
auto request_server_paths = TRY(get_paths_for_helper_process("RequestServer"sv));
|
||||
auto requests_client = TRY(launch_request_server_process(request_server_paths, s_ladybird_resource_root));
|
||||
app->request_server_client = move(requests_client);
|
||||
}
|
||||
auto request_server_paths = TRY(get_paths_for_helper_process("RequestServer"sv));
|
||||
auto requests_client = TRY(launch_request_server_process(request_server_paths, s_ladybird_resource_root));
|
||||
app->request_server_client = move(requests_client);
|
||||
|
||||
TRY(app->initialize_image_decoder());
|
||||
|
||||
|
|
|
@ -45,10 +45,7 @@ if (ENABLE_QT)
|
|||
qt_add_executable(WebContent
|
||||
../Qt/EventLoopImplementationQt.cpp
|
||||
../Qt/EventLoopImplementationQtEventTarget.cpp
|
||||
../Qt/RequestManagerQt.cpp
|
||||
../Qt/StringUtils.cpp
|
||||
../Qt/WebSocketQt.cpp
|
||||
../Qt/WebSocketImplQt.cpp
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(WebContent PRIVATE Qt::Core Qt::Network)
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#if defined(HAVE_QT)
|
||||
# include <Ladybird/Qt/EventLoopImplementationQt.h>
|
||||
# include <Ladybird/Qt/RequestManagerQt.h>
|
||||
# include <QCoreApplication>
|
||||
|
||||
# if defined(HAVE_QT_MULTIMEDIA)
|
||||
|
@ -100,7 +99,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
int image_decoder_socket { -1 };
|
||||
bool is_layout_test_mode = false;
|
||||
bool expose_internals_object = false;
|
||||
bool use_lagom_networking = false;
|
||||
bool wait_for_debugger = false;
|
||||
bool log_all_js_exceptions = false;
|
||||
bool enable_idl_tracing = false;
|
||||
|
@ -116,7 +114,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
args_parser.add_option(image_decoder_socket, "File descriptor of the socket for the ImageDecoder connection", "image-decoder-socket", 'i', "image_decoder_socket");
|
||||
args_parser.add_option(is_layout_test_mode, "Is layout test mode", "layout-test-mode");
|
||||
args_parser.add_option(expose_internals_object, "Expose internals object", "expose-internals-object");
|
||||
args_parser.add_option(use_lagom_networking, "Enable Lagom servers for networking", "use-lagom-networking");
|
||||
args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
|
||||
args_parser.add_option(wait_for_debugger, "Wait for debugger", "wait-for-debugger");
|
||||
args_parser.add_option(mach_server_name, "Mach server name", "mach-server-name", 0, "mach_server_name");
|
||||
|
@ -166,13 +163,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
if (!use_lagom_networking)
|
||||
Web::ResourceLoader::initialize(Ladybird::RequestManagerQt::create(certificates));
|
||||
else
|
||||
#endif
|
||||
TRY(initialize_lagom_networking(request_server_socket));
|
||||
|
||||
TRY(initialize_lagom_networking(request_server_socket));
|
||||
TRY(initialize_image_decoder(image_decoder_socket));
|
||||
|
||||
Web::HTML::Window::set_internals_object_exposed(expose_internals_object);
|
||||
|
|
|
@ -32,7 +32,7 @@ static ErrorOr<pid_t> launch_process(StringView application, ReadonlySpan<char c
|
|||
return result;
|
||||
}
|
||||
|
||||
static ErrorOr<pid_t> launch_browser(ByteString const& socket_path, bool use_qt_networking, bool force_cpu_painting)
|
||||
static ErrorOr<pid_t> launch_browser(ByteString const& socket_path, bool force_cpu_painting)
|
||||
{
|
||||
auto arguments = Vector {
|
||||
"--webdriver-content-path",
|
||||
|
@ -48,8 +48,6 @@ static ErrorOr<pid_t> launch_browser(ByteString const& socket_path, bool use_qt_
|
|||
arguments.append("--allow-popups");
|
||||
arguments.append("--force-new-process");
|
||||
arguments.append("--enable-autoplay");
|
||||
if (use_qt_networking)
|
||||
arguments.append("--enable-qt-networking");
|
||||
if (force_cpu_painting)
|
||||
arguments.append("--force-cpu-painting");
|
||||
|
||||
|
@ -77,14 +75,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
auto listen_address = "0.0.0.0"sv;
|
||||
int port = 8000;
|
||||
bool enable_qt_networking = false;
|
||||
bool force_cpu_painting = false;
|
||||
|
||||
Core::ArgsParser args_parser;
|
||||
args_parser.add_option(listen_address, "IP address to listen on", "listen-address", 'l', "listen_address");
|
||||
args_parser.add_option(port, "Port to listen on", "port", 'p', "port");
|
||||
args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
|
||||
args_parser.add_option(enable_qt_networking, "Launch browser with Qt networking enabled", "enable-qt-networking");
|
||||
args_parser.add_option(force_cpu_painting, "Launch browser with GPU painting disabled", "force-cpu-painting");
|
||||
args_parser.parse(arguments);
|
||||
|
||||
|
@ -122,7 +118,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
}
|
||||
|
||||
auto launch_browser_callback = [&](ByteString const& socket_path) {
|
||||
return launch_browser(socket_path, enable_qt_networking, force_cpu_painting);
|
||||
return launch_browser(socket_path, force_cpu_painting);
|
||||
};
|
||||
|
||||
auto maybe_client = WebDriver::Client::try_create(maybe_buffered_socket.release_value(), { move(launch_browser_callback), launch_headless_browser }, server);
|
||||
|
|
|
@ -29,10 +29,7 @@ if (ENABLE_QT)
|
|||
qt_add_executable(WebWorker
|
||||
../Qt/EventLoopImplementationQt.cpp
|
||||
../Qt/EventLoopImplementationQtEventTarget.cpp
|
||||
../Qt/RequestManagerQt.cpp
|
||||
../Qt/StringUtils.cpp
|
||||
../Qt/WebSocketQt.cpp
|
||||
../Qt/WebSocketImplQt.cpp
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(WebWorker PRIVATE Qt::Core Qt::Network)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#if defined(HAVE_QT)
|
||||
# include <Ladybird/Qt/EventLoopImplementationQt.h>
|
||||
# include <Ladybird/Qt/RequestManagerQt.h>
|
||||
# include <QCoreApplication>
|
||||
#endif
|
||||
|
||||
|
@ -41,13 +40,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
int request_server_socket { -1 };
|
||||
StringView serenity_resource_root;
|
||||
Vector<ByteString> certificates;
|
||||
bool use_lagom_networking { false };
|
||||
bool wait_for_debugger = false;
|
||||
|
||||
Core::ArgsParser args_parser;
|
||||
args_parser.add_option(request_server_socket, "File descriptor of the request server socket", "request-server-socket", 's', "request-server-socket");
|
||||
args_parser.add_option(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root");
|
||||
args_parser.add_option(use_lagom_networking, "Enable Lagom servers for networking", "use-lagom-networking");
|
||||
args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate");
|
||||
args_parser.add_option(wait_for_debugger, "Wait for debugger", "wait-for-debugger");
|
||||
args_parser.parse(arguments);
|
||||
|
@ -67,12 +64,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(false));
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
if (!use_lagom_networking)
|
||||
Web::ResourceLoader::initialize(Ladybird::RequestManagerQt::create(certificates));
|
||||
else
|
||||
#endif
|
||||
TRY(initialize_lagom_networking(request_server_socket));
|
||||
TRY(initialize_lagom_networking(request_server_socket));
|
||||
|
||||
TRY(Web::Bindings::initialize_main_thread_vm(Web::HTML::EventLoop::Type::Worker));
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ enable_qt_multimedia = !enable_pulseaudio && current_os != "mac"
|
|||
moc_qt_objects("generate_moc") {
|
||||
sources = [
|
||||
"//Ladybird/Qt/EventLoopImplementationQtEventTarget.h",
|
||||
"//Ladybird/Qt/RequestManagerQt.h",
|
||||
]
|
||||
|
||||
if (enable_qt_multimedia) {
|
||||
|
@ -78,10 +77,7 @@ executable("WebContent") {
|
|||
sources += [
|
||||
"//Ladybird/Qt/EventLoopImplementationQt.cpp",
|
||||
"//Ladybird/Qt/EventLoopImplementationQtEventTarget.cpp",
|
||||
"//Ladybird/Qt/RequestManagerQt.cpp",
|
||||
"//Ladybird/Qt/StringUtils.cpp",
|
||||
"//Ladybird/Qt/WebSocketImplQt.cpp",
|
||||
"//Ladybird/Qt/WebSocketQt.cpp",
|
||||
]
|
||||
|
||||
if (enable_qt_multimedia) {
|
||||
|
|
|
@ -65,11 +65,6 @@ enum class IsLayoutTestMode {
|
|||
Yes,
|
||||
};
|
||||
|
||||
enum class UseLagomNetworking {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
enum class LogAllJSExceptions {
|
||||
No,
|
||||
Yes,
|
||||
|
@ -106,7 +101,6 @@ struct WebContentOptions {
|
|||
Optional<ByteString> config_path {};
|
||||
Optional<StringView> user_agent_preset {};
|
||||
IsLayoutTestMode is_layout_test_mode { IsLayoutTestMode::No };
|
||||
UseLagomNetworking use_lagom_networking { UseLagomNetworking::Yes };
|
||||
LogAllJSExceptions log_all_js_exceptions { LogAllJSExceptions::No };
|
||||
EnableIDLTracing enable_idl_tracing { EnableIDLTracing::No };
|
||||
EnableHTTPCache enable_http_cache { EnableHTTPCache::No };
|
||||
|
|
Loading…
Reference in a new issue