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 |