| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 68 |
| 69 // Make sure we aren't connected to any of the passed-in ports. | 69 // Make sure we aren't connected to any of the passed-in ports. |
| 70 for (unsigned i = 0; i < ports.size(); ++i) { | 70 for (unsigned i = 0; i < ports.size(); ++i) { |
| 71 if (ports[i] == this) { | 71 if (ports[i] == this) { |
| 72 exceptionState.throwDOMException( | 72 exceptionState.throwDOMException( |
| 73 DataCloneError, | 73 DataCloneError, |
| 74 "Port at index " + String::number(i) + " contains the source port."); | 74 "Port at index " + String::number(i) + " contains the source port."); |
| 75 return; | 75 return; |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 std::unique_ptr<MessagePortChannelArray> channels = | 78 MessagePortChannelArray channels = |
| 79 MessagePort::disentanglePorts(context, ports, exceptionState); | 79 MessagePort::disentanglePorts(context, ports, exceptionState); |
| 80 if (exceptionState.hadException()) | 80 if (exceptionState.hadException()) |
| 81 return; | 81 return; |
| 82 | 82 |
| 83 WebString messageString = message->toWireString(); | 83 WebString messageString = message->toWireString(); |
| 84 std::unique_ptr<WebMessagePortChannelArray> webChannels = | 84 WebMessagePortChannelArray webChannels = |
| 85 toWebMessagePortChannelArray(std::move(channels)); | 85 toWebMessagePortChannelArray(std::move(channels)); |
| 86 m_entangledChannel->postMessage(messageString, webChannels.release()); | 86 m_entangledChannel->postMessage(messageString, std::move(webChannels)); |
| 87 } | 87 } |
| 88 | 88 |
| 89 // static | 89 // static |
| 90 std::unique_ptr<WebMessagePortChannelArray> | 90 WebMessagePortChannelArray MessagePort::toWebMessagePortChannelArray( |
| 91 MessagePort::toWebMessagePortChannelArray( | 91 MessagePortChannelArray channels) { |
| 92 std::unique_ptr<MessagePortChannelArray> channels) { | 92 WebMessagePortChannelArray webChannels(channels.size()); |
| 93 std::unique_ptr<WebMessagePortChannelArray> webChannels; | 93 for (size_t i = 0; i < channels.size(); ++i) |
| 94 if (channels && channels->size()) { | 94 webChannels[i] = std::move(channels[i]); |
| 95 webChannels = | |
| 96 WTF::wrapUnique(new WebMessagePortChannelArray(channels->size())); | |
| 97 for (size_t i = 0; i < channels->size(); ++i) | |
| 98 (*webChannels)[i] = (*channels)[i].release(); | |
| 99 } | |
| 100 return webChannels; | 95 return webChannels; |
| 101 } | 96 } |
| 102 | 97 |
| 103 // static | 98 // static |
| 104 MessagePortArray* MessagePort::toMessagePortArray( | 99 MessagePortArray* MessagePort::toMessagePortArray( |
| 105 ExecutionContext* context, | 100 ExecutionContext* context, |
| 106 const WebMessagePortChannelArray& webChannels) { | 101 WebMessagePortChannelArray webChannels) { |
| 107 std::unique_ptr<MessagePortChannelArray> channels = | 102 MessagePortChannelArray channels(webChannels.size()); |
| 108 WTF::wrapUnique(new MessagePortChannelArray(webChannels.size())); | |
| 109 for (size_t i = 0; i < webChannels.size(); ++i) | 103 for (size_t i = 0; i < webChannels.size(); ++i) |
| 110 (*channels)[i] = WebMessagePortChannelUniquePtr(webChannels[i]); | 104 channels[i] = std::move(webChannels[i]); |
| 111 return MessagePort::entanglePorts(*context, std::move(channels)); | 105 return MessagePort::entanglePorts(*context, std::move(channels)); |
| 112 } | 106 } |
| 113 | 107 |
| 114 WebMessagePortChannelUniquePtr MessagePort::disentangle() { | 108 WebMessagePortChannelUniquePtr MessagePort::disentangle() { |
| 115 DCHECK(m_entangledChannel); | 109 DCHECK(m_entangledChannel); |
| 116 m_entangledChannel->setClient(nullptr); | 110 m_entangledChannel->setClient(nullptr); |
| 117 return std::move(m_entangledChannel); | 111 return std::move(m_entangledChannel); |
| 118 } | 112 } |
| 119 | 113 |
| 120 // Invoked to notify us that there are messages available for this port. | 114 // Invoked to notify us that there are messages available for this port. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 DCHECK(!m_entangledChannel); | 150 DCHECK(!m_entangledChannel); |
| 157 DCHECK(getExecutionContext()); | 151 DCHECK(getExecutionContext()); |
| 158 | 152 |
| 159 m_entangledChannel = std::move(remote); | 153 m_entangledChannel = std::move(remote); |
| 160 } | 154 } |
| 161 | 155 |
| 162 const AtomicString& MessagePort::interfaceName() const { | 156 const AtomicString& MessagePort::interfaceName() const { |
| 163 return EventTargetNames::MessagePort; | 157 return EventTargetNames::MessagePort; |
| 164 } | 158 } |
| 165 | 159 |
| 166 static bool tryGetMessageFrom( | 160 static bool tryGetMessageFrom(WebMessagePortChannel& webChannel, |
| 167 WebMessagePortChannel& webChannel, | 161 RefPtr<SerializedScriptValue>& message, |
| 168 RefPtr<SerializedScriptValue>& message, | 162 MessagePortChannelArray& channels) { |
| 169 std::unique_ptr<MessagePortChannelArray>& channels) { | |
| 170 WebString messageString; | 163 WebString messageString; |
| 171 WebMessagePortChannelArray webChannels; | 164 WebMessagePortChannelArray webChannels; |
| 172 if (!webChannel.tryGetMessage(&messageString, webChannels)) | 165 if (!webChannel.tryGetMessage(&messageString, webChannels)) |
| 173 return false; | 166 return false; |
| 174 | 167 |
| 175 if (webChannels.size()) { | 168 if (webChannels.size()) { |
| 176 channels = WTF::wrapUnique(new MessagePortChannelArray(webChannels.size())); | 169 channels.resize(webChannels.size()); |
| 177 for (size_t i = 0; i < webChannels.size(); ++i) | 170 for (size_t i = 0; i < webChannels.size(); ++i) |
| 178 (*channels)[i] = WebMessagePortChannelUniquePtr(webChannels[i]); | 171 channels[i] = std::move(webChannels[i]); |
| 179 } | 172 } |
| 180 message = SerializedScriptValue::create(messageString); | 173 message = SerializedScriptValue::create(messageString); |
| 181 return true; | 174 return true; |
| 182 } | 175 } |
| 183 | 176 |
| 184 bool MessagePort::tryGetMessage( | 177 bool MessagePort::tryGetMessage(RefPtr<SerializedScriptValue>& message, |
| 185 RefPtr<SerializedScriptValue>& message, | 178 MessagePortChannelArray& channels) { |
| 186 std::unique_ptr<MessagePortChannelArray>& channels) { | |
| 187 if (!m_entangledChannel) | 179 if (!m_entangledChannel) |
| 188 return false; | 180 return false; |
| 189 return tryGetMessageFrom(*m_entangledChannel, message, channels); | 181 return tryGetMessageFrom(*m_entangledChannel, message, channels); |
| 190 } | 182 } |
| 191 | 183 |
| 192 void MessagePort::dispatchMessages() { | 184 void MessagePort::dispatchMessages() { |
| 193 // Messages for contexts that are not fully active get dispatched too, but | 185 // Messages for contexts that are not fully active get dispatched too, but |
| 194 // JSAbstractEventListener::handleEvent() doesn't call handlers for these. | 186 // JSAbstractEventListener::handleEvent() doesn't call handlers for these. |
| 195 // The HTML5 spec specifies that any messages sent to a document that is not | 187 // The HTML5 spec specifies that any messages sent to a document that is not |
| 196 // fully active should be dropped, so this behavior is OK. | 188 // fully active should be dropped, so this behavior is OK. |
| 197 if (!started()) | 189 if (!started()) |
| 198 return; | 190 return; |
| 199 | 191 |
| 200 while (true) { | 192 while (true) { |
| 201 // Because close() doesn't cancel any in flight calls to dispatchMessages(), | 193 // Because close() doesn't cancel any in flight calls to dispatchMessages(), |
| 202 // and can be triggered by the onmessage event handler, we need to check if | 194 // and can be triggered by the onmessage event handler, we need to check if |
| 203 // the port is still open before each dispatch. | 195 // the port is still open before each dispatch. |
| 204 if (m_closed) | 196 if (m_closed) |
| 205 break; | 197 break; |
| 206 | 198 |
| 207 // WorkerGlobalScope::close() in Worker onmessage handler should prevent | 199 // WorkerGlobalScope::close() in Worker onmessage handler should prevent |
| 208 // the next message from dispatching. | 200 // the next message from dispatching. |
| 209 if (getExecutionContext()->isWorkerGlobalScope() && | 201 if (getExecutionContext()->isWorkerGlobalScope() && |
| 210 toWorkerGlobalScope(getExecutionContext())->isClosing()) { | 202 toWorkerGlobalScope(getExecutionContext())->isClosing()) { |
| 211 break; | 203 break; |
| 212 } | 204 } |
| 213 | 205 |
| 214 RefPtr<SerializedScriptValue> message; | 206 RefPtr<SerializedScriptValue> message; |
| 215 std::unique_ptr<MessagePortChannelArray> channels; | 207 MessagePortChannelArray channels; |
| 216 if (!tryGetMessage(message, channels)) | 208 if (!tryGetMessage(message, channels)) |
| 217 break; | 209 break; |
| 218 | 210 |
| 219 MessagePortArray* ports = | 211 MessagePortArray* ports = |
| 220 MessagePort::entanglePorts(*getExecutionContext(), std::move(channels)); | 212 MessagePort::entanglePorts(*getExecutionContext(), std::move(channels)); |
| 221 Event* evt = MessageEvent::create(ports, std::move(message)); | 213 Event* evt = MessageEvent::create(ports, std::move(message)); |
| 222 | 214 |
| 223 dispatchEvent(evt); | 215 dispatchEvent(evt); |
| 224 } | 216 } |
| 225 } | 217 } |
| 226 | 218 |
| 227 bool MessagePort::hasPendingActivity() const { | 219 bool MessagePort::hasPendingActivity() const { |
| 228 // The spec says that entangled message ports should always be treated as if | 220 // The spec says that entangled message ports should always be treated as if |
| 229 // they have a strong reference. | 221 // they have a strong reference. |
| 230 // We'll also stipulate that the queue needs to be open (if the app drops its | 222 // We'll also stipulate that the queue needs to be open (if the app drops its |
| 231 // reference to the port before start()-ing it, then it's not really entangled | 223 // reference to the port before start()-ing it, then it's not really entangled |
| 232 // as it's unreachable). | 224 // as it's unreachable). |
| 233 return m_started && isEntangled(); | 225 return m_started && isEntangled(); |
| 234 } | 226 } |
| 235 | 227 |
| 236 std::unique_ptr<MessagePortChannelArray> MessagePort::disentanglePorts( | 228 MessagePortChannelArray MessagePort::disentanglePorts( |
| 237 ExecutionContext* context, | 229 ExecutionContext* context, |
| 238 const MessagePortArray& ports, | 230 const MessagePortArray& ports, |
| 239 ExceptionState& exceptionState) { | 231 ExceptionState& exceptionState) { |
| 240 if (!ports.size()) | 232 if (!ports.size()) |
| 241 return nullptr; | 233 return MessagePortChannelArray(); |
| 242 | 234 |
| 243 HeapHashSet<Member<MessagePort>> visited; | 235 HeapHashSet<Member<MessagePort>> visited; |
| 244 | 236 |
| 245 // Walk the incoming array - if there are any duplicate ports, or null ports | 237 // Walk the incoming array - if there are any duplicate ports, or null ports |
| 246 // or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec). | 238 // or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec). |
| 247 for (unsigned i = 0; i < ports.size(); ++i) { | 239 for (unsigned i = 0; i < ports.size(); ++i) { |
| 248 MessagePort* port = ports[i]; | 240 MessagePort* port = ports[i]; |
| 249 if (!port || port->isNeutered() || visited.contains(port)) { | 241 if (!port || port->isNeutered() || visited.contains(port)) { |
| 250 String type; | 242 String type; |
| 251 if (!port) | 243 if (!port) |
| 252 type = "null"; | 244 type = "null"; |
| 253 else if (port->isNeutered()) | 245 else if (port->isNeutered()) |
| 254 type = "already neutered"; | 246 type = "already neutered"; |
| 255 else | 247 else |
| 256 type = "a duplicate"; | 248 type = "a duplicate"; |
| 257 exceptionState.throwDOMException( | 249 exceptionState.throwDOMException( |
| 258 DataCloneError, | 250 DataCloneError, |
| 259 "Port at index " + String::number(i) + " is " + type + "."); | 251 "Port at index " + String::number(i) + " is " + type + "."); |
| 260 return nullptr; | 252 return MessagePortChannelArray(); |
| 261 } | 253 } |
| 262 visited.insert(port); | 254 visited.insert(port); |
| 263 } | 255 } |
| 264 | 256 |
| 265 UseCounter::count(context, UseCounter::MessagePortsTransferred); | 257 UseCounter::count(context, UseCounter::MessagePortsTransferred); |
| 266 | 258 |
| 267 // Passed-in ports passed validity checks, so we can disentangle them. | 259 // Passed-in ports passed validity checks, so we can disentangle them. |
| 268 std::unique_ptr<MessagePortChannelArray> portArray = | 260 MessagePortChannelArray portArray(ports.size()); |
| 269 WTF::wrapUnique(new MessagePortChannelArray(ports.size())); | |
| 270 for (unsigned i = 0; i < ports.size(); ++i) | 261 for (unsigned i = 0; i < ports.size(); ++i) |
| 271 (*portArray)[i] = ports[i]->disentangle(); | 262 portArray[i] = ports[i]->disentangle(); |
| 272 return portArray; | 263 return portArray; |
| 273 } | 264 } |
| 274 | 265 |
| 275 MessagePortArray* MessagePort::entanglePorts( | 266 MessagePortArray* MessagePort::entanglePorts(ExecutionContext& context, |
| 276 ExecutionContext& context, | 267 MessagePortChannelArray channels) { |
| 277 std::unique_ptr<MessagePortChannelArray> channels) { | |
| 278 // https://html.spec.whatwg.org/multipage/comms.html#message-ports | 268 // https://html.spec.whatwg.org/multipage/comms.html#message-ports |
| 279 // |ports| should be an empty array, not null even when there is no ports. | 269 // |ports| should be an empty array, not null even when there is no ports. |
| 280 if (!channels || !channels->size()) | 270 MessagePortArray* portArray = new MessagePortArray(channels.size()); |
| 281 return new MessagePortArray; | 271 for (unsigned i = 0; i < channels.size(); ++i) { |
| 282 | |
| 283 MessagePortArray* portArray = new MessagePortArray(channels->size()); | |
| 284 for (unsigned i = 0; i < channels->size(); ++i) { | |
| 285 MessagePort* port = MessagePort::create(context); | 272 MessagePort* port = MessagePort::create(context); |
| 286 port->entangle(std::move((*channels)[i])); | 273 port->entangle(std::move(channels[i])); |
| 287 (*portArray)[i] = port; | 274 (*portArray)[i] = port; |
| 288 } | 275 } |
| 289 return portArray; | 276 return portArray; |
| 290 } | 277 } |
| 291 | 278 |
| 292 DEFINE_TRACE(MessagePort) { | 279 DEFINE_TRACE(MessagePort) { |
| 293 ContextLifecycleObserver::trace(visitor); | 280 ContextLifecycleObserver::trace(visitor); |
| 294 EventTargetWithInlineData::trace(visitor); | 281 EventTargetWithInlineData::trace(visitor); |
| 295 } | 282 } |
| 296 | 283 |
| 297 } // namespace blink | 284 } // namespace blink |
| OLD | NEW |