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 21 matching lines...) Expand all Loading... |
32 #include "bindings/core/v8/SerializedScriptValueFactory.h" | 32 #include "bindings/core/v8/SerializedScriptValueFactory.h" |
33 #include "core/dom/CrossThreadTask.h" | 33 #include "core/dom/CrossThreadTask.h" |
34 #include "core/dom/ExceptionCode.h" | 34 #include "core/dom/ExceptionCode.h" |
35 #include "core/dom/ExecutionContext.h" | 35 #include "core/dom/ExecutionContext.h" |
36 #include "core/events/MessageEvent.h" | 36 #include "core/events/MessageEvent.h" |
37 #include "core/frame/LocalDOMWindow.h" | 37 #include "core/frame/LocalDOMWindow.h" |
38 #include "core/inspector/ConsoleMessage.h" | 38 #include "core/inspector/ConsoleMessage.h" |
39 #include "core/workers/WorkerGlobalScope.h" | 39 #include "core/workers/WorkerGlobalScope.h" |
40 #include "public/platform/WebString.h" | 40 #include "public/platform/WebString.h" |
41 #include "wtf/Functional.h" | 41 #include "wtf/Functional.h" |
| 42 #include "wtf/PtrUtil.h" |
42 #include "wtf/text/AtomicString.h" | 43 #include "wtf/text/AtomicString.h" |
| 44 #include <memory> |
43 | 45 |
44 namespace blink { | 46 namespace blink { |
45 | 47 |
46 MessagePort* MessagePort::create(ExecutionContext& executionContext) | 48 MessagePort* MessagePort::create(ExecutionContext& executionContext) |
47 { | 49 { |
48 MessagePort* port = new MessagePort(executionContext); | 50 MessagePort* port = new MessagePort(executionContext); |
49 port->suspendIfNeeded(); | 51 port->suspendIfNeeded(); |
50 return port; | 52 return port; |
51 } | 53 } |
52 | 54 |
(...skipping 19 matching lines...) Expand all Loading... |
72 DCHECK(getExecutionContext()); | 74 DCHECK(getExecutionContext()); |
73 DCHECK(m_entangledChannel); | 75 DCHECK(m_entangledChannel); |
74 | 76 |
75 // Make sure we aren't connected to any of the passed-in ports. | 77 // Make sure we aren't connected to any of the passed-in ports. |
76 for (unsigned i = 0; i < ports.size(); ++i) { | 78 for (unsigned i = 0; i < ports.size(); ++i) { |
77 if (ports[i] == this) { | 79 if (ports[i] == this) { |
78 exceptionState.throwDOMException(DataCloneError, "Port at index " +
String::number(i) + " contains the source port."); | 80 exceptionState.throwDOMException(DataCloneError, "Port at index " +
String::number(i) + " contains the source port."); |
79 return; | 81 return; |
80 } | 82 } |
81 } | 83 } |
82 OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(con
text, ports, exceptionState); | 84 std::unique_ptr<MessagePortChannelArray> channels = MessagePort::disentangle
Ports(context, ports, exceptionState); |
83 if (exceptionState.hadException()) | 85 if (exceptionState.hadException()) |
84 return; | 86 return; |
85 | 87 |
86 if (message->containsTransferableArrayBuffer()) | 88 if (message->containsTransferableArrayBuffer()) |
87 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMessag
eSource, WarningMessageLevel, "MessagePort cannot send an ArrayBuffer as a trans
ferable object yet. See http://crbug.com/334408")); | 89 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMessag
eSource, WarningMessageLevel, "MessagePort cannot send an ArrayBuffer as a trans
ferable object yet. See http://crbug.com/334408")); |
88 | 90 |
89 WebString messageString = message->toWireString(); | 91 WebString messageString = message->toWireString(); |
90 OwnPtr<WebMessagePortChannelArray> webChannels = toWebMessagePortChannelArra
y(std::move(channels)); | 92 std::unique_ptr<WebMessagePortChannelArray> webChannels = toWebMessagePortCh
annelArray(std::move(channels)); |
91 m_entangledChannel->postMessage(messageString, webChannels.leakPtr()); | 93 m_entangledChannel->postMessage(messageString, webChannels.release()); |
92 } | 94 } |
93 | 95 |
94 // static | 96 // static |
95 PassOwnPtr<WebMessagePortChannelArray> MessagePort::toWebMessagePortChannelArray
(PassOwnPtr<MessagePortChannelArray> channels) | 97 std::unique_ptr<WebMessagePortChannelArray> MessagePort::toWebMessagePortChannel
Array(std::unique_ptr<MessagePortChannelArray> channels) |
96 { | 98 { |
97 OwnPtr<WebMessagePortChannelArray> webChannels; | 99 std::unique_ptr<WebMessagePortChannelArray> webChannels; |
98 if (channels && channels->size()) { | 100 if (channels && channels->size()) { |
99 webChannels = adoptPtr(new WebMessagePortChannelArray(channels->size()))
; | 101 webChannels = wrapUnique(new WebMessagePortChannelArray(channels->size()
)); |
100 for (size_t i = 0; i < channels->size(); ++i) | 102 for (size_t i = 0; i < channels->size(); ++i) |
101 (*webChannels)[i] = (*channels)[i].release(); | 103 (*webChannels)[i] = (*channels)[i].release(); |
102 } | 104 } |
103 return webChannels; | 105 return webChannels; |
104 } | 106 } |
105 | 107 |
106 // static | 108 // static |
107 MessagePortArray* MessagePort::toMessagePortArray(ExecutionContext* context, con
st WebMessagePortChannelArray& webChannels) | 109 MessagePortArray* MessagePort::toMessagePortArray(ExecutionContext* context, con
st WebMessagePortChannelArray& webChannels) |
108 { | 110 { |
109 OwnPtr<MessagePortChannelArray> channels = adoptPtr(new MessagePortChannelAr
ray(webChannels.size())); | 111 std::unique_ptr<MessagePortChannelArray> channels = wrapUnique(new MessagePo
rtChannelArray(webChannels.size())); |
110 for (size_t i = 0; i < webChannels.size(); ++i) | 112 for (size_t i = 0; i < webChannels.size(); ++i) |
111 (*channels)[i] = WebMessagePortChannelUniquePtr(webChannels[i]); | 113 (*channels)[i] = WebMessagePortChannelUniquePtr(webChannels[i]); |
112 return MessagePort::entanglePorts(*context, std::move(channels)); | 114 return MessagePort::entanglePorts(*context, std::move(channels)); |
113 } | 115 } |
114 | 116 |
115 WebMessagePortChannelUniquePtr MessagePort::disentangle() | 117 WebMessagePortChannelUniquePtr MessagePort::disentangle() |
116 { | 118 { |
117 DCHECK(m_entangledChannel); | 119 DCHECK(m_entangledChannel); |
118 m_entangledChannel->setClient(0); | 120 m_entangledChannel->setClient(0); |
119 return std::move(m_entangledChannel); | 121 return std::move(m_entangledChannel); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 | 158 |
157 m_entangledChannel = std::move(remote); | 159 m_entangledChannel = std::move(remote); |
158 m_entangledChannel->setClient(this); | 160 m_entangledChannel->setClient(this); |
159 } | 161 } |
160 | 162 |
161 const AtomicString& MessagePort::interfaceName() const | 163 const AtomicString& MessagePort::interfaceName() const |
162 { | 164 { |
163 return EventTargetNames::MessagePort; | 165 return EventTargetNames::MessagePort; |
164 } | 166 } |
165 | 167 |
166 static bool tryGetMessageFrom(WebMessagePortChannel& webChannel, RefPtr<Serializ
edScriptValue>& message, OwnPtr<MessagePortChannelArray>& channels) | 168 static bool tryGetMessageFrom(WebMessagePortChannel& webChannel, RefPtr<Serializ
edScriptValue>& message, std::unique_ptr<MessagePortChannelArray>& channels) |
167 { | 169 { |
168 WebString messageString; | 170 WebString messageString; |
169 WebMessagePortChannelArray webChannels; | 171 WebMessagePortChannelArray webChannels; |
170 if (!webChannel.tryGetMessage(&messageString, webChannels)) | 172 if (!webChannel.tryGetMessage(&messageString, webChannels)) |
171 return false; | 173 return false; |
172 | 174 |
173 if (webChannels.size()) { | 175 if (webChannels.size()) { |
174 channels = adoptPtr(new MessagePortChannelArray(webChannels.size())); | 176 channels = wrapUnique(new MessagePortChannelArray(webChannels.size())); |
175 for (size_t i = 0; i < webChannels.size(); ++i) | 177 for (size_t i = 0; i < webChannels.size(); ++i) |
176 (*channels)[i] = WebMessagePortChannelUniquePtr(webChannels[i]); | 178 (*channels)[i] = WebMessagePortChannelUniquePtr(webChannels[i]); |
177 } | 179 } |
178 message = SerializedScriptValue::create(messageString); | 180 message = SerializedScriptValue::create(messageString); |
179 return true; | 181 return true; |
180 } | 182 } |
181 | 183 |
182 bool MessagePort::tryGetMessage(RefPtr<SerializedScriptValue>& message, OwnPtr<M
essagePortChannelArray>& channels) | 184 bool MessagePort::tryGetMessage(RefPtr<SerializedScriptValue>& message, std::uni
que_ptr<MessagePortChannelArray>& channels) |
183 { | 185 { |
184 if (!m_entangledChannel) | 186 if (!m_entangledChannel) |
185 return false; | 187 return false; |
186 return tryGetMessageFrom(*m_entangledChannel, message, channels); | 188 return tryGetMessageFrom(*m_entangledChannel, message, channels); |
187 } | 189 } |
188 | 190 |
189 void MessagePort::dispatchMessages() | 191 void MessagePort::dispatchMessages() |
190 { | 192 { |
191 // Because close() doesn't cancel any in flight calls to dispatchMessages()
we need to check if the port is still open before dispatch. | 193 // Because close() doesn't cancel any in flight calls to dispatchMessages()
we need to check if the port is still open before dispatch. |
192 if (m_closed) | 194 if (m_closed) |
193 return; | 195 return; |
194 | 196 |
195 // Messages for contexts that are not fully active get dispatched too, but J
SAbstractEventListener::handleEvent() doesn't call handlers for these. | 197 // Messages for contexts that are not fully active get dispatched too, but J
SAbstractEventListener::handleEvent() doesn't call handlers for these. |
196 // The HTML5 spec specifies that any messages sent to a document that is not
fully active should be dropped, so this behavior is OK. | 198 // The HTML5 spec specifies that any messages sent to a document that is not
fully active should be dropped, so this behavior is OK. |
197 if (!started()) | 199 if (!started()) |
198 return; | 200 return; |
199 | 201 |
200 RefPtr<SerializedScriptValue> message; | 202 RefPtr<SerializedScriptValue> message; |
201 OwnPtr<MessagePortChannelArray> channels; | 203 std::unique_ptr<MessagePortChannelArray> channels; |
202 while (tryGetMessage(message, channels)) { | 204 while (tryGetMessage(message, channels)) { |
203 // close() in Worker onmessage handler should prevent next message from
dispatching. | 205 // close() in Worker onmessage handler should prevent next message from
dispatching. |
204 if (getExecutionContext()->isWorkerGlobalScope() && toWorkerGlobalScope(
getExecutionContext())->isClosing()) | 206 if (getExecutionContext()->isWorkerGlobalScope() && toWorkerGlobalScope(
getExecutionContext())->isClosing()) |
205 return; | 207 return; |
206 | 208 |
207 MessagePortArray* ports = MessagePort::entanglePorts(*getExecutionContex
t(), std::move(channels)); | 209 MessagePortArray* ports = MessagePort::entanglePorts(*getExecutionContex
t(), std::move(channels)); |
208 Event* evt = MessageEvent::create(ports, message.release()); | 210 Event* evt = MessageEvent::create(ports, message.release()); |
209 | 211 |
210 dispatchEvent(evt); | 212 dispatchEvent(evt); |
211 } | 213 } |
212 } | 214 } |
213 | 215 |
214 bool MessagePort::hasPendingActivity() const | 216 bool MessagePort::hasPendingActivity() const |
215 { | 217 { |
216 // The spec says that entangled message ports should always be treated as if
they have a strong reference. | 218 // The spec says that entangled message ports should always be treated as if
they have a strong reference. |
217 // We'll also stipulate that the queue needs to be open (if the app drops it
s reference to the port before start()-ing it, then it's not really entangled as
it's unreachable). | 219 // We'll also stipulate that the queue needs to be open (if the app drops it
s reference to the port before start()-ing it, then it's not really entangled as
it's unreachable). |
218 return m_started && isEntangled(); | 220 return m_started && isEntangled(); |
219 } | 221 } |
220 | 222 |
221 PassOwnPtr<MessagePortChannelArray> MessagePort::disentanglePorts(ExecutionConte
xt* context, const MessagePortArray& ports, ExceptionState& exceptionState) | 223 std::unique_ptr<MessagePortChannelArray> MessagePort::disentanglePorts(Execution
Context* context, const MessagePortArray& ports, ExceptionState& exceptionState) |
222 { | 224 { |
223 if (!ports.size()) | 225 if (!ports.size()) |
224 return nullptr; | 226 return nullptr; |
225 | 227 |
226 HeapHashSet<Member<MessagePort>> visited; | 228 HeapHashSet<Member<MessagePort>> visited; |
227 | 229 |
228 // 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). | 230 // 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). |
229 for (unsigned i = 0; i < ports.size(); ++i) { | 231 for (unsigned i = 0; i < ports.size(); ++i) { |
230 MessagePort* port = ports[i]; | 232 MessagePort* port = ports[i]; |
231 if (!port || port->isNeutered() || visited.contains(port)) { | 233 if (!port || port->isNeutered() || visited.contains(port)) { |
232 String type; | 234 String type; |
233 if (!port) | 235 if (!port) |
234 type = "null"; | 236 type = "null"; |
235 else if (port->isNeutered()) | 237 else if (port->isNeutered()) |
236 type = "already neutered"; | 238 type = "already neutered"; |
237 else | 239 else |
238 type = "a duplicate"; | 240 type = "a duplicate"; |
239 exceptionState.throwDOMException(DataCloneError, "Port at index " +
String::number(i) + " is " + type + "."); | 241 exceptionState.throwDOMException(DataCloneError, "Port at index " +
String::number(i) + " is " + type + "."); |
240 return nullptr; | 242 return nullptr; |
241 } | 243 } |
242 visited.add(port); | 244 visited.add(port); |
243 } | 245 } |
244 | 246 |
245 UseCounter::count(context, UseCounter::MessagePortsTransferred); | 247 UseCounter::count(context, UseCounter::MessagePortsTransferred); |
246 | 248 |
247 // Passed-in ports passed validity checks, so we can disentangle them. | 249 // Passed-in ports passed validity checks, so we can disentangle them. |
248 OwnPtr<MessagePortChannelArray> portArray = adoptPtr(new MessagePortChannelA
rray(ports.size())); | 250 std::unique_ptr<MessagePortChannelArray> portArray = wrapUnique(new MessageP
ortChannelArray(ports.size())); |
249 for (unsigned i = 0; i < ports.size(); ++i) | 251 for (unsigned i = 0; i < ports.size(); ++i) |
250 (*portArray)[i] = ports[i]->disentangle(); | 252 (*portArray)[i] = ports[i]->disentangle(); |
251 return portArray; | 253 return portArray; |
252 } | 254 } |
253 | 255 |
254 MessagePortArray* MessagePort::entanglePorts(ExecutionContext& context, PassOwnP
tr<MessagePortChannelArray> channels) | 256 MessagePortArray* MessagePort::entanglePorts(ExecutionContext& context, std::uni
que_ptr<MessagePortChannelArray> channels) |
255 { | 257 { |
256 // https://html.spec.whatwg.org/multipage/comms.html#message-ports | 258 // https://html.spec.whatwg.org/multipage/comms.html#message-ports |
257 // |ports| should be an empty array, not null even when there is no ports. | 259 // |ports| should be an empty array, not null even when there is no ports. |
258 if (!channels || !channels->size()) | 260 if (!channels || !channels->size()) |
259 return new MessagePortArray; | 261 return new MessagePortArray; |
260 | 262 |
261 MessagePortArray* portArray = new MessagePortArray(channels->size()); | 263 MessagePortArray* portArray = new MessagePortArray(channels->size()); |
262 for (unsigned i = 0; i < channels->size(); ++i) { | 264 for (unsigned i = 0; i < channels->size(); ++i) { |
263 MessagePort* port = MessagePort::create(context); | 265 MessagePort* port = MessagePort::create(context); |
264 port->entangle(std::move((*channels)[i])); | 266 port->entangle(std::move((*channels)[i])); |
265 (*portArray)[i] = port; | 267 (*portArray)[i] = port; |
266 } | 268 } |
267 return portArray; | 269 return portArray; |
268 } | 270 } |
269 | 271 |
270 DEFINE_TRACE(MessagePort) | 272 DEFINE_TRACE(MessagePort) |
271 { | 273 { |
272 ActiveDOMObject::trace(visitor); | 274 ActiveDOMObject::trace(visitor); |
273 EventTargetWithInlineData::trace(visitor); | 275 EventTargetWithInlineData::trace(visitor); |
274 } | 276 } |
275 | 277 |
276 } // namespace blink | 278 } // namespace blink |
OLD | NEW |