OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #include "platform/RuntimeEnabledFeatures.h" | 47 #include "platform/RuntimeEnabledFeatures.h" |
48 #include "public/platform/Platform.h" | 48 #include "public/platform/Platform.h" |
49 #include "public/platform/WebWaitableEvent.h" | 49 #include "public/platform/WebWaitableEvent.h" |
50 #include "wtf/ArrayBuffer.h" | 50 #include "wtf/ArrayBuffer.h" |
51 #include "wtf/Assertions.h" | 51 #include "wtf/Assertions.h" |
52 #include "wtf/Functional.h" | 52 #include "wtf/Functional.h" |
53 #include "wtf/MainThread.h" | 53 #include "wtf/MainThread.h" |
54 | 54 |
55 namespace blink { | 55 namespace blink { |
56 | 56 |
| 57 typedef WorkerThreadableWebSocketChannel::Bridge Bridge; |
| 58 typedef WorkerThreadableWebSocketChannel::Peer Peer; |
| 59 |
57 // Created and destroyed on the worker thread. All setters of this class are | 60 // Created and destroyed on the worker thread. All setters of this class are |
58 // called on the main thread, while all getters are called on the worker | 61 // called on the main thread, while all getters are called on the worker |
59 // thread. signalWorkerThread() must be called before any getters are called. | 62 // thread. signalWorkerThread() must be called before any getters are called. |
60 class ThreadableWebSocketChannelSyncHelper : public ThreadSafeRefCountedWillBeGa
rbageCollectedFinalized<ThreadableWebSocketChannelSyncHelper> { | 63 class ThreadableWebSocketChannelSyncHelper : public ThreadSafeRefCountedWillBeGa
rbageCollectedFinalized<ThreadableWebSocketChannelSyncHelper> { |
61 public: | 64 public: |
62 static PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelSyncHelper> create(P
assOwnPtr<blink::WebWaitableEvent> event) | 65 static PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelSyncHelper> create(P
assOwnPtr<blink::WebWaitableEvent> event) |
63 { | 66 { |
64 return adoptRefWillBeNoop(new ThreadableWebSocketChannelSyncHelper(event
)); | 67 return adoptRefWillBeNoop(new ThreadableWebSocketChannelSyncHelper(event
)); |
65 } | 68 } |
66 | 69 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 195 } |
193 | 196 |
194 void WorkerThreadableWebSocketChannel::trace(Visitor* visitor) | 197 void WorkerThreadableWebSocketChannel::trace(Visitor* visitor) |
195 { | 198 { |
196 visitor->trace(m_bridge); | 199 visitor->trace(m_bridge); |
197 visitor->trace(m_workerClientWrapper); | 200 visitor->trace(m_workerClientWrapper); |
198 WebSocketChannel::trace(visitor); | 201 WebSocketChannel::trace(visitor); |
199 } | 202 } |
200 | 203 |
201 #if ENABLE(OILPAN) | 204 #if ENABLE(OILPAN) |
202 WorkerThreadableWebSocketChannel::Peer::Peer(RawPtr<ThreadableWebSocketChannelCl
ientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ExecutionContext* co
ntext, const String& sourceURL, unsigned lineNumber, RawPtr<ThreadableWebSocketC
hannelSyncHelper> syncHelper) | 205 Peer::Peer(RawPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, Worker
LoaderProxy& loaderProxy, ExecutionContext* context, const String& sourceURL, un
signed lineNumber, RawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) |
203 #else | 206 #else |
204 WorkerThreadableWebSocketChannel::Peer::Peer(PassRefPtr<WeakReference<Peer> > re
ference, PassRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, Work
erLoaderProxy& loaderProxy, ExecutionContext* context, const String& sourceURL,
unsigned lineNumber, PassRefPtr<ThreadableWebSocketChannelSyncHelper> syncHelper
) | 207 Peer::Peer(PassRefPtr<WeakReference<Peer> > reference, PassRefPtr<ThreadableWebS
ocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, Execut
ionContext* context, const String& sourceURL, unsigned lineNumber, PassRefPtr<Th
readableWebSocketChannelSyncHelper> syncHelper) |
205 #endif | 208 #endif |
206 : m_workerClientWrapper(clientWrapper) | 209 : m_workerClientWrapper(clientWrapper) |
207 , m_loaderProxy(loaderProxy) | 210 , m_loaderProxy(loaderProxy) |
208 , m_mainWebSocketChannel(nullptr) | 211 , m_mainWebSocketChannel(nullptr) |
209 , m_syncHelper(syncHelper) | 212 , m_syncHelper(syncHelper) |
210 #if ENABLE(OILPAN) | 213 #if ENABLE(OILPAN) |
211 , m_keepAlive(this) | 214 , m_keepAlive(this) |
212 #else | 215 #else |
213 , m_weakFactory(reference, this) | 216 , m_weakFactory(reference, this) |
214 #endif | 217 #endif |
215 { | 218 { |
216 ASSERT(isMainThread()); | 219 ASSERT(isMainThread()); |
217 ASSERT(m_workerClientWrapper.get()); | 220 ASSERT(m_workerClientWrapper.get()); |
218 | 221 |
219 Document* document = toDocument(context); | 222 Document* document = toDocument(context); |
220 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) { | 223 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) { |
221 m_mainWebSocketChannel = NewWebSocketChannelImpl::create(document, this,
sourceURL, lineNumber); | 224 m_mainWebSocketChannel = NewWebSocketChannelImpl::create(document, this,
sourceURL, lineNumber); |
222 } else { | 225 } else { |
223 m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, th
is, sourceURL, lineNumber); | 226 m_mainWebSocketChannel = MainThreadWebSocketChannel::create(document, th
is, sourceURL, lineNumber); |
224 } | 227 } |
225 } | 228 } |
226 | 229 |
227 WorkerThreadableWebSocketChannel::Peer::~Peer() | 230 Peer::~Peer() |
228 { | 231 { |
229 ASSERT(isMainThread()); | 232 ASSERT(isMainThread()); |
230 } | 233 } |
231 | 234 |
232 #if ENABLE(OILPAN) | 235 #if ENABLE(OILPAN) |
233 void WorkerThreadableWebSocketChannel::Peer::initialize(ExecutionContext* contex
t, WeakMember<Peer>* reference, WorkerLoaderProxy* loaderProxy, RawPtr<Threadabl
eWebSocketChannelClientWrapper> clientWrapper, const String& sourceURLAtConnecti
on, unsigned lineNumberAtConnection, RawPtr<ThreadableWebSocketChannelSyncHelper
> syncHelper) | 236 void Peer::initialize(ExecutionContext* context, WeakMember<Peer>* reference, Wo
rkerLoaderProxy* loaderProxy, RawPtr<ThreadableWebSocketChannelClientWrapper> cl
ientWrapper, const String& sourceURLAtConnection, unsigned lineNumberAtConnectio
n, RawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) |
234 { | 237 { |
235 // The caller must call destroy() to free the peer. | 238 // The caller must call destroy() to free the peer. |
236 *reference = new Peer(clientWrapper, *loaderProxy, context, sourceURLAtConne
ction, lineNumberAtConnection, syncHelper); | 239 *reference = new Peer(clientWrapper, *loaderProxy, context, sourceURLAtConne
ction, lineNumberAtConnection, syncHelper); |
237 syncHelper->signalWorkerThread(); | 240 syncHelper->signalWorkerThread(); |
238 } | 241 } |
239 #else | 242 #else |
240 void WorkerThreadableWebSocketChannel::Peer::initialize(ExecutionContext* contex
t, PassRefPtr<WeakReference<Peer> > reference, WorkerLoaderProxy* loaderProxy, P
assRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, const String&
sourceURLAtConnection, unsigned lineNumberAtConnection, PassRefPtr<ThreadableWeb
SocketChannelSyncHelper> prpSyncHelper) | 243 void Peer::initialize(ExecutionContext* context, PassRefPtr<WeakReference<Peer>
> reference, WorkerLoaderProxy* loaderProxy, PassRefPtr<ThreadableWebSocketChann
elClientWrapper> clientWrapper, const String& sourceURLAtConnection, unsigned li
neNumberAtConnection, PassRefPtr<ThreadableWebSocketChannelSyncHelper> prpSyncHe
lper) |
241 { | 244 { |
242 RefPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = prpSyncHelper; | 245 RefPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = prpSyncHelper; |
243 // The caller must call destroy() to free the peer. | 246 // The caller must call destroy() to free the peer. |
244 new Peer(reference, clientWrapper, *loaderProxy, context, sourceURLAtConnect
ion, lineNumberAtConnection, syncHelper); | 247 new Peer(reference, clientWrapper, *loaderProxy, context, sourceURLAtConnect
ion, lineNumberAtConnection, syncHelper); |
245 syncHelper->signalWorkerThread(); | 248 syncHelper->signalWorkerThread(); |
246 } | 249 } |
247 #endif | 250 #endif |
248 | 251 |
249 void WorkerThreadableWebSocketChannel::Peer::destroy() | 252 void Peer::destroy() |
250 { | 253 { |
251 ASSERT(isMainThread()); | 254 ASSERT(isMainThread()); |
252 disconnect(); | 255 disconnect(); |
253 | 256 |
254 #if ENABLE(OILPAN) | 257 #if ENABLE(OILPAN) |
255 m_keepAlive = nullptr; | 258 m_keepAlive = nullptr; |
256 m_syncHelper->signalWorkerThread(); | 259 m_syncHelper->signalWorkerThread(); |
257 m_syncHelper = nullptr; | 260 m_syncHelper = nullptr; |
258 #else | 261 #else |
259 delete this; | 262 delete this; |
260 #endif | 263 #endif |
261 } | 264 } |
262 | 265 |
263 void WorkerThreadableWebSocketChannel::Peer::connect(const KURL& url, const Stri
ng& protocol) | 266 void Peer::connect(const KURL& url, const String& protocol) |
264 { | 267 { |
265 ASSERT(isMainThread()); | 268 ASSERT(isMainThread()); |
266 ASSERT(m_syncHelper); | 269 ASSERT(m_syncHelper); |
267 if (!m_mainWebSocketChannel) { | 270 if (!m_mainWebSocketChannel) { |
268 m_syncHelper->setConnectRequestResult(false); | 271 m_syncHelper->setConnectRequestResult(false); |
269 } else { | 272 } else { |
270 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco
l); | 273 bool connectRequestResult = m_mainWebSocketChannel->connect(url, protoco
l); |
271 m_syncHelper->setConnectRequestResult(connectRequestResult); | 274 m_syncHelper->setConnectRequestResult(connectRequestResult); |
272 } | 275 } |
273 m_syncHelper->signalWorkerThread(); | 276 m_syncHelper->signalWorkerThread(); |
274 } | 277 } |
275 | 278 |
276 void WorkerThreadableWebSocketChannel::Peer::send(const String& message) | 279 void Peer::send(const String& message) |
277 { | 280 { |
278 ASSERT(isMainThread()); | 281 ASSERT(isMainThread()); |
279 ASSERT(m_syncHelper); | 282 ASSERT(m_syncHelper); |
280 if (!m_mainWebSocketChannel) { | 283 if (!m_mainWebSocketChannel) { |
281 m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); | 284 m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); |
282 } else { | 285 } else { |
283 WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel-
>send(message); | 286 WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel-
>send(message); |
284 m_syncHelper->setSendRequestResult(sendRequestResult); | 287 m_syncHelper->setSendRequestResult(sendRequestResult); |
285 } | 288 } |
286 m_syncHelper->signalWorkerThread(); | 289 m_syncHelper->signalWorkerThread(); |
287 } | 290 } |
288 | 291 |
289 void WorkerThreadableWebSocketChannel::Peer::sendArrayBuffer(PassOwnPtr<Vector<c
har> > data) | 292 void Peer::sendArrayBuffer(PassOwnPtr<Vector<char> > data) |
290 { | 293 { |
291 ASSERT(isMainThread()); | 294 ASSERT(isMainThread()); |
292 ASSERT(m_syncHelper); | 295 ASSERT(m_syncHelper); |
293 if (!m_mainWebSocketChannel) { | 296 if (!m_mainWebSocketChannel) { |
294 m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); | 297 m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); |
295 } else { | 298 } else { |
296 WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel-
>send(data); | 299 WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel-
>send(data); |
297 m_syncHelper->setSendRequestResult(sendRequestResult); | 300 m_syncHelper->setSendRequestResult(sendRequestResult); |
298 } | 301 } |
299 m_syncHelper->signalWorkerThread(); | 302 m_syncHelper->signalWorkerThread(); |
300 } | 303 } |
301 | 304 |
302 void WorkerThreadableWebSocketChannel::Peer::sendBlob(PassRefPtr<BlobDataHandle>
blobData) | 305 void Peer::sendBlob(PassRefPtr<BlobDataHandle> blobData) |
303 { | 306 { |
304 ASSERT(isMainThread()); | 307 ASSERT(isMainThread()); |
305 ASSERT(m_syncHelper); | 308 ASSERT(m_syncHelper); |
306 if (!m_mainWebSocketChannel) { | 309 if (!m_mainWebSocketChannel) { |
307 m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); | 310 m_syncHelper->setSendRequestResult(WebSocketChannel::SendFail); |
308 } else { | 311 } else { |
309 WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel-
>send(blobData); | 312 WebSocketChannel::SendResult sendRequestResult = m_mainWebSocketChannel-
>send(blobData); |
310 m_syncHelper->setSendRequestResult(sendRequestResult); | 313 m_syncHelper->setSendRequestResult(sendRequestResult); |
311 } | 314 } |
312 m_syncHelper->signalWorkerThread(); | 315 m_syncHelper->signalWorkerThread(); |
313 } | 316 } |
314 | 317 |
315 void WorkerThreadableWebSocketChannel::Peer::close(int code, const String& reaso
n) | 318 void Peer::close(int code, const String& reason) |
316 { | 319 { |
317 ASSERT(isMainThread()); | 320 ASSERT(isMainThread()); |
318 ASSERT(m_syncHelper); | 321 ASSERT(m_syncHelper); |
319 if (!m_mainWebSocketChannel) | 322 if (!m_mainWebSocketChannel) |
320 return; | 323 return; |
321 m_mainWebSocketChannel->close(code, reason); | 324 m_mainWebSocketChannel->close(code, reason); |
322 } | 325 } |
323 | 326 |
324 void WorkerThreadableWebSocketChannel::Peer::fail(const String& reason, MessageL
evel level, const String& sourceURL, unsigned lineNumber) | 327 void Peer::fail(const String& reason, MessageLevel level, const String& sourceUR
L, unsigned lineNumber) |
325 { | 328 { |
326 ASSERT(isMainThread()); | 329 ASSERT(isMainThread()); |
327 ASSERT(m_syncHelper); | 330 ASSERT(m_syncHelper); |
328 if (!m_mainWebSocketChannel) | 331 if (!m_mainWebSocketChannel) |
329 return; | 332 return; |
330 m_mainWebSocketChannel->fail(reason, level, sourceURL, lineNumber); | 333 m_mainWebSocketChannel->fail(reason, level, sourceURL, lineNumber); |
331 } | 334 } |
332 | 335 |
333 void WorkerThreadableWebSocketChannel::Peer::disconnect() | 336 void Peer::disconnect() |
334 { | 337 { |
335 ASSERT(isMainThread()); | 338 ASSERT(isMainThread()); |
336 ASSERT(m_syncHelper); | 339 ASSERT(m_syncHelper); |
337 if (!m_mainWebSocketChannel) | 340 if (!m_mainWebSocketChannel) |
338 return; | 341 return; |
339 m_mainWebSocketChannel->disconnect(); | 342 m_mainWebSocketChannel->disconnect(); |
340 m_mainWebSocketChannel = nullptr; | 343 m_mainWebSocketChannel = nullptr; |
341 } | 344 } |
342 | 345 |
343 static void workerGlobalScopeDidConnect(ExecutionContext* context, PassRefPtrWil
lBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const St
ring& subprotocol, const String& extensions) | 346 static void workerGlobalScopeDidConnect(ExecutionContext* context, PassRefPtrWil
lBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, const St
ring& subprotocol, const String& extensions) |
344 { | 347 { |
345 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 348 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
346 workerClientWrapper->didConnect(subprotocol, extensions); | 349 workerClientWrapper->didConnect(subprotocol, extensions); |
347 } | 350 } |
348 | 351 |
349 void WorkerThreadableWebSocketChannel::Peer::didConnect(const String& subprotoco
l, const String& extensions) | 352 void Peer::didConnect(const String& subprotocol, const String& extensions) |
350 { | 353 { |
351 ASSERT(isMainThread()); | 354 ASSERT(isMainThread()); |
352 // It is important to seprate task creation from posting | 355 // It is important to seprate task creation from posting |
353 // the task. See the above comment. | 356 // the task. See the above comment. |
354 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConnect, m_workerClientWrapper.get(), subprotocol, extensions); | 357 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConnect, m_workerClientWrapper.get(), subprotocol, extensions); |
355 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 358 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
356 } | 359 } |
357 | 360 |
358 static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRe
fPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, c
onst String& message) | 361 static void workerGlobalScopeDidReceiveMessage(ExecutionContext* context, PassRe
fPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, c
onst String& message) |
359 { | 362 { |
360 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 363 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
361 workerClientWrapper->didReceiveMessage(message); | 364 workerClientWrapper->didReceiveMessage(message); |
362 } | 365 } |
363 | 366 |
364 void WorkerThreadableWebSocketChannel::Peer::didReceiveMessage(const String& mes
sage) | 367 void Peer::didReceiveMessage(const String& message) |
365 { | 368 { |
366 ASSERT(isMainThread()); | 369 ASSERT(isMainThread()); |
367 // It is important to seprate task creation from posting | 370 // It is important to seprate task creation from posting |
368 // the task. See the above comment. | 371 // the task. See the above comment. |
369 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessage, m_workerClientWrapper.get(), message); | 372 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessage, m_workerClientWrapper.get(), message); |
370 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 373 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
371 } | 374 } |
372 | 375 |
373 static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, Pas
sRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper
, PassOwnPtr<Vector<char> > binaryData) | 376 static void workerGlobalScopeDidReceiveBinaryData(ExecutionContext* context, Pas
sRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper
, PassOwnPtr<Vector<char> > binaryData) |
374 { | 377 { |
375 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 378 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
376 workerClientWrapper->didReceiveBinaryData(binaryData); | 379 workerClientWrapper->didReceiveBinaryData(binaryData); |
377 } | 380 } |
378 | 381 |
379 void WorkerThreadableWebSocketChannel::Peer::didReceiveBinaryData(PassOwnPtr<Vec
tor<char> > binaryData) | 382 void Peer::didReceiveBinaryData(PassOwnPtr<Vector<char> > binaryData) |
380 { | 383 { |
381 ASSERT(isMainThread()); | 384 ASSERT(isMainThread()); |
382 // It is important to seprate task creation from posting | 385 // It is important to seprate task creation from posting |
383 // the task. See the above comment. | 386 // the task. See the above comment. |
384 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveBinaryData, m_workerClientWrapper.get(), binaryData); | 387 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveBinaryData, m_workerClientWrapper.get(), binaryData); |
385 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 388 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
386 } | 389 } |
387 | 390 |
388 static void workerGlobalScopeDidConsumeBufferedAmount(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper, unsigned long consumed) | 391 static void workerGlobalScopeDidConsumeBufferedAmount(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper, unsigned long consumed) |
389 { | 392 { |
390 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 393 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
391 workerClientWrapper->didConsumeBufferedAmount(consumed); | 394 workerClientWrapper->didConsumeBufferedAmount(consumed); |
392 } | 395 } |
393 | 396 |
394 void WorkerThreadableWebSocketChannel::Peer::didConsumeBufferedAmount(unsigned l
ong consumed) | 397 void Peer::didConsumeBufferedAmount(unsigned long consumed) |
395 { | 398 { |
396 ASSERT(isMainThread()); | 399 ASSERT(isMainThread()); |
397 // It is important to seprate task creation from posting | 400 // It is important to seprate task creation from posting |
398 // the task. See the above comment. | 401 // the task. See the above comment. |
399 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConsumeBufferedAmount, m_workerClientWrapper.get(), consumed); | 402 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidConsumeBufferedAmount, m_workerClientWrapper.get(), consumed); |
400 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 403 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
401 } | 404 } |
402 | 405 |
403 static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper) | 406 static void workerGlobalScopeDidStartClosingHandshake(ExecutionContext* context,
PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWra
pper) |
404 { | 407 { |
405 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 408 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
406 workerClientWrapper->didStartClosingHandshake(); | 409 workerClientWrapper->didStartClosingHandshake(); |
407 } | 410 } |
408 | 411 |
409 void WorkerThreadableWebSocketChannel::Peer::didStartClosingHandshake() | 412 void Peer::didStartClosingHandshake() |
410 { | 413 { |
411 ASSERT(isMainThread()); | 414 ASSERT(isMainThread()); |
412 // It is important to seprate task creation from posting | 415 // It is important to seprate task creation from posting |
413 // the task. See the above comment. | 416 // the task. See the above comment. |
414 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidStartClosingHandshake, m_workerClientWrapper.get()); | 417 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidStartClosingHandshake, m_workerClientWrapper.get()); |
415 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 418 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
416 } | 419 } |
417 | 420 |
418 static void workerGlobalScopeDidClose(ExecutionContext* context, PassRefPtrWillB
eRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WebSocketC
hannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsig
ned short code, const String& reason) | 421 static void workerGlobalScopeDidClose(ExecutionContext* context, PassRefPtrWillB
eRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WebSocketC
hannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsig
ned short code, const String& reason) |
419 { | 422 { |
420 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 423 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
421 workerClientWrapper->didClose(closingHandshakeCompletion, code, reason); | 424 workerClientWrapper->didClose(closingHandshakeCompletion, code, reason); |
422 } | 425 } |
423 | 426 |
424 void WorkerThreadableWebSocketChannel::Peer::didClose(ClosingHandshakeCompletion
Status closingHandshakeCompletion, unsigned short code, const String& reason) | 427 void Peer::didClose(ClosingHandshakeCompletionStatus closingHandshakeCompletion,
unsigned short code, const String& reason) |
425 { | 428 { |
426 ASSERT(isMainThread()); | 429 ASSERT(isMainThread()); |
427 m_mainWebSocketChannel = nullptr; | 430 m_mainWebSocketChannel = nullptr; |
428 // It is important to seprate task creation from posting | 431 // It is important to seprate task creation from posting |
429 // the task. See the above comment. | 432 // the task. See the above comment. |
430 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidClose, m_workerClientWrapper.get(), closingHandshakeCompletion, code, reason)
; | 433 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidClose, m_workerClientWrapper.get(), closingHandshakeCompletion, code, reason)
; |
431 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 434 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
432 } | 435 } |
433 | 436 |
434 static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, P
assRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapp
er) | 437 static void workerGlobalScopeDidReceiveMessageError(ExecutionContext* context, P
assRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapp
er) |
435 { | 438 { |
436 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 439 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
437 workerClientWrapper->didReceiveMessageError(); | 440 workerClientWrapper->didReceiveMessageError(); |
438 } | 441 } |
439 | 442 |
440 void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError() | 443 void Peer::didReceiveMessageError() |
441 { | 444 { |
442 ASSERT(isMainThread()); | 445 ASSERT(isMainThread()); |
443 // It is important to seprate task creation from posting | 446 // It is important to seprate task creation from posting |
444 // the task. See the above comment. | 447 // the task. See the above comment. |
445 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessageError, m_workerClientWrapper.get()); | 448 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&workerGlobalScope
DidReceiveMessageError, m_workerClientWrapper.get()); |
446 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); | 449 m_loaderProxy.postTaskToWorkerGlobalScope(task.release()); |
447 } | 450 } |
448 | 451 |
449 void WorkerThreadableWebSocketChannel::Peer::trace(Visitor* visitor) | 452 void Peer::trace(Visitor* visitor) |
450 { | 453 { |
451 visitor->trace(m_workerClientWrapper); | 454 visitor->trace(m_workerClientWrapper); |
452 visitor->trace(m_mainWebSocketChannel); | 455 visitor->trace(m_mainWebSocketChannel); |
453 visitor->trace(m_syncHelper); | 456 visitor->trace(m_syncHelper); |
454 WebSocketChannelClient::trace(visitor); | 457 WebSocketChannelClient::trace(visitor); |
455 } | 458 } |
456 | 459 |
457 WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtrWillBeRawPtr<Threadab
leWebSocketChannelClientWrapper> workerClientWrapper, WorkerGlobalScope& workerG
lobalScope) | 460 Bridge::Bridge(PassRefPtrWillBeRawPtr<ThreadableWebSocketChannelClientWrapper> w
orkerClientWrapper, WorkerGlobalScope& workerGlobalScope) |
458 : m_workerClientWrapper(workerClientWrapper) | 461 : m_workerClientWrapper(workerClientWrapper) |
459 , m_workerGlobalScope(workerGlobalScope) | 462 , m_workerGlobalScope(workerGlobalScope) |
460 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) | 463 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) |
461 , m_syncHelper(nullptr) | 464 , m_syncHelper(nullptr) |
462 , m_peer(nullptr) | 465 , m_peer(nullptr) |
463 { | 466 { |
464 ASSERT(m_workerClientWrapper.get()); | 467 ASSERT(m_workerClientWrapper.get()); |
465 } | 468 } |
466 | 469 |
467 WorkerThreadableWebSocketChannel::Bridge::~Bridge() | 470 Bridge::~Bridge() |
468 { | 471 { |
469 ASSERT(hasTerminatedPeer()); | 472 ASSERT(hasTerminatedPeer()); |
470 } | 473 } |
471 | 474 |
472 void WorkerThreadableWebSocketChannel::Bridge::initialize(const String& sourceUR
L, unsigned lineNumber) | 475 void Bridge::initialize(const String& sourceURL, unsigned lineNumber) |
473 { | 476 { |
474 #if !ENABLE(OILPAN) | 477 #if !ENABLE(OILPAN) |
475 RefPtr<WeakReference<Peer> > reference = WeakReference<Peer>::createUnbound(
); | 478 RefPtr<WeakReference<Peer> > reference = WeakReference<Peer>::createUnbound(
); |
476 m_peer = WeakPtr<Peer>(reference); | 479 m_peer = WeakPtr<Peer>(reference); |
477 #endif | 480 #endif |
478 | 481 |
479 RefPtrWillBeRawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = Thread
ableWebSocketChannelSyncHelper::create(adoptPtr(blink::Platform::current()->crea
teWaitableEvent())); | 482 RefPtrWillBeRawPtr<ThreadableWebSocketChannelSyncHelper> syncHelper = Thread
ableWebSocketChannelSyncHelper::create(adoptPtr(blink::Platform::current()->crea
teWaitableEvent())); |
480 // This pointer is guaranteed to be valid until we call terminatePeer. | 483 // This pointer is guaranteed to be valid until we call terminatePeer. |
481 m_syncHelper = syncHelper.get(); | 484 m_syncHelper = syncHelper.get(); |
482 | 485 |
483 RefPtrWillBeRawPtr<Bridge> protect(this); | 486 RefPtrWillBeRawPtr<Bridge> protect(this); |
484 #if ENABLE(OILPAN) | 487 #if ENABLE(OILPAN) |
485 // In order to assure all temporary objects to be destroyed before | 488 // In order to assure all temporary objects to be destroyed before |
486 // posting the task, we separate task creation and posting. | 489 // posting the task, we separate task creation and posting. |
487 // In other words, it is dangerous to have a complicated expression | 490 // In other words, it is dangerous to have a complicated expression |
488 // as a waitForMethodCompletion argument. | 491 // as a waitForMethodCompletion argument. |
489 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
&m_peer, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(), s
ourceURL, lineNumber, syncHelper.get()); | 492 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
&m_peer, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(), s
ourceURL, lineNumber, syncHelper.get()); |
490 #else | 493 #else |
491 // See the above comment. | 494 // See the above comment. |
492 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
reference, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(),
sourceURL, lineNumber, syncHelper.get()); | 495 OwnPtr<ExecutionContextTask> task = createCrossThreadTask(&Peer::initialize,
reference, AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper.get(),
sourceURL, lineNumber, syncHelper.get()); |
493 #endif | 496 #endif |
494 if (!waitForMethodCompletion(task.release())) { | 497 if (!waitForMethodCompletion(task.release())) { |
495 // The worker thread has been signalled to shutdown before method comple
tion. | 498 // The worker thread has been signalled to shutdown before method comple
tion. |
496 disconnect(); | 499 disconnect(); |
497 } | 500 } |
498 } | 501 } |
499 | 502 |
500 bool WorkerThreadableWebSocketChannel::Bridge::connect(const KURL& url, const St
ring& protocol) | 503 bool Bridge::connect(const KURL& url, const String& protocol) |
501 { | 504 { |
502 if (hasTerminatedPeer()) | 505 if (hasTerminatedPeer()) |
503 return false; | 506 return false; |
504 | 507 |
505 RefPtrWillBeRawPtr<Bridge> protect(this); | 508 RefPtrWillBeRawPtr<Bridge> protect(this); |
506 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, m_peer, u
rl, protocol))) | 509 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::connect, m_peer, u
rl, protocol))) |
507 return false; | 510 return false; |
508 | 511 |
509 return m_syncHelper->connectRequestResult(); | 512 return m_syncHelper->connectRequestResult(); |
510 } | 513 } |
511 | 514 |
512 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(cons
t String& message) | 515 WebSocketChannel::SendResult Bridge::send(const String& message) |
513 { | 516 { |
514 if (hasTerminatedPeer()) | 517 if (hasTerminatedPeer()) |
515 return WebSocketChannel::SendFail; | 518 return WebSocketChannel::SendFail; |
516 | 519 |
517 RefPtrWillBeRawPtr<Bridge> protect(this); | 520 RefPtrWillBeRawPtr<Bridge> protect(this); |
518 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::send, m_peer, mess
age))) | 521 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::send, m_peer, mess
age))) |
519 return WebSocketChannel::SendFail; | 522 return WebSocketChannel::SendFail; |
520 | 523 |
521 return m_syncHelper->sendRequestResult(); | 524 return m_syncHelper->sendRequestResult(); |
522 } | 525 } |
523 | 526 |
524 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(cons
t ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) | 527 WebSocketChannel::SendResult Bridge::send(const ArrayBuffer& binaryData, unsigne
d byteOffset, unsigned byteLength) |
525 { | 528 { |
526 if (hasTerminatedPeer()) | 529 if (hasTerminatedPeer()) |
527 return WebSocketChannel::SendFail; | 530 return WebSocketChannel::SendFail; |
528 | 531 |
529 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied
into Vector<char>. | 532 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied
into Vector<char>. |
530 OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); | 533 OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); |
531 if (binaryData.byteLength()) | 534 if (binaryData.byteLength()) |
532 memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteO
ffset, byteLength); | 535 memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteO
ffset, byteLength); |
533 | 536 |
534 RefPtrWillBeRawPtr<Bridge> protect(this); | 537 RefPtrWillBeRawPtr<Bridge> protect(this); |
535 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendArrayBuffer, m
_peer, data.release()))) | 538 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendArrayBuffer, m
_peer, data.release()))) |
536 return WebSocketChannel::SendFail; | 539 return WebSocketChannel::SendFail; |
537 | 540 |
538 return m_syncHelper->sendRequestResult(); | 541 return m_syncHelper->sendRequestResult(); |
539 } | 542 } |
540 | 543 |
541 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(Pass
RefPtr<BlobDataHandle> data) | 544 WebSocketChannel::SendResult Bridge::send(PassRefPtr<BlobDataHandle> data) |
542 { | 545 { |
543 if (hasTerminatedPeer()) | 546 if (hasTerminatedPeer()) |
544 return WebSocketChannel::SendFail; | 547 return WebSocketChannel::SendFail; |
545 | 548 |
546 RefPtrWillBeRawPtr<Bridge> protect(this); | 549 RefPtrWillBeRawPtr<Bridge> protect(this); |
547 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendBlob, m_peer,
data))) | 550 if (!waitForMethodCompletion(createCrossThreadTask(&Peer::sendBlob, m_peer,
data))) |
548 return WebSocketChannel::SendFail; | 551 return WebSocketChannel::SendFail; |
549 | 552 |
550 return m_syncHelper->sendRequestResult(); | 553 return m_syncHelper->sendRequestResult(); |
551 } | 554 } |
552 | 555 |
553 void WorkerThreadableWebSocketChannel::Bridge::close(int code, const String& rea
son) | 556 void Bridge::close(int code, const String& reason) |
554 { | 557 { |
555 if (hasTerminatedPeer()) | 558 if (hasTerminatedPeer()) |
556 return; | 559 return; |
557 | 560 |
558 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::close, m_peer, c
ode, reason)); | 561 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::close, m_peer, c
ode, reason)); |
559 } | 562 } |
560 | 563 |
561 void WorkerThreadableWebSocketChannel::Bridge::fail(const String& reason, Messag
eLevel level, const String& sourceURL, unsigned lineNumber) | 564 void Bridge::fail(const String& reason, MessageLevel level, const String& source
URL, unsigned lineNumber) |
562 { | 565 { |
563 if (hasTerminatedPeer()) | 566 if (hasTerminatedPeer()) |
564 return; | 567 return; |
565 | 568 |
566 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::fail, m_peer, re
ason, level, sourceURL, lineNumber)); | 569 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::fail, m_peer, re
ason, level, sourceURL, lineNumber)); |
567 } | 570 } |
568 | 571 |
569 void WorkerThreadableWebSocketChannel::Bridge::disconnect() | 572 void Bridge::disconnect() |
570 { | 573 { |
571 if (hasTerminatedPeer()) | 574 if (hasTerminatedPeer()) |
572 return; | 575 return; |
573 | 576 |
574 clearClientWrapper(); | 577 clearClientWrapper(); |
575 terminatePeer(); | 578 terminatePeer(); |
576 } | 579 } |
577 | 580 |
578 void WorkerThreadableWebSocketChannel::Bridge::clearClientWrapper() | 581 void Bridge::clearClientWrapper() |
579 { | 582 { |
580 m_workerClientWrapper->clearClient(); | 583 m_workerClientWrapper->clearClient(); |
581 } | 584 } |
582 | 585 |
583 // Caller of this function should hold a reference to the bridge, because this f
unction may call WebSocket::didClose() in the end, | 586 // Caller of this function should hold a reference to the bridge, because this f
unction may call WebSocket::didClose() in the end, |
584 // which causes the bridge to get disconnected from the WebSocket and deleted if
there is no other reference. | 587 // which causes the bridge to get disconnected from the WebSocket and deleted if
there is no other reference. |
585 bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion(PassOwnPt
r<ExecutionContextTask> task) | 588 bool Bridge::waitForMethodCompletion(PassOwnPtr<ExecutionContextTask> task) |
586 { | 589 { |
587 ASSERT(m_workerGlobalScope); | 590 ASSERT(m_workerGlobalScope); |
588 ASSERT(m_syncHelper); | 591 ASSERT(m_syncHelper); |
589 | 592 |
590 m_loaderProxy.postTaskToLoader(task); | 593 m_loaderProxy.postTaskToLoader(task); |
591 | 594 |
592 // We wait for the syncHelper event even if a shutdown event is fired. | 595 // We wait for the syncHelper event even if a shutdown event is fired. |
593 // See https://codereview.chromium.org/267323004/#msg43 for why we need to w
ait this. | 596 // See https://codereview.chromium.org/267323004/#msg43 for why we need to w
ait this. |
594 Vector<blink::WebWaitableEvent*> events; | 597 Vector<blink::WebWaitableEvent*> events; |
595 events.append(m_syncHelper->event()); | 598 events.append(m_syncHelper->event()); |
596 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); | 599 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); |
597 blink::Platform::current()->waitMultipleEvents(events); | 600 blink::Platform::current()->waitMultipleEvents(events); |
598 // This is checking whether a shutdown event is fired or not. | 601 // This is checking whether a shutdown event is fired or not. |
599 return !m_workerGlobalScope->thread()->terminated(); | 602 return !m_workerGlobalScope->thread()->terminated(); |
600 } | 603 } |
601 | 604 |
602 void WorkerThreadableWebSocketChannel::Bridge::terminatePeer() | 605 void Bridge::terminatePeer() |
603 { | 606 { |
604 ASSERT(!hasTerminatedPeer()); | 607 ASSERT(!hasTerminatedPeer()); |
605 | 608 |
606 #if ENABLE(OILPAN) | 609 #if ENABLE(OILPAN) |
607 // The worker thread has to wait for the main thread to complete Peer::destr
oy, | 610 // The worker thread has to wait for the main thread to complete Peer::destr
oy, |
608 // because the worker thread has to make sure that the main thread does not
have any | 611 // because the worker thread has to make sure that the main thread does not
have any |
609 // references to on-heap objects allocated in the thread heap of the worker
thread | 612 // references to on-heap objects allocated in the thread heap of the worker
thread |
610 // before the worker thread shuts down. | 613 // before the worker thread shuts down. |
611 waitForMethodCompletion(createCrossThreadTask(&Peer::destroy, m_peer)); | 614 waitForMethodCompletion(createCrossThreadTask(&Peer::destroy, m_peer)); |
612 #else | 615 #else |
613 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::destroy, m_peer)
); | 616 m_loaderProxy.postTaskToLoader(createCrossThreadTask(&Peer::destroy, m_peer)
); |
614 #endif | 617 #endif |
615 | 618 |
616 // Peer::destroy() deletes m_peer and then m_syncHelper will be released. | 619 // Peer::destroy() deletes m_peer and then m_syncHelper will be released. |
617 // We must not touch m_syncHelper any more. | 620 // We must not touch m_syncHelper any more. |
618 m_syncHelper = nullptr; | 621 m_syncHelper = nullptr; |
619 | 622 |
620 // We won't use this any more. | 623 // We won't use this any more. |
621 m_workerGlobalScope = nullptr; | 624 m_workerGlobalScope = nullptr; |
622 } | 625 } |
623 | 626 |
624 void WorkerThreadableWebSocketChannel::Bridge::trace(Visitor* visitor) | 627 void Bridge::trace(Visitor* visitor) |
625 { | 628 { |
626 visitor->trace(m_workerClientWrapper); | 629 visitor->trace(m_workerClientWrapper); |
627 visitor->trace(m_workerGlobalScope); | 630 visitor->trace(m_workerGlobalScope); |
628 visitor->trace(m_syncHelper); | 631 visitor->trace(m_syncHelper); |
629 visitor->trace(m_peer); | 632 visitor->trace(m_peer); |
630 } | 633 } |
631 | 634 |
632 } // namespace blink | 635 } // namespace blink |
OLD | NEW |