Deprecate ActiveDOMObject::canSuspendForDocumentSuspension()
[WebKit-https.git] / Source / WebCore / dom / MessagePort.h
index 6318aa4..a136a56 100644 (file)
  *
  */
 
-#ifndef MessagePort_h
-#define MessagePort_h
+#pragma once
 
-#include "EventListener.h"
+#include "ActiveDOMObject.h"
 #include "EventTarget.h"
+#include "ExceptionOr.h"
+#include "GenericEventQueue.h"
 #include "MessagePortChannel.h"
-#include <memory>
-#include <wtf/Forward.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
+#include "MessagePortIdentifier.h"
+#include "MessageWithMessagePorts.h"
+#include <wtf/WeakPtr.h>
+
+namespace JSC {
+class CallFrame;
+class JSObject;
+class JSValue;
+using ExecState = CallFrame;
+}
 
 namespace WebCore {
 
-    class Event;
-    class Frame;
-    class MessagePort;
-    class ScriptExecutionContext;
+class Frame;
 
-    // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
-    typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray;
+class MessagePort final : public ActiveDOMObject, public EventTargetWithInlineData, public CanMakeWeakPtr<MessagePort, WeakPtrFactoryInitialization::Eager> {
+    WTF_MAKE_NONCOPYABLE(MessagePort);
+    WTF_MAKE_ISO_ALLOCATED(MessagePort);
+public:
+    static Ref<MessagePort> create(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
+    virtual ~MessagePort();
 
-    class MessagePort final : public RefCounted<MessagePort>, public EventTargetWithInlineData {
-    public:
-        static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(*new MessagePort(scriptExecutionContext)); }
-        virtual ~MessagePort();
+    ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&);
 
-        void postMessage(RefPtr<SerializedScriptValue>&& message, const MessagePortArray*, ExceptionCode&);
-        // Needed for Objective-C bindings (see bug 28774).
-        void postMessage(RefPtr<SerializedScriptValue>&& message, MessagePort*, ExceptionCode&);
+    void start();
+    void close();
+    void entangle();
 
-        void start();
-        void close();
+    // Returns nullptr if the passed-in vector is empty.
+    static ExceptionOr<TransferredMessagePortArray> disentanglePorts(Vector<RefPtr<MessagePort>>&&);
+    static Vector<RefPtr<MessagePort>> entanglePorts(ScriptExecutionContext&, TransferredMessagePortArray&&);
 
-        void entangle(std::unique_ptr<MessagePortChannel>);
-        std::unique_ptr<MessagePortChannel> disentangle();
+    WEBCORE_EXPORT static bool isExistingMessagePortLocallyReachable(const MessagePortIdentifier&);
+    WEBCORE_EXPORT static void notifyMessageAvailable(const MessagePortIdentifier&);
 
-        // Returns 0 if there is an exception, or if the passed-in array is 0/empty.
-        static std::unique_ptr<MessagePortChannelArray> disentanglePorts(const MessagePortArray*, ExceptionCode&);
+    WEBCORE_EXPORT void messageAvailable();
+    bool started() const { return m_started; }
+    bool closed() const { return m_closed; }
 
-        // Returns 0 if the passed array is 0/empty.
-        static std::unique_ptr<MessagePortArray> entanglePorts(ScriptExecutionContext&, std::unique_ptr<MessagePortChannelArray>);
+    void dispatchMessages();
 
-        void messageAvailable();
-        bool started() const { return m_started; }
+    // Returns null if there is no entangled port, or if the entangled port is run by a different thread.
+    // This is used solely to enable a GC optimization. Some platforms may not be able to determine ownership
+    // of the remote port (since it may live cross-process) - those platforms may always return null.
+    MessagePort* locallyEntangledPort() const;
 
-        void contextDestroyed();
+    const MessagePortIdentifier& identifier() const { return m_identifier; }
+    const MessagePortIdentifier& remoteIdentifier() const { return m_remoteIdentifier; }
 
-        EventTargetInterface eventTargetInterface() const override { return MessagePortEventTargetInterfaceType; }
-        ScriptExecutionContext* scriptExecutionContext() const override { return m_scriptExecutionContext; }
+    WEBCORE_EXPORT void ref() const;
+    WEBCORE_EXPORT void deref() const;
 
-        void dispatchMessages();
+    // ActiveDOMObject
+    const char* activeDOMObjectName() const final;
+    void contextDestroyed() final;
+    void stop() final { close(); }
+    bool hasPendingActivity() const final;
 
-        using RefCounted<MessagePort>::ref;
-        using RefCounted<MessagePort>::deref;
+    WEBCORE_EXPORT bool isLocallyReachable() const;
 
-        bool hasPendingActivity();
+    // EventTargetWithInlineData.
+    EventTargetInterface eventTargetInterface() const final { return MessagePortEventTargetInterfaceType; }
+    ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
+    void refEventTarget() final { ref(); }
+    void derefEventTarget() final { deref(); }
 
-        // Returns null if there is no entangled port, or if the entangled port is run by a different thread.
-        // This is used solely to enable a GC optimization. Some platforms may not be able to determine ownership
-        // of the remote port (since it may live cross-process) - those platforms may always return null.
-        MessagePort* locallyEntangledPort();
+private:
+    explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
 
-        // A port starts out its life entangled, and remains entangled until it is closed or is cloned.
-        bool isEntangled() { return !m_closed && !isNeutered(); }
+    bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
+    bool removeEventListener(const AtomString& eventType, EventListener&, const ListenerOptions&) final;
 
-        // A port gets neutered when it is transferred to a new owner via postMessage().
-        bool isNeutered() { return !m_entangledChannel; }
+    void disentangle();
 
-        bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
+    void registerLocalActivity();
 
-    private:
-        explicit MessagePort(ScriptExecutionContext&);
+    // A port starts out its life entangled, and remains entangled until it is closed or is cloned.
+    bool isEntangled() const { return !m_closed && m_entangled; }
 
-        void refEventTarget() override { ref(); }
-        void derefEventTarget() override { deref(); }
-        bool isMessagePort() const override { return true; }
+    void updateActivity(MessagePortChannelProvider::HasActivity);
 
-        std::unique_ptr<MessagePortChannel> m_entangledChannel;
+    bool m_started { false };
+    bool m_closed { false };
+    bool m_entangled { true };
 
-        bool m_started;
-        bool m_closed;
+    // Flags to manage querying the remote port for GC purposes
+    mutable bool m_mightBeEligibleForGC { false };
+    mutable bool m_hasHadLocalActivitySinceLastCheck { false };
+    mutable bool m_isRemoteEligibleForGC { false };
+    mutable bool m_isAskingRemoteAboutGC { false };
+    bool m_hasMessageEventListener { false };
 
-        ScriptExecutionContext* m_scriptExecutionContext;
-    };
+    MessagePortIdentifier m_identifier;
+    MessagePortIdentifier m_remoteIdentifier;
 
-} // namespace WebCore
+    mutable std::atomic<unsigned> m_refCount { 1 };
+    UniqueRef<GenericEventQueue> m_eventQueue;
+};
 
-#endif // MessagePort_h
+} // namespace WebCore