diff options
Diffstat (limited to 'Source/WebCore/dom/MessagePort.cpp')
-rw-r--r-- | Source/WebCore/dom/MessagePort.cpp | 139 |
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 |