mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-18 18:00:31 +00:00
A MessagePort can be transferred while it already has local queued state such as incoming messages drained from its transport, outgoing messages posted before a transport exists, and a pending shutdown to apply once the port is enabled. Serialize and restore that state as part of transfer so it moves with the port instead of being left behind on the old transport. Also mark transports that are being transferred so shutdown of the old endpoint during handoff is not reported as peer EOF. That shutdown is part of moving the transport to the new owner, not peer disconnected. Co-Authored-By: Alexander Kalenik <kalenik.aliaksandr@gmail.com>
107 lines
3.7 KiB
C++
107 lines
3.7 KiB
C++
/*
|
|
* Copyright (c) 2021, Andreas Kling <andreas@ladybird.org>
|
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
|
* Copyright (c) 2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/RefCounted.h>
|
|
#include <AK/Weakable.h>
|
|
#include <LibCore/Socket.h>
|
|
#include <LibIPC/File.h>
|
|
#include <LibIPC/Transport.h>
|
|
#include <LibWeb/Bindings/Transferable.h>
|
|
#include <LibWeb/DOM/EventTarget.h>
|
|
#include <LibWeb/Export.h>
|
|
#include <LibWeb/Forward.h>
|
|
|
|
namespace Web::HTML {
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#message-ports
|
|
class WEB_API MessagePort final
|
|
: public DOM::EventTarget
|
|
, public Bindings::Transferable {
|
|
WEB_PLATFORM_OBJECT(MessagePort, DOM::EventTarget);
|
|
GC_DECLARE_ALLOCATOR(MessagePort);
|
|
|
|
public:
|
|
static constexpr bool OVERRIDES_FINALIZE = true;
|
|
|
|
[[nodiscard]] static GC::Ref<MessagePort> create(JS::Realm&);
|
|
|
|
static void for_each_message_port(Function<void(MessagePort&)>);
|
|
|
|
virtual ~MessagePort() override;
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#entangle
|
|
void entangle_with(MessagePort&);
|
|
|
|
void disentangle();
|
|
|
|
GC::Ptr<MessagePort> entangled_port() { return m_remote_port; }
|
|
GC::Ptr<MessagePort const> entangled_port() const { return m_remote_port; }
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage
|
|
WebIDL::ExceptionOr<void> post_message(JS::Value message, Vector<GC::Root<JS::Object>> const& transfer);
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#dom-messageport-postmessage-options
|
|
WebIDL::ExceptionOr<void> post_message(JS::Value message, StructuredSerializeOptions const& options);
|
|
|
|
void enable();
|
|
void start();
|
|
|
|
void close();
|
|
|
|
void set_onmessageerror(GC::Ptr<WebIDL::CallbackType>);
|
|
GC::Ptr<WebIDL::CallbackType> onmessageerror();
|
|
|
|
void set_onmessage(GC::Ptr<WebIDL::CallbackType>);
|
|
GC::Ptr<WebIDL::CallbackType> onmessage();
|
|
|
|
// ^Transferable
|
|
virtual WebIDL::ExceptionOr<void> transfer_steps(HTML::TransferDataEncoder&) override;
|
|
virtual WebIDL::ExceptionOr<void> transfer_receiving_steps(HTML::TransferDataDecoder&) override;
|
|
virtual HTML::TransferType primary_interface() const override { return HTML::TransferType::MessagePort; }
|
|
|
|
void set_worker_event_target(GC::Ref<DOM::EventTarget>);
|
|
|
|
WebIDL::ExceptionOr<void> message_port_post_message_steps(GC::Ptr<MessagePort> target_port, JS::Value message, StructuredSerializeOptions const& options);
|
|
|
|
private:
|
|
explicit MessagePort(JS::Realm&);
|
|
|
|
virtual void initialize(JS::Realm&) override;
|
|
virtual void finalize() override;
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
|
|
|
bool is_entangled() const;
|
|
|
|
void dispatch_pending_messages();
|
|
void flush_pending_outgoing_messages();
|
|
void queue_message_task(SerializedTransferRecord&&);
|
|
void drain_transport();
|
|
void post_message_task_steps(SerializedTransferRecord&);
|
|
void post_port_message(SerializedTransferRecord const&);
|
|
ErrorOr<void> send_message_on_transport(SerializedTransferRecord const&);
|
|
void read_from_transport();
|
|
|
|
// The HTML spec implies(!) that this is MessagePort.[[RemotePort]]
|
|
GC::Ptr<MessagePort> m_remote_port;
|
|
|
|
// https://html.spec.whatwg.org/multipage/web-messaging.html#has-been-shipped
|
|
bool m_has_been_shipped { false };
|
|
|
|
OwnPtr<IPC::Transport> m_transport;
|
|
|
|
GC::Ptr<DOM::EventTarget> m_worker_event_target;
|
|
|
|
Vector<SerializedTransferRecord> m_pending_incoming_messages;
|
|
Vector<SerializedTransferRecord> m_pending_outgoing_messages;
|
|
bool m_should_shutdown_on_enable { false };
|
|
bool m_enabled { false };
|
|
};
|
|
|
|
}
|