Coverage Report

Created: 2025-11-16 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibWeb/WebSockets/WebSocket.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2021-2022, Dex♪ <dexes.ttp@gmail.com>
3
 * Copyright (c) 2023, Kenneth Myhra <kennethmyhra@serenityos.org>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#pragma once
9
10
#include <AK/ByteBuffer.h>
11
#include <LibCore/EventReceiver.h>
12
#include <LibURL/URL.h>
13
#include <LibWeb/Bindings/PlatformObject.h>
14
#include <LibWeb/DOM/EventTarget.h>
15
#include <LibWeb/Forward.h>
16
#include <LibWeb/HTML/Window.h>
17
#include <LibWeb/WebIDL/ExceptionOr.h>
18
19
#define ENUMERATE_WEBSOCKET_EVENT_HANDLERS(E) \
20
    E(onerror, HTML::EventNames::error)       \
21
    E(onclose, HTML::EventNames::close)       \
22
    E(onopen, HTML::EventNames::open)         \
23
    E(onmessage, HTML::EventNames::message)
24
25
namespace Web::WebSockets {
26
27
class WebSocketClientSocket;
28
class WebSocketClientManager;
29
30
class WebSocket final : public DOM::EventTarget {
31
    WEB_PLATFORM_OBJECT(WebSocket, DOM::EventTarget);
32
    JS_DECLARE_ALLOCATOR(WebSocket);
33
34
public:
35
    enum class ReadyState : u16 {
36
        Connecting = 0,
37
        Open = 1,
38
        Closing = 2,
39
        Closed = 3,
40
    };
41
42
    static WebIDL::ExceptionOr<JS::NonnullGCPtr<WebSocket>> construct_impl(JS::Realm&, String const& url, Optional<Variant<String, Vector<String>>> const& protocols);
43
44
    virtual ~WebSocket() override;
45
46
0
    WebIDL::ExceptionOr<String> url() const { return TRY_OR_THROW_OOM(vm(), m_url.to_string()); }
47
0
    void set_url(URL::URL url) { m_url = move(url); }
48
49
#undef __ENUMERATE
50
#define __ENUMERATE(attribute_name, event_name)       \
51
    void set_##attribute_name(WebIDL::CallbackType*); \
52
    WebIDL::CallbackType* attribute_name();
53
    ENUMERATE_WEBSOCKET_EVENT_HANDLERS(__ENUMERATE)
54
#undef __ENUMERATE
55
56
    ReadyState ready_state() const;
57
    String extensions() const;
58
    WebIDL::ExceptionOr<String> protocol() const;
59
60
0
    String const& binary_type() { return m_binary_type; }
61
0
    void set_binary_type(String const& type) { m_binary_type = type; }
62
63
    WebIDL::ExceptionOr<void> close(Optional<u16> code, Optional<String> reason);
64
    WebIDL::ExceptionOr<void> send(Variant<JS::Handle<WebIDL::BufferSource>, JS::Handle<FileAPI::Blob>, String> const& data);
65
66
private:
67
    void on_open();
68
    void on_message(ByteBuffer message, bool is_text);
69
    void on_error();
70
    void on_close(u16 code, String reason, bool was_clean);
71
72
    WebSocket(JS::Realm&);
73
74
    virtual void initialize(JS::Realm&) override;
75
76
    ErrorOr<void> establish_web_socket_connection(URL::URL& url_record, Vector<String>& protocols, HTML::EnvironmentSettingsObject& client);
77
78
    URL::URL m_url;
79
    String m_binary_type { "blob"_string };
80
    RefPtr<WebSocketClientSocket> m_websocket;
81
};
82
83
class WebSocketClientSocket : public RefCounted<WebSocketClientSocket> {
84
public:
85
    virtual ~WebSocketClientSocket();
86
87
    struct CertificateAndKey {
88
        ByteString certificate;
89
        ByteString key;
90
    };
91
92
    struct Message {
93
        ByteBuffer data;
94
        bool is_text { false };
95
    };
96
97
    enum class Error {
98
        CouldNotEstablishConnection,
99
        ConnectionUpgradeFailed,
100
        ServerClosedSocket,
101
    };
102
103
    virtual Web::WebSockets::WebSocket::ReadyState ready_state() = 0;
104
    virtual ByteString subprotocol_in_use() = 0;
105
106
    virtual void send(ByteBuffer binary_or_text_message, bool is_text) = 0;
107
    virtual void send(StringView text_message) = 0;
108
    virtual void close(u16 code = 1005, ByteString reason = {}) = 0;
109
110
    Function<void()> on_open;
111
    Function<void(Message)> on_message;
112
    Function<void(Error)> on_error;
113
    Function<void(u16 code, ByteString reason, bool was_clean)> on_close;
114
    Function<CertificateAndKey()> on_certificate_requested;
115
116
protected:
117
    explicit WebSocketClientSocket() = default;
118
};
119
120
}