42
44
class AtomicStringImpl;
45
48
class ScriptExecutionContext;
51
// The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
52
typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray;
49
54
class MessagePort : public RefCounted<MessagePort>, public EventTarget {
51
static PassRefPtr<MessagePort> create(ScriptExecutionContext* scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); }
56
static PassRefPtr<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); }
54
PassRefPtr<MessagePort> clone(ExceptionCode&); // Returns a port that isn't attached to any context.
56
bool active() const { return m_entangledPort; }
57
59
void postMessage(const String& message, ExceptionCode&);
60
void postMessage(const String& message, const MessagePortArray*, ExceptionCode&);
61
// FIXME: remove this when we update the ObjC bindings (bug #28774).
58
62
void postMessage(const String& message, MessagePort*, ExceptionCode&);
59
PassRefPtr<MessagePort> startConversation(ScriptExecutionContext*, const String& message);
63
bool queueIsOpen() const { return m_queueIsOpen; }
65
MessagePort* entangledPort() { return m_entangledPort; }
66
static void entangle(MessagePort*, MessagePort*);
67
void entangle(PassOwnPtr<MessagePortChannel>);
68
PassOwnPtr<MessagePortChannel> disentangle(ExceptionCode&);
70
// Disentangle an array of ports, returning the entangled channels.
71
// 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.
72
// Returns 0 if there is an exception, or if the passed-in array is 0/empty.
73
static PassOwnPtr<MessagePortChannelArray> disentanglePorts(const MessagePortArray*, ExceptionCode&);
75
// Entangles an array of channels, returning an array of MessagePorts in matching order.
76
// Returns 0 if the passed array is 0/empty.
77
static PassOwnPtr<MessagePortArray> entanglePorts(ScriptExecutionContext&, PassOwnPtr<MessagePortChannelArray>);
79
void messageAvailable();
80
bool started() const { return m_started; }
69
82
void contextDestroyed();
70
void attachToContext(ScriptExecutionContext*);
71
84
virtual ScriptExecutionContext* scriptExecutionContext() const;
73
86
virtual MessagePort* toMessagePort() { return this; }
75
void queueCloseEvent();
76
88
void dispatchMessages();
78
virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
79
virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
80
virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
82
typedef Vector<RefPtr<EventListener> > ListenerVector;
83
typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
84
EventListenersMap& eventListeners() { return m_eventListeners; }
86
90
using RefCounted<MessagePort>::ref;
87
91
using RefCounted<MessagePort>::deref;
89
93
bool hasPendingActivity();
91
// FIXME: Per current spec, setting onmessage should automagically start the port (unlike addEventListener("message", ...)).
92
void setOnmessage(PassRefPtr<EventListener> eventListener) { m_onMessageListener = eventListener; }
93
EventListener* onmessage() const { return m_onMessageListener.get(); }
95
void setOnmessage(PassRefPtr<EventListener> listener)
97
setAttributeEventListener(eventNames().messageEvent, listener);
100
EventListener* onmessage() { return getAttributeEventListener(eventNames().messageEvent); }
95
void setOnclose(PassRefPtr<EventListener> eventListener) { m_onCloseListener = eventListener; }
96
EventListener* onclose() const { return m_onCloseListener.get(); }
102
// Returns null if there is no entangled port, or if the entangled port is run by a different thread.
103
// Returns null otherwise.
104
// 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.
105
MessagePort* locallyEntangledPort();
106
bool isEntangled() { return m_entangledChannel; }
99
friend class MessagePortCloseEventTask;
101
MessagePort(ScriptExecutionContext*);
109
MessagePort(ScriptExecutionContext&);
103
111
virtual void refEventTarget() { ref(); }
104
112
virtual void derefEventTarget() { deref(); }
106
void dispatchCloseEvent();
108
MessagePort* m_entangledPort;
110
// FIXME: EventData is necessary to pass messages to other threads. In single threaded case, we can just queue a created event.
111
struct EventData : public RefCounted<EventData> {
112
static PassRefPtr<EventData> create(const String& message, PassRefPtr<MessagePort>);
116
RefPtr<MessagePort> messagePort;
119
EventData(const String& message, PassRefPtr<MessagePort>);
121
MessageQueue<RefPtr<EventData> > m_messageQueue; // FIXME: No need to use MessageQueue in single threaded case.
113
virtual EventTargetData* eventTargetData();
114
virtual EventTargetData* ensureEventTargetData();
116
OwnPtr<MessagePortChannel> m_entangledChannel;
124
120
ScriptExecutionContext* m_scriptExecutionContext;
126
RefPtr<EventListener> m_onMessageListener;
127
RefPtr<EventListener> m_onCloseListener;
129
EventListenersMap m_eventListeners;
131
bool m_pendingCloseEvent; // The port is GC protected while waiting for a close event to be dispatched.
121
EventTargetData m_eventTargetData;
134
124
} // namespace WebCore