diff --git a/Ladybird/Android/src/main/AndroidManifest.xml b/Ladybird/Android/src/main/AndroidManifest.xml index bcf49bc8a0..0bb6360f63 100644 --- a/Ladybird/Android/src/main/AndroidManifest.xml +++ b/Ladybird/Android/src/main/AndroidManifest.xml @@ -56,11 +56,6 @@ android:enabled="true" android:exported="false" android:process=":RequestServer" /> - #include #include -#include #include #include @@ -37,11 +36,6 @@ static ErrorOr> bind_request_server_servi return bind_service(&bind_request_server_java); } -static ErrorOr> bind_web_socket_service() -{ - return bind_service(&bind_web_socket_java); -} - template ErrorOr, Error> bind_service(void (*)(int, int)); @@ -64,9 +58,6 @@ ErrorOr service_main(int ipc_socket, int fd_passing_socket) auto request_server_client = TRY(bind_request_server_service()); Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client)))); - auto web_socket_client = TRY(bind_web_socket_service()); - Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create(move(web_socket_client)))); - bool is_layout_test_mode = false; Web::HTML::Window::set_internals_object_exposed(is_layout_test_mode); diff --git a/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp b/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp index e050bbb673..09f423294c 100644 --- a/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp +++ b/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp @@ -11,7 +11,6 @@ jobject global_instance; jclass global_class_reference; jmethodID bind_request_server_method; -jmethodID bind_web_socket_method; jmethodID bind_image_decoder_method; extern "C" JNIEXPORT void JNICALL @@ -30,11 +29,6 @@ Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject t TODO(); bind_request_server_method = method; - method = env->GetMethodID(global_class_reference, "bindWebSocket", "(II)V"); - if (!method) - TODO(); - bind_web_socket_method = method; - method = env->GetMethodID(global_class_reference, "bindImageDecoder", "(II)V"); if (!method) TODO(); @@ -47,12 +41,6 @@ void bind_request_server_java(int ipc_socket, int fd_passing_socket) env.get()->CallVoidMethod(global_instance, bind_request_server_method, ipc_socket, fd_passing_socket); } -void bind_web_socket_java(int ipc_socket, int fd_passing_socket) -{ - Ladybird::JavaEnvironment env(global_vm); - env.get()->CallVoidMethod(global_instance, bind_web_socket_method, ipc_socket, fd_passing_socket); -} - void bind_image_decoder_java(int ipc_socket, int fd_passing_socket) { Ladybird::JavaEnvironment env(global_vm); diff --git a/Ladybird/Android/src/main/cpp/WebSocketService.cpp b/Ladybird/Android/src/main/cpp/WebSocketService.cpp deleted file mode 100644 index aab7df7dd3..0000000000 --- a/Ladybird/Android/src/main/cpp/WebSocketService.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * Copyright (c) 2023, Andrew Kaster - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// FIXME: Share b/w RequestServer and WebSocket -ErrorOr find_certificates(StringView serenity_resource_root) -{ - auto cert_path = ByteString::formatted("{}/ladybird/cacert.pem", serenity_resource_root); - if (!FileSystem::exists(cert_path)) - return Error::from_string_view("Don't know how to load certs!"sv); - return cert_path; -} - -ErrorOr service_main(int ipc_socket, int fd_passing_socket) -{ - // Ensure the certificates are read out here. - DefaultRootCACertificates::set_default_certificate_paths(Vector { TRY(find_certificates(s_serenity_resource_root)) }); - [[maybe_unused]] auto& certs = DefaultRootCACertificates::the(); - - Core::EventLoop event_loop; - - auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket)); - auto client = TRY(WebSocket::ConnectionFromClient::try_create(move(socket))); - client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket))); - - return event_loop.exec(); -} diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt index 0108808b9e..97a59ad89c 100644 --- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt +++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt @@ -35,21 +35,6 @@ class WebContentService : LadybirdServiceBase("WebContentService") { ) } - private fun bindWebSocket(ipcFd: Int, fdPassingFd: Int) - { - val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir) - connector.onDisconnect = { - // FIXME: Notify impl that service is dead and might need restarted - Log.e(TAG, "WebSocket Died! :(") - } - // FIXME: Unbind this at some point maybe - bindService( - Intent(this, WebSocketService::class.java), - connector, - Context.BIND_AUTO_CREATE - ) - } - private fun bindImageDecoder(ipcFd: Int, fdPassingFd: Int) { val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir) diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebSocketService.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebSocketService.kt deleted file mode 100644 index 6d3a2e894f..0000000000 --- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebSocketService.kt +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2023, Andrew Kaster - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -package org.serenityos.ladybird - -import android.os.Message - -class WebSocketService : LadybirdServiceBase("WebSocketService") { - override fun handleServiceSpecificMessage(msg: Message): Boolean { - return false - } - - companion object { - init { - System.loadLibrary("websocket") - } - } -} diff --git a/Ladybird/CMakeLists.txt b/Ladybird/CMakeLists.txt index 55409dcce6..8cf7181df0 100644 --- a/Ladybird/CMakeLists.txt +++ b/Ladybird/CMakeLists.txt @@ -226,10 +226,9 @@ add_subdirectory(RequestServer) add_subdirectory(SQLServer) add_subdirectory(WebContent) add_subdirectory(WebDriver) -add_subdirectory(WebSocket) add_subdirectory(WebWorker) -set(ladybird_helper_processes ImageDecoder RequestServer SQLServer WebContent WebDriver WebSocketServer WebWorker headless-browser) +set(ladybird_helper_processes ImageDecoder RequestServer SQLServer WebContent WebDriver WebWorker headless-browser) add_dependencies(ladybird ${ladybird_helper_processes}) function(create_ladybird_bundle target_name) diff --git a/Ladybird/HelperProcess.cpp b/Ladybird/HelperProcess.cpp index b46ce4a350..a45a51fe2a 100644 --- a/Ladybird/HelperProcess.cpp +++ b/Ladybird/HelperProcess.cpp @@ -178,8 +178,3 @@ ErrorOr> launch_request_server_process(Re { return launch_generic_server_process(candidate_request_server_paths, serenity_resource_root, certificates, "RequestServer"sv); } - -ErrorOr> launch_web_socket_process(ReadonlySpan candidate_web_socket_paths, StringView serenity_resource_root, Vector const& certificates) -{ - return launch_generic_server_process(candidate_web_socket_paths, serenity_resource_root, certificates, "WebSocket"sv); -} diff --git a/Ladybird/HelperProcess.h b/Ladybird/HelperProcess.h index 90605c77ea..2722545d24 100644 --- a/Ladybird/HelperProcess.h +++ b/Ladybird/HelperProcess.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -25,4 +24,3 @@ ErrorOr> launch_web_content_process( ErrorOr> launch_image_decoder_process(ReadonlySpan candidate_image_decoder_paths); ErrorOr> launch_web_worker_process(ReadonlySpan candidate_web_worker_paths, Vector const& certificates); ErrorOr> launch_request_server_process(ReadonlySpan candidate_request_server_paths, StringView serenity_resource_root, Vector const& certificates); -ErrorOr> launch_web_socket_process(ReadonlySpan candidate_web_socket_paths, StringView serenity_resource_root, Vector const& certificates); diff --git a/Ladybird/Qt/RequestManagerQt.cpp b/Ladybird/Qt/RequestManagerQt.cpp index e4657eab17..83810ee4b9 100644 --- a/Ladybird/Qt/RequestManagerQt.cpp +++ b/Ladybird/Qt/RequestManagerQt.cpp @@ -5,6 +5,8 @@ */ #include "RequestManagerQt.h" +#include "WebSocketImplQt.h" +#include "WebSocketQt.h" #include #include @@ -76,6 +78,18 @@ ErrorOr> RequestManagerQt::Request::cre return adopt_ref(*new Request(*reply)); } +RefPtr RequestManagerQt::websocket_connect(AK::URL const& url, AK::ByteString const& origin, Vector 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) { diff --git a/Ladybird/Qt/RequestManagerQt.h b/Ladybird/Qt/RequestManagerQt.h index 3a1087f42d..61087de891 100644 --- a/Ladybird/Qt/RequestManagerQt.h +++ b/Ladybird/Qt/RequestManagerQt.h @@ -28,6 +28,7 @@ public: virtual void preconnect(URL const&) override { } virtual RefPtr start_request(ByteString const& method, URL const&, HashMap const& request_headers, ReadonlyBytes request_body, Core::ProxyData const&) override; + virtual RefPtr websocket_connect(const URL&, ByteString const& origin, Vector const& protocols) override; private slots: void reply_finished(QNetworkReply*); diff --git a/Ladybird/Qt/WebSocketClientManagerQt.cpp b/Ladybird/Qt/WebSocketClientManagerQt.cpp deleted file mode 100644 index 401566ee21..0000000000 --- a/Ladybird/Qt/WebSocketClientManagerQt.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2022, Dex♪ - * Copyright (c) 2022, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "WebSocketClientManagerQt.h" -#include "WebSocketImplQt.h" -#include "WebSocketQt.h" - -namespace Ladybird { - -NonnullRefPtr WebSocketClientManagerQt::create() -{ - return adopt_ref(*new WebSocketClientManagerQt()); -} - -WebSocketClientManagerQt::WebSocketClientManagerQt() = default; -WebSocketClientManagerQt::~WebSocketClientManagerQt() = default; - -RefPtr WebSocketClientManagerQt::connect(URL const& url, ByteString const& origin, Vector 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); -} - -} diff --git a/Ladybird/Qt/WebSocketClientManagerQt.h b/Ladybird/Qt/WebSocketClientManagerQt.h deleted file mode 100644 index a60ec0b4b2..0000000000 --- a/Ladybird/Qt/WebSocketClientManagerQt.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2022, Dex♪ - * Copyright (c) 2022, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include - -#pragma once - -namespace Ladybird { - -class WebSocketClientManagerQt : public Web::WebSockets::WebSocketClientManager { -public: - static NonnullRefPtr create(); - - virtual ~WebSocketClientManagerQt() override; - virtual RefPtr connect(URL const&, ByteString const& origin, Vector const& protocols) override; - -private: - WebSocketClientManagerQt(); -}; - -} diff --git a/Ladybird/RequestServer/CMakeLists.txt b/Ladybird/RequestServer/CMakeLists.txt index 3b6f4e94e5..128dc1dbd4 100644 --- a/Ladybird/RequestServer/CMakeLists.txt +++ b/Ladybird/RequestServer/CMakeLists.txt @@ -33,7 +33,7 @@ target_link_libraries(RequestServer PRIVATE requestserver) target_include_directories(requestserver PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/) target_include_directories(requestserver PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) -target_link_libraries(requestserver PUBLIC LibCore LibMain LibCrypto LibFileSystem LibGemini LibHTTP LibIPC LibMain LibTLS LibWebView) +target_link_libraries(requestserver PUBLIC LibCore LibMain LibCrypto LibFileSystem LibGemini LibHTTP LibIPC LibMain LibTLS LibWebView LibWebSocket) if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") # Solaris has socket and networking related functions in two extra libraries target_link_libraries(requestserver PUBLIC nsl socket) diff --git a/Ladybird/WebContent/CMakeLists.txt b/Ladybird/WebContent/CMakeLists.txt index fadd13dfa1..d9316e389b 100644 --- a/Ladybird/WebContent/CMakeLists.txt +++ b/Ladybird/WebContent/CMakeLists.txt @@ -21,7 +21,6 @@ if (ENABLE_QT) ../Qt/EventLoopImplementationQtEventTarget.cpp ../Qt/RequestManagerQt.cpp ../Qt/StringUtils.cpp - ../Qt/WebSocketClientManagerQt.cpp ../Qt/WebSocketQt.cpp ../Qt/WebSocketImplQt.cpp main.cpp diff --git a/Ladybird/WebContent/main.cpp b/Ladybird/WebContent/main.cpp index b4b3fad884..066bf9f3bd 100644 --- a/Ladybird/WebContent/main.cpp +++ b/Ladybird/WebContent/main.cpp @@ -38,7 +38,6 @@ #if defined(HAVE_QT) # include # include -# include # include # if defined(HAVE_QT_MULTIMEDIA) @@ -109,14 +108,11 @@ ErrorOr serenity_main(Main::Arguments arguments) } #if defined(HAVE_QT) - if (!use_lagom_networking) { + if (!use_lagom_networking) Web::ResourceLoader::initialize(Ladybird::RequestManagerQt::create()); - Web::WebSockets::WebSocketClientManager::initialize(Ladybird::WebSocketClientManagerQt::create()); - } else + else #endif - { TRY(initialize_lagom_networking(certificates)); - } Web::HTML::Window::set_internals_object_exposed(is_layout_test_mode); @@ -195,9 +191,5 @@ static ErrorOr initialize_lagom_networking(Vector const& certi auto request_server_client = TRY(launch_request_server_process(candidate_request_server_paths, s_serenity_resource_root, certificates)); Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client)))); - auto candidate_web_socket_paths = TRY(get_paths_for_helper_process("WebSocket"sv)); - auto web_socket_client = TRY(launch_web_socket_process(candidate_web_socket_paths, s_serenity_resource_root, certificates)); - Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create(move(web_socket_client)))); - return {}; } diff --git a/Ladybird/WebSocket/CMakeLists.txt b/Ladybird/WebSocket/CMakeLists.txt deleted file mode 100644 index 3e230a05cb..0000000000 --- a/Ladybird/WebSocket/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -set(SOURCES - "${SERENITY_SOURCE_DIR}/Userland/Services/WebSocket/ConnectionFromClient.cpp" -) - -if (ANDROID) - add_library(websocket SHARED - ${SOURCES} - ../Android/src/main/cpp/WebSocketService.cpp - ../Android/src/main/cpp/LadybirdServiceBaseJNI.cpp - ../Utilities.cpp - ) -else() - add_library(websocket STATIC ${SOURCES}) -endif() -add_executable(WebSocketServer main.cpp) -target_link_libraries(WebSocketServer PRIVATE websocket) -set_target_properties(WebSocketServer PROPERTIES OUTPUT_NAME WebSocket) -target_link_libraries(websocket PUBLIC LibCore LibFileSystem LibIPC LibMain LibTLS LibWebSocket LibWebView) diff --git a/Ladybird/WebSocket/main.cpp b/Ladybird/WebSocket/main.cpp deleted file mode 100644 index 632865b55b..0000000000 --- a/Ladybird/WebSocket/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * Copyright (c) 2023, Andrew Kaster - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// FIXME: Share b/w RequestServer and WebSocket -ErrorOr find_certificates(StringView serenity_resource_root) -{ - auto cert_path = ByteString::formatted("{}/ladybird/cacert.pem", serenity_resource_root); - if (!FileSystem::exists(cert_path)) - return Error::from_string_view("Don't know how to load certs!"sv); - return cert_path; -} - -ErrorOr serenity_main(Main::Arguments arguments) -{ - AK::set_rich_debug_enabled(true); - - int fd_passing_socket { -1 }; - StringView serenity_resource_root; - Vector certificates; - - Core::ArgsParser args_parser; - args_parser.add_option(fd_passing_socket, "File descriptor of the fd passing socket", "fd-passing-socket", 'c', "fd-passing-socket"); - args_parser.add_option(certificates, "Path to a certificate file", "certificate", 'C', "certificate"); - args_parser.add_option(serenity_resource_root, "Absolute path to directory for serenity resources", "serenity-resource-root", 'r', "serenity-resource-root"); - args_parser.parse(arguments); - - // Ensure the certificates are read out here. - if (certificates.is_empty()) - certificates.append(TRY(find_certificates(serenity_resource_root))); - DefaultRootCACertificates::set_default_certificate_paths(certificates.span()); - [[maybe_unused]] auto& certs = DefaultRootCACertificates::the(); - - Core::EventLoop event_loop; - - auto client = TRY(IPC::take_over_accepted_client_from_system_server()); - client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket))); - - return event_loop.exec(); -} diff --git a/Ladybird/WebWorker/main.cpp b/Ladybird/WebWorker/main.cpp index 108bd14537..95f58dde49 100644 --- a/Ladybird/WebWorker/main.cpp +++ b/Ladybird/WebWorker/main.cpp @@ -67,9 +67,5 @@ static ErrorOr initialize_lagom_networking(Vector const& certi auto request_server_client = TRY(launch_request_server_process(candidate_request_server_paths, s_serenity_resource_root, certificates)); Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create(move(request_server_client)))); - auto candidate_web_socket_paths = TRY(get_paths_for_helper_process("WebSocket"sv)); - auto web_socket_client = TRY(launch_web_socket_process(candidate_web_socket_paths, s_serenity_resource_root, certificates)); - Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create(move(web_socket_client)))); - return {}; } diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index 2ae913e3ce..71b98ef093 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -486,8 +486,6 @@ if (BUILD_LAGOM) # These are needed for both LibWeb and LibProtocol. compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/RequestServer/RequestClient.ipc Userland/Services/RequestServer/RequestClientEndpoint.h) compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/RequestServer/RequestServer.ipc Userland/Services/RequestServer/RequestServerEndpoint.h) - compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebSocket/WebSocketClient.ipc Userland/Services/WebSocket/WebSocketClientEndpoint.h) - compile_ipc(${SERENITY_PROJECT_ROOT}/Userland/Services/WebSocket/WebSocketServer.ipc Userland/Services/WebSocket/WebSocketServerEndpoint.h) if (ENABLE_LAGOM_LIBWEB) list(APPEND lagom_standard_libraries Web WebView) diff --git a/Meta/gn/secondary/Ladybird/BUILD.gn b/Meta/gn/secondary/Ladybird/BUILD.gn index dce1827492..1b1b210c60 100644 --- a/Meta/gn/secondary/Ladybird/BUILD.gn +++ b/Meta/gn/secondary/Ladybird/BUILD.gn @@ -335,7 +335,6 @@ if (current_os != "mac") { "$root_out_dir/libexec/SQLServer", "$root_out_dir/libexec/WebContent", "$root_out_dir/libexec/WebDriver", - "$root_out_dir/libexec/WebSocket", "$root_out_dir/libexec/WebWorker", "$root_out_dir/libexec/headless-browser", ] diff --git a/Meta/gn/secondary/Ladybird/RequestServer/BUILD.gn b/Meta/gn/secondary/Ladybird/RequestServer/BUILD.gn index 20b51bc9f1..460764bac1 100644 --- a/Meta/gn/secondary/Ladybird/RequestServer/BUILD.gn +++ b/Meta/gn/secondary/Ladybird/RequestServer/BUILD.gn @@ -15,6 +15,7 @@ executable("RequestServer") { "//Userland/Libraries/LibMain", "//Userland/Libraries/LibProtocol", "//Userland/Libraries/LibTLS", + "//Userland/Libraries/LibWebSocket", ] sources = [ "//Userland/Services/RequestServer/ConnectionCache.cpp", diff --git a/Meta/gn/secondary/Ladybird/WebSocket/BUILD.gn b/Meta/gn/secondary/Ladybird/WebSocket/BUILD.gn deleted file mode 100644 index d2df881fb2..0000000000 --- a/Meta/gn/secondary/Ladybird/WebSocket/BUILD.gn +++ /dev/null @@ -1,22 +0,0 @@ -executable("WebSocket") { - configs += [ "//Ladybird:ladybird_config" ] - include_dirs = [ - "//Userland/Libraries", - "//Userland/Services", - ] - deps = [ - "//AK", - "//Userland/Libraries/LibCore", - "//Userland/Libraries/LibFileSystem", - "//Userland/Libraries/LibIPC", - "//Userland/Libraries/LibMain", - "//Userland/Libraries/LibProtocol", - "//Userland/Libraries/LibTLS", - "//Userland/Libraries/LibWebSocket", - ] - sources = [ - "//Userland/Services/WebSocket/ConnectionFromClient.cpp", - "main.cpp", - ] - output_dir = "$root_out_dir/libexec" -} diff --git a/Meta/gn/secondary/Userland/Libraries/LibProtocol/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibProtocol/BUILD.gn index 4c35a51339..faa3fce922 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibProtocol/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibProtocol/BUILD.gn @@ -22,28 +22,6 @@ compiled_action("RequestServerEndpoint") { ] } -compiled_action("WebSocketClientEndpoint") { - tool = "//Meta/Lagom/Tools/CodeGenerators/IPCCompiler" - inputs = [ "//Userland/Services/WebSocket/WebSocketClient.ipc" ] - outputs = [ "$root_gen_dir/WebSocket/WebSocketClientEndpoint.h" ] - args = [ - rebase_path(inputs[0], root_build_dir), - "-o", - rebase_path(outputs[0], root_build_dir), - ] -} - -compiled_action("WebSocketServerEndpoint") { - tool = "//Meta/Lagom/Tools/CodeGenerators/IPCCompiler" - inputs = [ "//Userland/Services/WebSocket/WebSocketServer.ipc" ] - outputs = [ "$root_gen_dir/WebSocket/WebSocketServerEndpoint.h" ] - args = [ - rebase_path(inputs[0], root_build_dir), - "-o", - rebase_path(outputs[0], root_build_dir), - ] -} - shared_library("LibProtocol") { output_name = "protocol" include_dirs = [ @@ -53,8 +31,6 @@ shared_library("LibProtocol") { deps = [ ":RequestClientEndpoint", ":RequestServerEndpoint", - ":WebSocketClientEndpoint", - ":WebSocketServerEndpoint", "//AK", "//Userland/Libraries/LibCore", "//Userland/Libraries/LibIPC", @@ -63,10 +39,7 @@ shared_library("LibProtocol") { "Request.cpp", "RequestClient.cpp", "WebSocket.cpp", - "WebSocketClient.cpp", ] sources += get_target_outputs(":RequestClientEndpoint") + - get_target_outputs(":RequestServerEndpoint") + - get_target_outputs(":WebSocketClientEndpoint") + - get_target_outputs(":WebSocketServerEndpoint") + get_target_outputs(":RequestServerEndpoint") } diff --git a/Userland/Applications/Browser/CMakeLists.txt b/Userland/Applications/Browser/CMakeLists.txt index 6409346b0f..95a40e7f75 100644 --- a/Userland/Applications/Browser/CMakeLists.txt +++ b/Userland/Applications/Browser/CMakeLists.txt @@ -2,7 +2,7 @@ serenity_component( Browser RECOMMENDED TARGETS Browser - DEPENDS BrowserSettings ImageDecoder RequestServer WebContent WebSocket + DEPENDS BrowserSettings ImageDecoder RequestServer WebContent ) stringify_gml(BrowserWindow.gml BrowserWindowGML.h browser_window_gml) diff --git a/Userland/Libraries/LibProtocol/CMakeLists.txt b/Userland/Libraries/LibProtocol/CMakeLists.txt index 95d340b699..cbf23b0fc1 100644 --- a/Userland/Libraries/LibProtocol/CMakeLists.txt +++ b/Userland/Libraries/LibProtocol/CMakeLists.txt @@ -2,14 +2,11 @@ set(SOURCES Request.cpp RequestClient.cpp WebSocket.cpp - WebSocketClient.cpp ) set(GENERATED_SOURCES ../../Services/RequestServer/RequestClientEndpoint.h ../../Services/RequestServer/RequestServerEndpoint.h - ../../Services/WebSocket/WebSocketClientEndpoint.h - ../../Services/WebSocket/WebSocketServerEndpoint.h ) serenity_lib(LibProtocol protocol) diff --git a/Userland/Libraries/LibProtocol/RequestClient.cpp b/Userland/Libraries/LibProtocol/RequestClient.cpp index a8c297d93b..d9cb3f7a34 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.cpp +++ b/Userland/Libraries/LibProtocol/RequestClient.cpp @@ -103,6 +103,54 @@ void RequestClient::certificate_requested(i32 request_id) } } +RefPtr RequestClient::websocket_connect(const URL& url, ByteString const& origin, Vector const& protocols, Vector const& extensions, HashMap const& request_headers) +{ + auto headers_or_error = request_headers.clone(); + if (headers_or_error.is_error()) + return nullptr; + auto connection_id = IPCProxy::websocket_connect(url, origin, protocols, extensions, headers_or_error.release_value()); + if (connection_id < 0) + return nullptr; + auto connection = WebSocket::create_from_id({}, *this, connection_id); + m_websockets.set(connection_id, connection); + return connection; +} + +void RequestClient::websocket_connected(i32 connection_id) +{ + auto maybe_connection = m_websockets.get(connection_id); + if (maybe_connection.has_value()) + maybe_connection.value()->did_open({}); +} + +void RequestClient::websocket_received(i32 connection_id, bool is_text, ByteBuffer const& data) +{ + auto maybe_connection = m_websockets.get(connection_id); + if (maybe_connection.has_value()) + maybe_connection.value()->did_receive({}, data, is_text); +} + +void RequestClient::websocket_errored(i32 connection_id, i32 message) +{ + auto maybe_connection = m_websockets.get(connection_id); + if (maybe_connection.has_value()) + maybe_connection.value()->did_error({}, message); +} + +void RequestClient::websocket_closed(i32 connection_id, u16 code, ByteString const& reason, bool clean) +{ + auto maybe_connection = m_websockets.get(connection_id); + if (maybe_connection.has_value()) + maybe_connection.value()->did_close({}, code, reason, clean); +} + +void RequestClient::websocket_certificate_requested(i32 connection_id) +{ + auto maybe_connection = m_websockets.get(connection_id); + if (maybe_connection.has_value()) + maybe_connection.value()->did_request_certificates({}); +} + } template RefPtr Protocol::RequestClient::start_request(ByteString const& method, URL const&, HashMap const& request_headers, ReadonlyBytes request_body, Core::ProxyData const&); diff --git a/Userland/Libraries/LibProtocol/RequestClient.h b/Userland/Libraries/LibProtocol/RequestClient.h index fda544e871..05fb4f1119 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.h +++ b/Userland/Libraries/LibProtocol/RequestClient.h @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include @@ -26,6 +28,8 @@ public: template> RefPtr start_request(ByteString const& method, URL const&, HashMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}); + RefPtr websocket_connect(const URL&, ByteString const& origin = {}, Vector const& protocols = {}, Vector const& extensions = {}, HashMap const& request_headers = {}); + void ensure_connection(URL const&, ::RequestServer::CacheLevel); bool stop_request(Badge, Request&); @@ -38,7 +42,14 @@ private: virtual void certificate_requested(i32) override; virtual void headers_became_available(i32, HashMap const&, Optional const&) override; + virtual void websocket_connected(i32) override; + virtual void websocket_received(i32, bool, ByteBuffer const&) override; + virtual void websocket_errored(i32, i32) override; + virtual void websocket_closed(i32, u16, ByteString const&, bool) override; + virtual void websocket_certificate_requested(i32) override; + HashMap> m_requests; + HashMap> m_websockets; }; } diff --git a/Userland/Libraries/LibProtocol/WebSocket.cpp b/Userland/Libraries/LibProtocol/WebSocket.cpp index 9f6d51f876..2dd2d56c23 100644 --- a/Userland/Libraries/LibProtocol/WebSocket.cpp +++ b/Userland/Libraries/LibProtocol/WebSocket.cpp @@ -4,12 +4,12 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include -#include namespace Protocol { -WebSocket::WebSocket(WebSocketClient& client, i32 connection_id) +WebSocket::WebSocket(RequestClient& client, i32 connection_id) : m_client(client) , m_connection_id(connection_id) { @@ -17,17 +17,17 @@ WebSocket::WebSocket(WebSocketClient& client, i32 connection_id) WebSocket::ReadyState WebSocket::ready_state() { - return (WebSocket::ReadyState)m_client->ready_state({}, *this); + return static_cast(m_client->websocket_ready_state(m_connection_id)); } ByteString WebSocket::subprotocol_in_use() { - return m_client->subprotocol_in_use({}, *this); + return m_client->websocket_subprotocol_in_use(m_connection_id); } void WebSocket::send(ByteBuffer binary_or_text_message, bool is_text) { - m_client->send({}, *this, move(binary_or_text_message), is_text); + m_client->async_websocket_send(m_connection_id, is_text, move(binary_or_text_message)); } void WebSocket::send(StringView text_message) @@ -37,38 +37,38 @@ void WebSocket::send(StringView text_message) void WebSocket::close(u16 code, ByteString reason) { - m_client->close({}, *this, code, move(reason)); + m_client->async_websocket_close(m_connection_id, code, move(reason)); } -void WebSocket::did_open(Badge) +void WebSocket::did_open(Badge) { if (on_open) on_open(); } -void WebSocket::did_receive(Badge, ByteBuffer data, bool is_text) +void WebSocket::did_receive(Badge, ByteBuffer data, bool is_text) { if (on_message) on_message(WebSocket::Message { move(data), is_text }); } -void WebSocket::did_error(Badge, i32 error_code) +void WebSocket::did_error(Badge, i32 error_code) { if (on_error) on_error((WebSocket::Error)error_code); } -void WebSocket::did_close(Badge, u16 code, ByteString reason, bool was_clean) +void WebSocket::did_close(Badge, u16 code, ByteString reason, bool was_clean) { if (on_close) on_close(code, move(reason), was_clean); } -void WebSocket::did_request_certificates(Badge) +void WebSocket::did_request_certificates(Badge) { if (on_certificate_requested) { auto result = on_certificate_requested(); - if (!m_client->set_certificate({}, *this, result.certificate, result.key)) + if (!m_client->websocket_set_certificate(m_connection_id, result.certificate, result.key)) dbgln("WebSocket: set_certificate failed"); } } diff --git a/Userland/Libraries/LibProtocol/WebSocket.h b/Userland/Libraries/LibProtocol/WebSocket.h index cc3f9e64ae..ef7b9212ff 100644 --- a/Userland/Libraries/LibProtocol/WebSocket.h +++ b/Userland/Libraries/LibProtocol/WebSocket.h @@ -17,7 +17,7 @@ namespace Protocol { -class WebSocketClient; +class RequestClient; class WebSocket : public RefCounted { public: @@ -44,7 +44,7 @@ public: Closed = 3, }; - static NonnullRefPtr create_from_id(Badge, WebSocketClient& client, i32 connection_id) + static NonnullRefPtr create_from_id(Badge, RequestClient& client, i32 connection_id) { return adopt_ref(*new WebSocket(client, connection_id)); } @@ -65,15 +65,15 @@ public: Function on_close; Function on_certificate_requested; - void did_open(Badge); - void did_receive(Badge, ByteBuffer, bool); - void did_error(Badge, i32); - void did_close(Badge, u16, ByteString, bool); - void did_request_certificates(Badge); + void did_open(Badge); + void did_receive(Badge, ByteBuffer, bool); + void did_error(Badge, i32); + void did_close(Badge, u16, ByteString, bool); + void did_request_certificates(Badge); private: - explicit WebSocket(WebSocketClient&, i32 connection_id); - WeakPtr m_client; + explicit WebSocket(RequestClient&, i32 connection_id); + WeakPtr m_client; int m_connection_id { -1 }; }; diff --git a/Userland/Libraries/LibProtocol/WebSocketClient.cpp b/Userland/Libraries/LibProtocol/WebSocketClient.cpp deleted file mode 100644 index 0f5d52ea44..0000000000 --- a/Userland/Libraries/LibProtocol/WebSocketClient.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include - -namespace Protocol { - -WebSocketClient::WebSocketClient(NonnullOwnPtr socket) - : IPC::ConnectionToServer(*this, move(socket)) -{ -} - -RefPtr WebSocketClient::connect(const URL& url, ByteString const& origin, Vector const& protocols, Vector const& extensions, HashMap const& request_headers) -{ - auto headers_or_error = request_headers.clone(); - if (headers_or_error.is_error()) - return nullptr; - auto connection_id = IPCProxy::connect(url, origin, protocols, extensions, headers_or_error.release_value()); - if (connection_id < 0) - return nullptr; - auto connection = WebSocket::create_from_id({}, *this, connection_id); - m_connections.set(connection_id, connection); - return connection; -} - -u32 WebSocketClient::ready_state(Badge, WebSocket& connection) -{ - if (!m_connections.contains(connection.id())) - return (u32)WebSocket::ReadyState::Closed; - return IPCProxy::ready_state(connection.id()); -} - -ByteString WebSocketClient::subprotocol_in_use(Badge, WebSocket& connection) -{ - if (!m_connections.contains(connection.id())) - return ByteString::empty(); - return IPCProxy::subprotocol_in_use(connection.id()); -} - -void WebSocketClient::send(Badge, WebSocket& connection, ByteBuffer data, bool is_text) -{ - if (!m_connections.contains(connection.id())) - return; - async_send(connection.id(), is_text, move(data)); -} - -void WebSocketClient::close(Badge, WebSocket& connection, u16 code, ByteString message) -{ - if (!m_connections.contains(connection.id())) - return; - async_close(connection.id(), code, move(message)); -} - -bool WebSocketClient::set_certificate(Badge, WebSocket& connection, ByteString certificate, ByteString key) -{ - if (!m_connections.contains(connection.id())) - return false; - return IPCProxy::set_certificate(connection.id(), move(certificate), move(key)); -} - -void WebSocketClient::connected(i32 connection_id) -{ - auto maybe_connection = m_connections.get(connection_id); - if (maybe_connection.has_value()) - maybe_connection.value()->did_open({}); -} - -void WebSocketClient::received(i32 connection_id, bool is_text, ByteBuffer const& data) -{ - auto maybe_connection = m_connections.get(connection_id); - if (maybe_connection.has_value()) - maybe_connection.value()->did_receive({}, data, is_text); -} - -void WebSocketClient::errored(i32 connection_id, i32 message) -{ - auto maybe_connection = m_connections.get(connection_id); - if (maybe_connection.has_value()) - maybe_connection.value()->did_error({}, message); -} - -void WebSocketClient::closed(i32 connection_id, u16 code, ByteString const& reason, bool clean) -{ - auto maybe_connection = m_connections.get(connection_id); - if (maybe_connection.has_value()) - maybe_connection.value()->did_close({}, code, reason, clean); -} - -void WebSocketClient::certificate_requested(i32 connection_id) -{ - auto maybe_connection = m_connections.get(connection_id); - if (maybe_connection.has_value()) - maybe_connection.value()->did_request_certificates({}); -} - -} diff --git a/Userland/Libraries/LibProtocol/WebSocketClient.h b/Userland/Libraries/LibProtocol/WebSocketClient.h deleted file mode 100644 index aab80123e5..0000000000 --- a/Userland/Libraries/LibProtocol/WebSocketClient.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace Protocol { - -class WebSocket; - -class WebSocketClient final - : public IPC::ConnectionToServer - , public WebSocketClientEndpoint { - IPC_CLIENT_CONNECTION(WebSocketClient, "/tmp/session/%sid/portal/websocket"sv) - -public: - explicit WebSocketClient(NonnullOwnPtr); - - RefPtr connect(const URL&, ByteString const& origin = {}, Vector const& protocols = {}, Vector const& extensions = {}, HashMap const& request_headers = {}); - - u32 ready_state(Badge, WebSocket&); - ByteString subprotocol_in_use(Badge, WebSocket&); - void send(Badge, WebSocket&, ByteBuffer, bool is_text); - void close(Badge, WebSocket&, u16 code, ByteString reason); - bool set_certificate(Badge, WebSocket&, ByteString, ByteString); - -private: - virtual void connected(i32) override; - virtual void received(i32, bool, ByteBuffer const&) override; - virtual void errored(i32, i32) override; - virtual void closed(i32, u16, ByteString const&, bool) override; - virtual void certificate_requested(i32) override; - - HashMap> m_connections; -}; - -} diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h index ec4aa74f38..878dbb698b 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h @@ -66,6 +66,10 @@ namespace Web { constexpr auto default_user_agent = "Mozilla/5.0 (" OS_STRING "; " CPU_STRING ") " BROWSER_NAME "/" BROWSER_VERSION ""sv; constexpr auto default_platform = OS_STRING " " CPU_STRING ""sv; +namespace WebSockets { +class WebSocketClientSocket; +} + class ResourceLoaderConnectorRequest : public RefCounted { public: virtual ~ResourceLoaderConnectorRequest(); @@ -97,6 +101,7 @@ public: virtual void preconnect(URL const&) = 0; virtual RefPtr start_request(ByteString const& method, URL const&, HashMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) = 0; + virtual RefPtr websocket_connect(const URL&, ByteString const& origin, Vector const& protocols) = 0; protected: explicit ResourceLoaderConnector(); diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp index 8efb6447f2..c8e5c72a5f 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -29,28 +30,8 @@ namespace Web::WebSockets { JS_DEFINE_ALLOCATOR(WebSocket); -static RefPtr s_websocket_client_manager; - -void WebSocketClientManager::initialize(RefPtr websocket_client_manager) -{ - s_websocket_client_manager = websocket_client_manager; -} - -WebSocketClientManager& WebSocketClientManager::the() -{ - if (!s_websocket_client_manager) [[unlikely]] { - dbgln("Web::WebSockets::WebSocketClientManager was not initialized!"); - VERIFY_NOT_REACHED(); - } - return *s_websocket_client_manager; -} - -WebSocketClientSocket::WebSocketClientSocket() = default; - WebSocketClientSocket::~WebSocketClientSocket() = default; -WebSocketClientManager::WebSocketClientManager() = default; - // https://websockets.spec.whatwg.org/#dom-websocket-websocket WebIDL::ExceptionOr> WebSocket::construct_impl(JS::Realm& realm, String const& url, Optional>> const& protocols) { @@ -148,7 +129,7 @@ ErrorOr WebSocket::establish_web_socket_connection(URL& url_record, Vector for (auto const& protocol : protocols) TRY(protcol_byte_strings.try_append(protocol.to_byte_string())); - m_websocket = WebSocketClientManager::the().connect(url_record, origin_string, protcol_byte_strings); + m_websocket = ResourceLoader::the().connector().websocket_connect(url_record, origin_string, protcol_byte_strings); m_websocket->on_open = [weak_this = make_weak_ptr()] { if (!weak_this) return; diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.h b/Userland/Libraries/LibWeb/WebSockets/WebSocket.h index 20160d4ac4..3c9737e5e7 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.h +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.h @@ -114,19 +114,7 @@ public: Function on_certificate_requested; protected: - explicit WebSocketClientSocket(); -}; - -class WebSocketClientManager : public Core::EventReceiver { - C_OBJECT_ABSTRACT(WebSocketClientManager) -public: - static void initialize(RefPtr); - static WebSocketClientManager& the(); - - virtual RefPtr connect(URL const&, ByteString const& origin, Vector const& protocols) = 0; - -protected: - explicit WebSocketClientManager(); + explicit WebSocketClientSocket() = default; }; } diff --git a/Userland/Libraries/LibWebView/CMakeLists.txt b/Userland/Libraries/LibWebView/CMakeLists.txt index 104e65378e..edcb3e1c4d 100644 --- a/Userland/Libraries/LibWebView/CMakeLists.txt +++ b/Userland/Libraries/LibWebView/CMakeLists.txt @@ -40,8 +40,6 @@ set(GENERATED_SOURCES ../../Services/WebContent/WebContentServerEndpoint.h ../../Services/WebContent/WebDriverClientEndpoint.h ../../Services/WebContent/WebDriverServerEndpoint.h - ../../Services/WebSocket/WebSocketClientEndpoint.h - ../../Services/WebSocket/WebSocketServerEndpoint.h NativeStyleSheetSource.cpp ) diff --git a/Userland/Libraries/LibWebView/RequestServerAdapter.cpp b/Userland/Libraries/LibWebView/RequestServerAdapter.cpp index 42055e29b5..6c09129527 100644 --- a/Userland/Libraries/LibWebView/RequestServerAdapter.cpp +++ b/Userland/Libraries/LibWebView/RequestServerAdapter.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include "WebSocketClientAdapter.h" #include #include #include @@ -94,6 +95,14 @@ RefPtr RequestServerAdapter::start_request( return RequestServerRequestAdapter::try_create(protocol_request.release_nonnull()).release_value_but_fixme_should_propagate_errors(); } +RefPtr RequestServerAdapter::websocket_connect(AK::URL const& url, AK::ByteString const& origin, Vector 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 const& url) { m_protocol_client->ensure_connection(url, RequestServer::CacheLevel::ResolveOnly); diff --git a/Userland/Libraries/LibWebView/RequestServerAdapter.h b/Userland/Libraries/LibWebView/RequestServerAdapter.h index 220a4f46a7..e1a4317aa9 100644 --- a/Userland/Libraries/LibWebView/RequestServerAdapter.h +++ b/Userland/Libraries/LibWebView/RequestServerAdapter.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace Protocol { class Request; @@ -46,6 +47,7 @@ public: virtual void preconnect(URL const& url) override; virtual RefPtr start_request(ByteString const& method, URL const&, HashMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) override; + virtual RefPtr websocket_connect(const URL&, ByteString const& origin, Vector const& protocols) override; private: RefPtr m_protocol_client; diff --git a/Userland/Libraries/LibWebView/WebSocketClientAdapter.cpp b/Userland/Libraries/LibWebView/WebSocketClientAdapter.cpp index 9e93e757e9..6eaf2463e7 100644 --- a/Userland/Libraries/LibWebView/WebSocketClientAdapter.cpp +++ b/Userland/Libraries/LibWebView/WebSocketClientAdapter.cpp @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include -#include #include namespace WebView { @@ -107,30 +107,4 @@ void WebSocketClientSocketAdapter::close(u16 code, ByteString reason) m_websocket->close(code, reason); } -ErrorOr> WebSocketClientManagerAdapter::try_create(NonnullRefPtr websocket_client) -{ - return adopt_nonnull_ref_or_enomem(new (nothrow) WebSocketClientManagerAdapter(move(websocket_client))); -} - -ErrorOr> WebSocketClientManagerAdapter::try_create() -{ - auto websocket_client = TRY(Protocol::WebSocketClient::try_create()); - return adopt_nonnull_ref_or_enomem(new (nothrow) WebSocketClientManagerAdapter(move(websocket_client))); -} - -WebSocketClientManagerAdapter::WebSocketClientManagerAdapter(NonnullRefPtr websocket_client) - : m_websocket_client(move(websocket_client)) -{ -} - -WebSocketClientManagerAdapter::~WebSocketClientManagerAdapter() = default; - -RefPtr WebSocketClientManagerAdapter::connect(const URL& url, ByteString const& origin, Vector const& protocols) -{ - auto underlying_websocket = m_websocket_client->connect(url, origin, protocols); - if (!underlying_websocket) - return {}; - return WebSocketClientSocketAdapter::create(underlying_websocket.release_nonnull()); -} - } diff --git a/Userland/Libraries/LibWebView/WebSocketClientAdapter.h b/Userland/Libraries/LibWebView/WebSocketClientAdapter.h index 9dd9c45f48..d37da67870 100644 --- a/Userland/Libraries/LibWebView/WebSocketClientAdapter.h +++ b/Userland/Libraries/LibWebView/WebSocketClientAdapter.h @@ -13,7 +13,7 @@ namespace Protocol { class WebSocket; -class WebSocketClient; +class RequestClient; }; namespace WebView { @@ -38,19 +38,4 @@ private: NonnullRefPtr m_websocket; }; -class WebSocketClientManagerAdapter : public Web::WebSockets::WebSocketClientManager { -public: - static ErrorOr> try_create(NonnullRefPtr); - static ErrorOr> try_create(); - - virtual ~WebSocketClientManagerAdapter() override; - - virtual RefPtr connect(const URL&, ByteString const& origin, Vector const& protocols) override; - -private: - WebSocketClientManagerAdapter(NonnullRefPtr); - - NonnullRefPtr m_websocket_client; -}; - } diff --git a/Userland/Services/CMakeLists.txt b/Userland/Services/CMakeLists.txt index 82e72923de..1773bce081 100644 --- a/Userland/Services/CMakeLists.txt +++ b/Userland/Services/CMakeLists.txt @@ -26,7 +26,6 @@ if (SERENITYOS) add_subdirectory(TelnetServer) add_subdirectory(WebContent) add_subdirectory(WebDriver) - add_subdirectory(WebSocket) add_subdirectory(WebWorker) add_subdirectory(WindowServer) endif() diff --git a/Userland/Services/RequestServer/CMakeLists.txt b/Userland/Services/RequestServer/CMakeLists.txt index 9090b009bd..3b990aa09f 100644 --- a/Userland/Services/RequestServer/CMakeLists.txt +++ b/Userland/Services/RequestServer/CMakeLists.txt @@ -26,4 +26,4 @@ set(GENERATED_SOURCES ) serenity_bin(RequestServer) -target_link_libraries(RequestServer PRIVATE LibCore LibCrypto LibIPC LibGemini LibHTTP LibMain LibTLS) +target_link_libraries(RequestServer PRIVATE LibCore LibCrypto LibIPC LibGemini LibHTTP LibMain LibTLS LibWebSocket) diff --git a/Userland/Services/RequestServer/ConnectionFromClient.cpp b/Userland/Services/RequestServer/ConnectionFromClient.cpp index d732fe5c12..d7162d1fc4 100644 --- a/Userland/Services/RequestServer/ConnectionFromClient.cpp +++ b/Userland/Services/RequestServer/ConnectionFromClient.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -187,4 +189,80 @@ void ConnectionFromClient::ensure_connection(URL const& url, ::RequestServer::Ca dbgln("EnsureConnection: Invalid URL scheme: '{}'", url.scheme()); } +static i32 s_next_websocket_id = 1; +Messages::RequestServer::WebsocketConnectResponse ConnectionFromClient::websocket_connect(URL const& url, ByteString const& origin, Vector const& protocols, Vector const& extensions, HashMap const& additional_request_headers) +{ + if (!url.is_valid()) { + dbgln("WebSocket::Connect: Invalid URL requested: '{}'", url); + return -1; + } + + WebSocket::ConnectionInfo connection_info(url); + connection_info.set_origin(origin); + connection_info.set_protocols(protocols); + connection_info.set_extensions(extensions); + + Vector headers; + for (auto const& header : additional_request_headers) { + headers.append({ header.key, header.value }); + } + connection_info.set_headers(headers); + + auto id = ++s_next_websocket_id; + auto connection = WebSocket::WebSocket::create(move(connection_info)); + connection->on_open = [this, id]() { + async_websocket_connected(id); + }; + connection->on_message = [this, id](auto message) { + async_websocket_received(id, message.is_text(), message.data()); + }; + connection->on_error = [this, id](auto message) { + async_websocket_errored(id, (i32)message); + }; + connection->on_close = [this, id](u16 code, ByteString reason, bool was_clean) { + async_websocket_closed(id, code, move(reason), was_clean); + }; + + connection->start(); + m_websockets.set(id, move(connection)); + return id; +} + +Messages::RequestServer::WebsocketReadyStateResponse ConnectionFromClient::websocket_ready_state(i32 connection_id) +{ + if (auto connection = m_websockets.get(connection_id).value_or({})) + return (u32)connection->ready_state(); + return (u32)WebSocket::ReadyState::Closed; +} + +Messages::RequestServer::WebsocketSubprotocolInUseResponse ConnectionFromClient::websocket_subprotocol_in_use(i32 connection_id) +{ + if (auto connection = m_websockets.get(connection_id).value_or({})) + return connection->subprotocol_in_use(); + return ByteString::empty(); +} + +void ConnectionFromClient::websocket_send(i32 connection_id, bool is_text, ByteBuffer const& data) +{ + if (auto connection = m_websockets.get(connection_id).value_or({}); connection && connection->ready_state() == WebSocket::ReadyState::Open) + connection->send(WebSocket::Message { data, is_text }); +} + +void ConnectionFromClient::websocket_close(i32 connection_id, u16 code, ByteString const& reason) +{ + if (auto connection = m_websockets.get(connection_id).value_or({}); connection && connection->ready_state() == WebSocket::ReadyState::Open) + connection->close(code, reason); +} + +Messages::RequestServer::WebsocketSetCertificateResponse ConnectionFromClient::websocket_set_certificate(i32 connection_id, ByteString const&, ByteString const&) +{ + auto success = false; + if (auto connection = m_websockets.get(connection_id).value_or({}); connection) { + // NO OP here + // connection->set_certificate(certificate, key); + success = true; + } + return success; +} + } diff --git a/Userland/Services/RequestServer/ConnectionFromClient.h b/Userland/Services/RequestServer/ConnectionFromClient.h index ead2159e4f..0e6314d309 100644 --- a/Userland/Services/RequestServer/ConnectionFromClient.h +++ b/Userland/Services/RequestServer/ConnectionFromClient.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,15 @@ private: virtual Messages::RequestServer::SetCertificateResponse set_certificate(i32, ByteString const&, ByteString const&) override; virtual void ensure_connection(URL const& url, ::RequestServer::CacheLevel const& cache_level) override; + virtual Messages::RequestServer::WebsocketConnectResponse websocket_connect(URL const&, ByteString const&, Vector const&, Vector const&, HashMap const&) override; + virtual Messages::RequestServer::WebsocketReadyStateResponse websocket_ready_state(i32) override; + virtual Messages::RequestServer::WebsocketSubprotocolInUseResponse websocket_subprotocol_in_use(i32) override; + virtual void websocket_send(i32, bool, ByteBuffer const&) override; + virtual void websocket_close(i32, u16, ByteString const&) override; + virtual Messages::RequestServer::WebsocketSetCertificateResponse websocket_set_certificate(i32, ByteString const&, ByteString const&) override; + HashMap> m_requests; + HashMap> m_websockets; }; } diff --git a/Userland/Services/RequestServer/RequestClient.ipc b/Userland/Services/RequestServer/RequestClient.ipc index 408d5295be..de7f08e15e 100644 --- a/Userland/Services/RequestServer/RequestClient.ipc +++ b/Userland/Services/RequestServer/RequestClient.ipc @@ -7,6 +7,14 @@ endpoint RequestClient request_finished(i32 request_id, bool success, u64 total_size) =| headers_became_available(i32 request_id, HashMap response_headers, Optional status_code) =| + // Websocket API + // FIXME: See if this can be merged with the regular APIs + websocket_connected(i32 connection_id) =| + websocket_received(i32 connection_id, bool is_text, ByteBuffer data) =| + websocket_errored(i32 connection_id, i32 message) =| + websocket_closed(i32 connection_id, u16 code, ByteString reason, bool clean) =| + websocket_certificate_requested(i32 request_id) =| + // Certificate requests certificate_requested(i32 request_id) =| } diff --git a/Userland/Services/RequestServer/RequestServer.ipc b/Userland/Services/RequestServer/RequestServer.ipc index 01225f8041..2be236f11f 100644 --- a/Userland/Services/RequestServer/RequestServer.ipc +++ b/Userland/Services/RequestServer/RequestServer.ipc @@ -11,4 +11,12 @@ endpoint RequestServer set_certificate(i32 request_id, ByteString certificate, ByteString key) => (bool success) ensure_connection(URL url, ::RequestServer::CacheLevel cache_level) =| + + // Websocket Connection API + websocket_connect(URL url, ByteString origin, Vector protocols, Vector extensions, HashMap additional_request_headers) => (i32 connection_id) + websocket_ready_state(i32 connection_id) => (u32 ready_state) + websocket_subprotocol_in_use(i32 connection_id) => (ByteString subprotocol_in_use) + websocket_send(i32 connection_id, bool is_text, ByteBuffer data) =| + websocket_close(i32 connection_id, u16 code, ByteString reason) =| + websocket_set_certificate(i32 request_id, ByteString certificate, ByteString key) => (bool success) } diff --git a/Userland/Services/WebContent/CMakeLists.txt b/Userland/Services/WebContent/CMakeLists.txt index cd6637a970..ca4f95f732 100644 --- a/Userland/Services/WebContent/CMakeLists.txt +++ b/Userland/Services/WebContent/CMakeLists.txt @@ -3,7 +3,7 @@ include(accelerated_graphics) serenity_component( WebContent TARGETS WebContent - DEPENDS ImageDecoder RequestServer WebSocket + DEPENDS ImageDecoder RequestServer ) compile_ipc(WebContentServer.ipc WebContentServerEndpoint.h) diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp index 6f793174f2..b7c69eeecb 100644 --- a/Userland/Services/WebContent/main.cpp +++ b/Userland/Services/WebContent/main.cpp @@ -40,7 +40,6 @@ ErrorOr serenity_main(Main::Arguments) TRY(Core::System::unveil("/tmp/session/%sid/portal/audio", "rw")); TRY(Core::System::unveil("/tmp/session/%sid/portal/request", "rw")); TRY(Core::System::unveil("/tmp/session/%sid/portal/image", "rw")); - TRY(Core::System::unveil("/tmp/session/%sid/portal/websocket", "rw")); TRY(Core::System::unveil(nullptr, nullptr)); Web::Platform::EventLoopPlugin::install(*new Web::Platform::EventLoopPluginSerenity); @@ -51,7 +50,6 @@ ErrorOr serenity_main(Main::Arguments) return Web::Platform::AudioCodecPluginAgnostic::create(move(loader)); }); - Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create())); Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create())); TRY(Web::Bindings::initialize_main_thread_vm()); diff --git a/Userland/Services/WebSocket/CMakeLists.txt b/Userland/Services/WebSocket/CMakeLists.txt deleted file mode 100644 index b023234ae0..0000000000 --- a/Userland/Services/WebSocket/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -serenity_component( - WebSocket - TARGETS WebSocketServer -) - -compile_ipc(WebSocketServer.ipc WebSocketServerEndpoint.h) -compile_ipc(WebSocketClient.ipc WebSocketClientEndpoint.h) - -set(SOURCES - ConnectionFromClient.cpp - main.cpp -) - -set(GENERATED_SOURCES - WebSocketClientEndpoint.h - WebSocketServerEndpoint.h -) - -# Note: We use a target name of WebSocketServer here to deconflict with the -# Lagom namespaced target name for LibWebSocket, Lagom::WebSocket. -# The server binary name is still WebSocket. -serenity_bin(WebSocketServer) -set_target_properties(WebSocketServer PROPERTIES OUTPUT_NAME WebSocket) -target_link_libraries(WebSocketServer PRIVATE LibCore LibIPC LibWebSocket LibMain LibTLS) diff --git a/Userland/Services/WebSocket/ConnectionFromClient.cpp b/Userland/Services/WebSocket/ConnectionFromClient.cpp deleted file mode 100644 index 21135c6b12..0000000000 --- a/Userland/Services/WebSocket/ConnectionFromClient.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include - -namespace WebSocket { - -static HashMap> s_connections; - -ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr socket) - : IPC::ConnectionFromClient(*this, move(socket), 1) -{ - s_connections.set(1, *this); -} - -void ConnectionFromClient::die() -{ - s_connections.remove(client_id()); - if (s_connections.is_empty()) - Core::EventLoop::current().quit(0); -} - -Messages::WebSocketServer::ConnectResponse ConnectionFromClient::connect(URL const& url, ByteString const& origin, - Vector const& protocols, Vector const& extensions, HashMap const& additional_request_headers) -{ - if (!url.is_valid()) { - dbgln("WebSocket::Connect: Invalid URL requested: '{}'", url); - return -1; - } - - ConnectionInfo connection_info(url); - connection_info.set_origin(origin); - connection_info.set_protocols(protocols); - connection_info.set_extensions(extensions); - - Vector headers; - for (auto const& header : additional_request_headers) { - headers.append({ header.key, header.value }); - } - connection_info.set_headers(headers); - - VERIFY(m_connection_ids < NumericLimits::max()); - auto id = ++m_connection_ids; - auto connection = WebSocket::create(move(connection_info)); - connection->on_open = [this, id]() { - did_connect(id); - }; - connection->on_message = [this, id](auto message) { - did_receive_message(id, move(message)); - }; - connection->on_error = [this, id](auto message) { - did_error(id, (i32)message); - }; - connection->on_close = [this, id](u16 code, ByteString reason, bool was_clean) { - did_close(id, code, move(reason), was_clean); - }; - - connection->start(); - m_connections.set(id, move(connection)); - return id; -} - -Messages::WebSocketServer::ReadyStateResponse ConnectionFromClient::ready_state(i32 connection_id) -{ - RefPtr connection = m_connections.get(connection_id).value_or({}); - if (connection) { - return (u32)connection->ready_state(); - } - return (u32)ReadyState::Closed; -} - -Messages::WebSocketServer::SubprotocolInUseResponse ConnectionFromClient::subprotocol_in_use(i32 connection_id) -{ - RefPtr connection = m_connections.get(connection_id).value_or({}); - if (connection) { - return connection->subprotocol_in_use(); - } - return ByteString::empty(); -} - -void ConnectionFromClient::send(i32 connection_id, bool is_text, ByteBuffer const& data) -{ - RefPtr connection = m_connections.get(connection_id).value_or({}); - if (connection && connection->ready_state() == ReadyState::Open) { - Message websocket_message(data, is_text); - connection->send(websocket_message); - } -} - -void ConnectionFromClient::close(i32 connection_id, u16 code, ByteString const& reason) -{ - RefPtr connection = m_connections.get(connection_id).value_or({}); - if (connection && connection->ready_state() == ReadyState::Open) - connection->close(code, reason); -} - -Messages::WebSocketServer::SetCertificateResponse ConnectionFromClient::set_certificate(i32 connection_id, - [[maybe_unused]] ByteString const& certificate, [[maybe_unused]] ByteString const& key) -{ - RefPtr connection = m_connections.get(connection_id).value_or({}); - bool success = false; - if (connection) { - // NO OP here - // connection->set_certificate(certificate, key); - success = true; - } - return success; -} - -void ConnectionFromClient::did_connect(i32 connection_id) -{ - async_connected(connection_id); -} - -void ConnectionFromClient::did_receive_message(i32 connection_id, Message message) -{ - async_received(connection_id, message.is_text(), message.data()); -} - -void ConnectionFromClient::did_error(i32 connection_id, i32 message) -{ - async_errored(connection_id, message); -} - -void ConnectionFromClient::did_close(i32 connection_id, u16 code, ByteString reason, bool was_clean) -{ - async_closed(connection_id, code, reason, was_clean); - deferred_invoke([this, connection_id] { - m_connections.remove(connection_id); - }); -} - -void ConnectionFromClient::did_request_certificates(i32 connection_id) -{ - async_certificate_requested(connection_id); -} - -} diff --git a/Userland/Services/WebSocket/ConnectionFromClient.h b/Userland/Services/WebSocket/ConnectionFromClient.h deleted file mode 100644 index e8a8dd3c32..0000000000 --- a/Userland/Services/WebSocket/ConnectionFromClient.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace WebSocket { - -class ConnectionFromClient final - : public IPC::ConnectionFromClient { - C_OBJECT(ConnectionFromClient); - -public: - ~ConnectionFromClient() override = default; - - virtual void die() override; - -private: - explicit ConnectionFromClient(NonnullOwnPtr); - - virtual Messages::WebSocketServer::ConnectResponse connect(URL const&, ByteString const&, Vector const&, Vector const&, HashMap const&) override; - virtual Messages::WebSocketServer::ReadyStateResponse ready_state(i32) override; - virtual Messages::WebSocketServer::SubprotocolInUseResponse subprotocol_in_use(i32) override; - virtual void send(i32, bool, ByteBuffer const&) override; - virtual void close(i32, u16, ByteString const&) override; - virtual Messages::WebSocketServer::SetCertificateResponse set_certificate(i32, ByteString const&, ByteString const&) override; - - void did_connect(i32); - void did_receive_message(i32, Message); - void did_error(i32, i32 message); - void did_close(i32, u16 code, ByteString reason, bool was_clean); - void did_request_certificates(i32); - - i32 m_connection_ids { 0 }; - HashMap> m_connections; -}; - -} diff --git a/Userland/Services/WebSocket/WebSocketClient.ipc b/Userland/Services/WebSocket/WebSocketClient.ipc deleted file mode 100644 index 77a2929e24..0000000000 --- a/Userland/Services/WebSocket/WebSocketClient.ipc +++ /dev/null @@ -1,13 +0,0 @@ -#include - -endpoint WebSocketClient -{ - // Connection API - connected(i32 connection_id) =| - received(i32 connection_id, bool is_text, ByteBuffer data) =| - errored(i32 connection_id, i32 message) =| - closed(i32 connection_id, u16 code, ByteString reason, bool clean) =| - - // Certificate requests - certificate_requested(i32 connection_id) =| -} diff --git a/Userland/Services/WebSocket/WebSocketServer.ipc b/Userland/Services/WebSocket/WebSocketServer.ipc deleted file mode 100644 index 66d4d6d9a0..0000000000 --- a/Userland/Services/WebSocket/WebSocketServer.ipc +++ /dev/null @@ -1,13 +0,0 @@ -#include - -endpoint WebSocketServer -{ - // Connection API - connect(URL url, ByteString origin, Vector protocols, Vector extensions, HashMap additional_request_headers) => (i32 connection_id) - ready_state(i32 connection_id) => (u32 ready_state) - subprotocol_in_use(i32 connection_id) => (ByteString subprotocol_in_use) - send(i32 connection_id, bool is_text, ByteBuffer data) =| - close(i32 connection_id, u16 code, ByteString reason) =| - - set_certificate(i32 connection_id, ByteString certificate, ByteString key) => (bool success) -} diff --git a/Userland/Services/WebSocket/main.cpp b/Userland/Services/WebSocket/main.cpp deleted file mode 100644 index 40c9ff5df2..0000000000 --- a/Userland/Services/WebSocket/main.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021, Dex♪ - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -ErrorOr serenity_main(Main::Arguments) -{ - TRY(Core::System::pledge("stdio inet unix rpath sendfd recvfd")); - - // Ensure the certificates are read out here. - // FIXME: Allow specifying extra certificates on the command line, or in other configuration. - [[maybe_unused]] auto& certs = DefaultRootCACertificates::the(); - - Core::EventLoop event_loop; - // FIXME: Establish a connection to LookupServer and then drop "unix"? - TRY(Core::System::unveil("/tmp/portal/lookup", "rw")); - TRY(Core::System::unveil("/etc/timezone", "r")); - TRY(Core::System::unveil(nullptr, nullptr)); - - auto client = TRY(IPC::take_over_accepted_client_from_system_server()); - - return event_loop.exec(); -} diff --git a/Userland/Services/WebWorker/main.cpp b/Userland/Services/WebWorker/main.cpp index 655fd3929a..14dcc60980 100644 --- a/Userland/Services/WebWorker/main.cpp +++ b/Userland/Services/WebWorker/main.cpp @@ -30,13 +30,11 @@ ErrorOr serenity_main(Main::Arguments) TRY(Core::System::unveil("/etc/timezone", "r")); TRY(Core::System::unveil("/tmp/session/%sid/portal/request", "rw")); TRY(Core::System::unveil("/tmp/session/%sid/portal/image", "rw")); - TRY(Core::System::unveil("/tmp/session/%sid/portal/websocket", "rw")); TRY(Core::System::unveil(nullptr, nullptr)); Web::Platform::EventLoopPlugin::install(*new Web::Platform::EventLoopPluginSerenity); Web::Platform::FontPlugin::install(*new Web::Platform::FontPluginSerenity); - Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create())); Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create())); TRY(Web::Bindings::initialize_main_thread_vm()); diff --git a/Userland/Utilities/telws.cpp b/Userland/Utilities/telws.cpp index 22f0fd55b4..398c01c993 100644 --- a/Userland/Utilities/telws.cpp +++ b/Userland/Utilities/telws.cpp @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include ErrorOr serenity_main(Main::Arguments arguments) { @@ -38,7 +38,7 @@ ErrorOr serenity_main(Main::Arguments arguments) Core::EventLoop loop; - auto maybe_websocket_client = Protocol::WebSocketClient::try_create(); + auto maybe_websocket_client = Protocol::RequestClient::try_create(); if (maybe_websocket_client.is_error()) { warnln("Failed to connect to the websocket server: {}\n", maybe_websocket_client.error()); return maybe_websocket_client.release_error(); @@ -47,7 +47,7 @@ ErrorOr serenity_main(Main::Arguments arguments) RefPtr editor = Line::Editor::construct(); bool should_quit = false; - auto socket = websocket_client->connect(url, origin); + auto socket = websocket_client->websocket_connect(url, origin); if (!socket) { warnln("Failed to start socket for '{}'\n", url); return 1;