summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/MessagePort.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom/MessagePort.cpp')
-rw-r--r--Source/WebCore/dom/MessagePort.cpp139
1 files changed, 67 insertions, 72 deletions
diff --git a/Source/WebCore/dom/MessagePort.cpp b/Source/WebCore/dom/MessagePort.cpp
index 64167230f..a44af43a2 100644
--- a/Source/WebCore/dom/MessagePort.cpp
+++ b/Source/WebCore/dom/MessagePort.cpp
@@ -10,10 +10,10 @@
* 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
@@ -28,19 +28,17 @@
#include "MessagePort.h"
#include "Document.h"
-#include "EventException.h"
+#include "EventNames.h"
+#include "ExceptionCode.h"
#include "MessageEvent.h"
-#include "SecurityOrigin.h"
#include "WorkerGlobalScope.h"
namespace WebCore {
MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext)
- : m_started(false)
- , m_closed(false)
- , m_scriptExecutionContext(&scriptExecutionContext)
+ : m_scriptExecutionContext(&scriptExecutionContext)
{
- m_scriptExecutionContext->createdMessagePort(this);
+ m_scriptExecutionContext->createdMessagePort(*this);
// Don't need to call processMessagePortMessagesSoon() here, because the port will not be opened until start() is invoked.
}
@@ -49,52 +47,48 @@ MessagePort::~MessagePort()
{
close();
if (m_scriptExecutionContext)
- m_scriptExecutionContext->destroyedMessagePort(this);
+ m_scriptExecutionContext->destroyedMessagePort(*this);
}
-void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec)
+ExceptionOr<void> MessagePort::postMessage(JSC::ExecState& state, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer)
{
- MessagePortArray ports;
- if (port)
- ports.append(port);
- postMessage(message, &ports, ec);
-}
+ Vector<RefPtr<MessagePort>> ports;
+ auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
+ if (message.hasException())
+ return message.releaseException();
-void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec)
-{
if (!isEntangled())
- return;
+ return { };
ASSERT(m_scriptExecutionContext);
- OwnPtr<MessagePortChannelArray> channels;
+ std::unique_ptr<MessagePortChannelArray> channels;
// Make sure we aren't connected to any of the passed-in ports.
- if (ports) {
- for (unsigned int i = 0; i < ports->size(); ++i) {
- MessagePort* dataPort = (*ports)[i].get();
- if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort)) {
- ec = DATA_CLONE_ERR;
- return;
- }
+ if (!ports.isEmpty()) {
+ for (auto& dataPort : ports) {
+ if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort.get()))
+ return Exception { DATA_CLONE_ERR };
}
- channels = MessagePort::disentanglePorts(ports, ec);
- if (ec)
- return;
+ auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports));
+ if (disentangleResult.hasException())
+ return disentangleResult.releaseException();
+ channels = disentangleResult.releaseReturnValue();
}
- m_entangledChannel->postMessageToRemote(message, channels.release());
+ m_entangledChannel->postMessageToRemote(message.releaseReturnValue(), WTFMove(channels));
+ return { };
}
-PassOwnPtr<MessagePortChannel> MessagePort::disentangle()
+std::unique_ptr<MessagePortChannel> MessagePort::disentangle()
{
ASSERT(m_entangledChannel);
m_entangledChannel->disentangle();
- // We can't receive any messages or generate any events, so remove ourselves from the list of active ports.
+ // We can't receive any messages or generate any events after this, so remove ourselves from the list of active ports.
ASSERT(m_scriptExecutionContext);
- m_scriptExecutionContext->destroyedMessagePort(this);
- m_scriptExecutionContext = 0;
+ m_scriptExecutionContext->destroyedMessagePort(*this);
+ m_scriptExecutionContext = nullptr;
- return m_entangledChannel.release();
+ return WTFMove(m_entangledChannel);
}
// Invoked to notify us that there are messages available for this port.
@@ -126,7 +120,7 @@ void MessagePort::close()
m_closed = true;
}
-void MessagePort::entangle(PassOwnPtr<MessagePortChannel> remote)
+void MessagePort::entangle(std::unique_ptr<MessagePortChannel>&& remote)
{
// Only invoked to set our initial entanglement.
ASSERT(!m_entangledChannel);
@@ -134,7 +128,7 @@ void MessagePort::entangle(PassOwnPtr<MessagePortChannel> remote)
// Don't entangle the ports if the channel is closed.
if (remote->entangleIfOpen(this))
- m_entangledChannel = remote;
+ m_entangledChannel = WTFMove(remote);
}
void MessagePort::contextDestroyed()
@@ -143,7 +137,7 @@ void MessagePort::contextDestroyed()
// Must be closed before blowing away the cached context, to ensure that we get no more calls to messageAvailable().
// ScriptExecutionContext::closeMessagePorts() takes care of that.
ASSERT(m_closed);
- m_scriptExecutionContext = 0;
+ m_scriptExecutionContext = nullptr;
}
void MessagePort::dispatchMessages()
@@ -152,18 +146,19 @@ void MessagePort::dispatchMessages()
// The HTML5 spec specifies that any messages sent to a document that is not fully active should be dropped, so this behavior is OK.
ASSERT(started());
- RefPtr<SerializedScriptValue> message;
- OwnPtr<MessagePortChannelArray> channels;
- while (m_entangledChannel && m_entangledChannel->tryGetMessageFromRemote(message, channels)) {
+ if (!m_entangledChannel)
+ return;
+
+ bool contextIsWorker = is<WorkerGlobalScope>(*m_scriptExecutionContext);
+ auto pendingMessages = m_entangledChannel->takeAllMessagesFromRemote();
+ for (auto& message : pendingMessages) {
// close() in Worker onmessage handler should prevent next message from dispatching.
- if (m_scriptExecutionContext->isWorkerGlobalScope() && static_cast<WorkerGlobalScope*>(m_scriptExecutionContext)->isClosing())
+ if (contextIsWorker && downcast<WorkerGlobalScope>(*m_scriptExecutionContext).isClosing())
return;
- OwnPtr<MessagePortArray> ports = MessagePort::entanglePorts(*m_scriptExecutionContext, channels.release());
- RefPtr<Event> evt = MessageEvent::create(ports.release(), message.release());
-
- dispatchEvent(evt.release(), ASSERT_NO_EXCEPTION);
+ auto ports = MessagePort::entanglePorts(*m_scriptExecutionContext, WTFMove(message->channels));
+ dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message->message)));
}
}
@@ -180,48 +175,48 @@ bool MessagePort::hasPendingActivity()
MessagePort* MessagePort::locallyEntangledPort()
{
- return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : 0;
+ return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : nullptr;
}
-PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(const MessagePortArray* ports, ExceptionCode& ec)
+ExceptionOr<std::unique_ptr<MessagePortChannelArray>> MessagePort::disentanglePorts(Vector<RefPtr<MessagePort>>&& ports)
{
- if (!ports || !ports->size())
+ if (ports.isEmpty())
return nullptr;
- // HashSet used to efficiently check for duplicates in the passed-in array.
- HashSet<MessagePort*> portSet;
-
// Walk the incoming array - if there are any duplicate ports, or null ports or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec).
- for (unsigned int i = 0; i < ports->size(); ++i) {
- MessagePort* port = (*ports)[i].get();
- if (!port || port->isNeutered() || portSet.contains(port)) {
- ec = DATA_CLONE_ERR;
- return nullptr;
- }
- portSet.add(port);
+ HashSet<MessagePort*> portSet;
+ for (auto& port : ports) {
+ if (!port || port->isNeutered() || !portSet.add(port.get()).isNewEntry)
+ return Exception { DATA_CLONE_ERR };
}
// Passed-in ports passed validity checks, so we can disentangle them.
- OwnPtr<MessagePortChannelArray> portArray = adoptPtr(new MessagePortChannelArray(ports->size()));
- for (unsigned int i = 0 ; i < ports->size() ; ++i) {
- OwnPtr<MessagePortChannel> channel = (*ports)[i]->disentangle();
- (*portArray)[i] = channel.release();
- }
- return portArray.release();
+ auto portArray = std::make_unique<MessagePortChannelArray>(ports.size());
+ for (unsigned i = 0 ; i < ports.size(); ++i)
+ (*portArray)[i] = ports[i]->disentangle();
+ return WTFMove(portArray);
}
-PassOwnPtr<MessagePortArray> MessagePort::entanglePorts(ScriptExecutionContext& context, PassOwnPtr<MessagePortChannelArray> channels)
+Vector<RefPtr<MessagePort>> MessagePort::entanglePorts(ScriptExecutionContext& context, std::unique_ptr<MessagePortChannelArray>&& channels)
{
if (!channels || !channels->size())
- return nullptr;
+ return { };
- OwnPtr<MessagePortArray> portArray = adoptPtr(new MessagePortArray(channels->size()));
+ Vector<RefPtr<MessagePort>> portArray;
+ portArray.reserveInitialCapacity(channels->size());
for (unsigned int i = 0; i < channels->size(); ++i) {
- RefPtr<MessagePort> port = MessagePort::create(context);
- port->entangle((*channels)[i].release());
- (*portArray)[i] = port.release();
+ auto port = MessagePort::create(context);
+ port->entangle(WTFMove((*channels)[i]));
+ portArray.uncheckedAppend(WTFMove(port));
}
- return portArray.release();
+ return portArray;
+}
+
+bool MessagePort::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
+{
+ if (listener->isAttribute() && eventType == eventNames().messageEvent)
+ start();
+ return EventTargetWithInlineData::addEventListener(eventType, WTFMove(listener), options);
}
} // namespace WebCore