Coverage Report

Created: 2026-02-14 08:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibWeb/HTML/MessagePort.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#pragma once
9
10
#include <AK/RefCounted.h>
11
#include <AK/Weakable.h>
12
#include <LibCore/Socket.h>
13
#include <LibIPC/File.h>
14
#include <LibWeb/Bindings/Transferable.h>
15
#include <LibWeb/DOM/EventTarget.h>
16
#include <LibWeb/Forward.h>
17
18
namespace Web::HTML {
19
20
#define ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(E) \
21
    E(onmessage, HTML::EventNames::message)      \
22
    E(onmessageerror, HTML::EventNames::messageerror)
23
24
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
25
class MessagePort final : public DOM::EventTarget
26
    , public Bindings::Transferable {
27
    WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget);
28
    JS_DECLARE_ALLOCATOR(MessagePort);
29
30
public:
31
    [[nodiscard]] static JS::NonnullGCPtr<MessagePort> create(JS::Realm&);
32
33
    static void for_each_message_port(Function<void(MessagePort&)>);
34
35
    virtual ~MessagePort() override;
36
37
    // https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
38
    void entangle_with(MessagePort&);
39
40
    void disentangle();
41
42
    // https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
43
    WebIDL::ExceptionOr<void> post_message(JS::Value message, Vector<JS::Handle<JS::Object>> const& transfer);
44
45
    // https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage-options
46
    WebIDL::ExceptionOr<void> post_message(JS::Value message, StructuredSerializeOptions const& options);
47
48
    void start();
49
50
    void close();
51
52
#undef __ENUMERATE
53
#define __ENUMERATE(attribute_name, event_name)       \
54
    void set_##attribute_name(WebIDL::CallbackType*); \
55
    WebIDL::CallbackType* attribute_name();
56
    ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
57
#undef __ENUMERATE
58
59
    // ^Transferable
60
    virtual WebIDL::ExceptionOr<void> transfer_steps(HTML::TransferDataHolder&) override;
61
    virtual WebIDL::ExceptionOr<void> transfer_receiving_steps(HTML::TransferDataHolder&) override;
62
0
    virtual HTML::TransferType primary_interface() const override { return HTML::TransferType::MessagePort; }
63
64
    void set_worker_event_target(JS::NonnullGCPtr<DOM::EventTarget>);
65
66
private:
67
    explicit MessagePort(JS::Realm&);
68
69
    virtual void initialize(JS::Realm&) override;
70
    virtual void visit_edges(Cell::Visitor&) override;
71
72
0
    bool is_entangled() const { return static_cast<bool>(m_socket); }
73
74
    WebIDL::ExceptionOr<void> message_port_post_message_steps(JS::GCPtr<MessagePort> target_port, JS::Value message, StructuredSerializeOptions const& options);
75
    void post_message_task_steps(SerializedTransferRecord&);
76
    void post_port_message(SerializedTransferRecord);
77
    ErrorOr<void> send_message_on_socket(SerializedTransferRecord const&);
78
    void read_from_socket();
79
80
    enum class ParseDecision {
81
        NotEnoughData,
82
        ParseNextMessage,
83
    };
84
    ErrorOr<ParseDecision> parse_message();
85
86
    // The HTML spec implies(!) that this is MessagePort.[[RemotePort]]
87
    JS::GCPtr<MessagePort> m_remote_port;
88
89
    // https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
90
    bool m_has_been_shipped { false };
91
92
    OwnPtr<Core::LocalSocket> m_socket;
93
94
    enum class SocketState : u8 {
95
        Header,
96
        Data,
97
        Error,
98
    } m_socket_state { SocketState::Header };
99
    size_t m_socket_incoming_message_size { 0 };
100
    Queue<IPC::File> m_unprocessed_fds;
101
    Vector<u8> m_buffered_data;
102
103
    JS::GCPtr<DOM::EventTarget> m_worker_event_target;
104
};
105
106
}