Deprecate ActiveDOMObject::canSuspendForDocumentSuspension()
[WebKit-https.git] / Source / WebCore / dom / MessagePort.h
index 1287834..a136a56 100644 (file)
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  *
  */
 
-#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 <wtf/Forward.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/text/AtomicStringHash.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 : public RefCounted<MessagePort>, public EventTarget {
-    public:
-        static PassRefPtr<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); }
-        ~MessagePort();
+    ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&);
 
-        void postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode&);
-        void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionCode&);
-        // FIXME: remove this when we update the ObjC bindings (bug #28774).
-        void postMessage(PassRefPtr<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(PassOwnPtr<MessagePortChannel>);
-        PassOwnPtr<MessagePortChannel> disentangle(ExceptionCode&);
+    WEBCORE_EXPORT static bool isExistingMessagePortLocallyReachable(const MessagePortIdentifier&);
+    WEBCORE_EXPORT static void notifyMessageAvailable(const MessagePortIdentifier&);
 
-        // Disentangle an array of ports, returning the entangled channels.
-        // Per section 8.3.3 of the HTML5 spec, generates an INVALID_STATE_ERR exception if any of the passed ports are null or not entangled.
-        // Returns 0 if there is an exception, or if the passed-in array is 0/empty.
-        static PassOwnPtr<MessagePortChannelArray> disentanglePorts(const MessagePortArray*, ExceptionCode&);
+    WEBCORE_EXPORT void messageAvailable();
+    bool started() const { return m_started; }
+    bool closed() const { return m_closed; }
 
-        // Entangles an array of channels, returning an array of MessagePorts in matching order.
-        // Returns 0 if the passed array is 0/empty.
-        static PassOwnPtr<MessagePortArray> entanglePorts(ScriptExecutionContext&, PassOwnPtr<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; }
 
-        virtual ScriptExecutionContext* scriptExecutionContext() const;
+    WEBCORE_EXPORT void ref() const;
+    WEBCORE_EXPORT void deref() const;
 
-        virtual MessagePort* toMessagePort() { return this; }
+    // ActiveDOMObject
+    const char* activeDOMObjectName() const final;
+    void contextDestroyed() final;
+    void stop() final { close(); }
+    bool hasPendingActivity() const final;
 
-        void dispatchMessages();
+    WEBCORE_EXPORT bool isLocallyReachable() const;
 
-        using RefCounted<MessagePort>::ref;
-        using RefCounted<MessagePort>::deref;
+    // EventTargetWithInlineData.
+    EventTargetInterface eventTargetInterface() const final { return MessagePortEventTargetInterfaceType; }
+    ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
+    void refEventTarget() final { ref(); }
+    void derefEventTarget() final { deref(); }
 
-        bool hasPendingActivity();
+private:
+    explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
 
-        void setOnmessage(PassRefPtr<EventListener> listener)
-        {
-            setAttributeEventListener(eventNames().messageEvent, listener);
-            start();
-        }
-        EventListener* onmessage() { return getAttributeEventListener(eventNames().messageEvent); }
+    bool addEventListener(const AtomString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
+    bool removeEventListener(const AtomString& eventType, EventListener&, const ListenerOptions&) final;
 
-        // Returns null if there is no entangled port, or if the entangled port is run by a different thread.
-        // Returns null otherwise.
-        // NOTE: 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();
-        // A port starts out its life entangled, and remains entangled until it is closed or is cloned.
-        bool isEntangled() { return !m_closed && !isCloned(); }
-        // A port is cloned if its entangled channel has been removed and sent to a new owner via postMessage().
-        bool isCloned() { return !m_entangledChannel; }
+    void disentangle();
 
-    private:
-        MessagePort(ScriptExecutionContext&);
+    void registerLocalActivity();
 
-        virtual void refEventTarget() { ref(); }
-        virtual void derefEventTarget() { deref(); }
-        virtual EventTargetData* eventTargetData();
-        virtual EventTargetData* ensureEventTargetData();
+    // 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; }
 
-        OwnPtr<MessagePortChannel> m_entangledChannel;
+    void updateActivity(MessagePortChannelProvider::HasActivity);
 
-        bool m_started;
-        bool m_closed;
+    bool m_started { false };
+    bool m_closed { false };
+    bool m_entangled { true };
 
-        ScriptExecutionContext* m_scriptExecutionContext;
-        EventTargetData m_eventTargetData;
-    };
+    // 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 };
 
-} // namespace WebCore
+    MessagePortIdentifier m_identifier;
+    MessagePortIdentifier m_remoteIdentifier;
 
-#endif // MessagePort_h
+    mutable std::atomic<unsigned> m_refCount { 1 };
+    UniqueRef<GenericEventQueue> m_eventQueue;
+};
+
+} // namespace WebCore