| 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 12 matching lines...) Expand all Loading... |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "modules/websockets/WorkerWebSocketChannel.h" | 31 #include "modules/websockets/WorkerWebSocketChannel.h" |
| 32 | 32 |
| 33 #include <memory> |
| 33 #include "core/dom/DOMArrayBuffer.h" | 34 #include "core/dom/DOMArrayBuffer.h" |
| 34 #include "core/dom/Document.h" | 35 #include "core/dom/Document.h" |
| 35 #include "core/dom/ExecutionContext.h" | 36 #include "core/dom/ExecutionContext.h" |
| 36 #include "core/dom/ExecutionContextTask.h" | |
| 37 #include "core/fileapi/Blob.h" | 37 #include "core/fileapi/Blob.h" |
| 38 #include "core/workers/WorkerGlobalScope.h" | 38 #include "core/workers/WorkerGlobalScope.h" |
| 39 #include "core/workers/WorkerLoaderProxy.h" | 39 #include "core/workers/WorkerLoaderProxy.h" |
| 40 #include "core/workers/WorkerThread.h" | 40 #include "core/workers/WorkerThread.h" |
| 41 #include "modules/websockets/DocumentWebSocketChannel.h" | 41 #include "modules/websockets/DocumentWebSocketChannel.h" |
| 42 #include "platform/CrossThreadFunctional.h" |
| 42 #include "platform/WaitableEvent.h" | 43 #include "platform/WaitableEvent.h" |
| 43 #include "platform/heap/SafePoint.h" | 44 #include "platform/heap/SafePoint.h" |
| 44 #include "public/platform/Platform.h" | 45 #include "public/platform/Platform.h" |
| 45 #include "wtf/Assertions.h" | 46 #include "wtf/Assertions.h" |
| 46 #include "wtf/Functional.h" | 47 #include "wtf/Functional.h" |
| 47 #include "wtf/PtrUtil.h" | 48 #include "wtf/PtrUtil.h" |
| 48 #include "wtf/text/CString.h" | 49 #include "wtf/text/CString.h" |
| 49 #include "wtf/text/WTFString.h" | 50 #include "wtf/text/WTFString.h" |
| 50 #include <memory> | |
| 51 | 51 |
| 52 namespace blink { | 52 namespace blink { |
| 53 | 53 |
| 54 typedef WorkerWebSocketChannel::Bridge Bridge; | 54 typedef WorkerWebSocketChannel::Bridge Bridge; |
| 55 typedef WorkerWebSocketChannel::Peer Peer; | 55 typedef WorkerWebSocketChannel::Peer Peer; |
| 56 | 56 |
| 57 // Created and destroyed on the worker thread. All setters of this class are | 57 // 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 | 58 // called on the main thread, while all getters are called on the worker |
| 59 // thread. signalWorkerThread() must be called before any getters are called. | 59 // thread. signalWorkerThread() must be called before any getters are called. |
| 60 class WebSocketChannelSyncHelper { | 60 class WebSocketChannelSyncHelper { |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 : m_client(client), | 357 : m_client(client), |
| 358 m_workerGlobalScope(workerGlobalScope), | 358 m_workerGlobalScope(workerGlobalScope), |
| 359 m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) {} | 359 m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) {} |
| 360 | 360 |
| 361 Bridge::~Bridge() { | 361 Bridge::~Bridge() { |
| 362 DCHECK(!m_peer); | 362 DCHECK(!m_peer); |
| 363 } | 363 } |
| 364 | 364 |
| 365 void Bridge::connectOnMainThread( | 365 void Bridge::connectOnMainThread( |
| 366 std::unique_ptr<SourceLocation> location, | 366 std::unique_ptr<SourceLocation> location, |
| 367 RefPtr<WorkerLoaderProxy> loaderProxy, |
| 367 WorkerThreadLifecycleContext* workerThreadLifecycleContext, | 368 WorkerThreadLifecycleContext* workerThreadLifecycleContext, |
| 368 const KURL& url, | 369 const KURL& url, |
| 369 const String& protocol, | 370 const String& protocol, |
| 370 WebSocketChannelSyncHelper* syncHelper, | 371 WebSocketChannelSyncHelper* syncHelper) { |
| 371 ExecutionContext* context) { | |
| 372 DCHECK(isMainThread()); | 372 DCHECK(isMainThread()); |
| 373 DCHECK(!m_peer); | 373 DCHECK(!m_peer); |
| 374 ExecutionContext* loaderContext = loaderProxy->getLoaderExecutionContext(); |
| 375 if (!loaderContext) |
| 376 return; |
| 374 Peer* peer = new Peer(this, m_loaderProxy, workerThreadLifecycleContext); | 377 Peer* peer = new Peer(this, m_loaderProxy, workerThreadLifecycleContext); |
| 375 if (peer->initialize(std::move(location), context)) { | 378 if (peer->initialize(std::move(location), loaderContext)) { |
| 376 m_peer = peer; | 379 m_peer = peer; |
| 377 syncHelper->setConnectRequestResult(m_peer->connect(url, protocol)); | 380 syncHelper->setConnectRequestResult(m_peer->connect(url, protocol)); |
| 378 } | 381 } |
| 379 syncHelper->signalWorkerThread(); | 382 syncHelper->signalWorkerThread(); |
| 380 } | 383 } |
| 381 | 384 |
| 382 bool Bridge::connect(std::unique_ptr<SourceLocation> location, | 385 bool Bridge::connect(std::unique_ptr<SourceLocation> location, |
| 383 const KURL& url, | 386 const KURL& url, |
| 384 const String& protocol) { | 387 const String& protocol) { |
| 385 // Wait for completion of the task on the main thread because the mixed | 388 // Wait for completion of the task on the main thread because the mixed |
| 386 // content check must synchronously be conducted. | 389 // content check must synchronously be conducted. |
| 387 WebSocketChannelSyncHelper syncHelper; | 390 WebSocketChannelSyncHelper syncHelper; |
| 388 m_loaderProxy->postTaskToLoader( | 391 m_loaderProxy->postTaskToLoader( |
| 389 BLINK_FROM_HERE, | 392 BLINK_FROM_HERE, |
| 390 createCrossThreadTask( | 393 crossThreadBind( |
| 391 &Bridge::connectOnMainThread, wrapCrossThreadPersistent(this), | 394 &Bridge::connectOnMainThread, wrapCrossThreadPersistent(this), |
| 392 WTF::passed(location->clone()), | 395 WTF::passed(location->clone()), m_loaderProxy, |
| 393 wrapCrossThreadPersistent( | 396 wrapCrossThreadPersistent( |
| 394 m_workerGlobalScope->thread()->getWorkerThreadLifecycleContext()), | 397 m_workerGlobalScope->thread()->getWorkerThreadLifecycleContext()), |
| 395 url, protocol, crossThreadUnretained(&syncHelper))); | 398 url, protocol, crossThreadUnretained(&syncHelper))); |
| 396 syncHelper.wait(); | 399 syncHelper.wait(); |
| 397 return syncHelper.connectRequestResult(); | 400 return syncHelper.connectRequestResult(); |
| 398 } | 401 } |
| 399 | 402 |
| 400 void Bridge::send(const CString& message) { | 403 void Bridge::send(const CString& message) { |
| 401 DCHECK(m_peer); | 404 DCHECK(m_peer); |
| 402 std::unique_ptr<Vector<char>> data = | 405 std::unique_ptr<Vector<char>> data = |
| 403 WTF::wrapUnique(new Vector<char>(message.length())); | 406 WTF::wrapUnique(new Vector<char>(message.length())); |
| 404 if (message.length()) | 407 if (message.length()) |
| 405 memcpy(data->data(), static_cast<const char*>(message.data()), | 408 memcpy(data->data(), static_cast<const char*>(message.data()), |
| 406 message.length()); | 409 message.length()); |
| 407 | 410 |
| 408 m_loaderProxy->postTaskToLoader( | 411 m_loaderProxy->postTaskToLoader( |
| 409 BLINK_FROM_HERE, | 412 BLINK_FROM_HERE, |
| 410 createCrossThreadTask(&Peer::sendTextAsCharVector, m_peer, | 413 crossThreadBind(&Peer::sendTextAsCharVector, m_peer, |
| 411 WTF::passed(std::move(data)))); | 414 WTF::passed(std::move(data)))); |
| 412 } | 415 } |
| 413 | 416 |
| 414 void Bridge::send(const DOMArrayBuffer& binaryData, | 417 void Bridge::send(const DOMArrayBuffer& binaryData, |
| 415 unsigned byteOffset, | 418 unsigned byteOffset, |
| 416 unsigned byteLength) { | 419 unsigned byteLength) { |
| 417 DCHECK(m_peer); | 420 DCHECK(m_peer); |
| 418 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied | 421 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied |
| 419 // into Vector<char>. | 422 // into Vector<char>. |
| 420 std::unique_ptr<Vector<char>> data = | 423 std::unique_ptr<Vector<char>> data = |
| 421 WTF::makeUnique<Vector<char>>(byteLength); | 424 WTF::makeUnique<Vector<char>>(byteLength); |
| 422 if (binaryData.byteLength()) | 425 if (binaryData.byteLength()) |
| 423 memcpy(data->data(), | 426 memcpy(data->data(), |
| 424 static_cast<const char*>(binaryData.data()) + byteOffset, | 427 static_cast<const char*>(binaryData.data()) + byteOffset, |
| 425 byteLength); | 428 byteLength); |
| 426 | 429 |
| 427 m_loaderProxy->postTaskToLoader( | 430 m_loaderProxy->postTaskToLoader( |
| 428 BLINK_FROM_HERE, | 431 BLINK_FROM_HERE, |
| 429 createCrossThreadTask(&Peer::sendBinaryAsCharVector, m_peer, | 432 crossThreadBind(&Peer::sendBinaryAsCharVector, m_peer, |
| 430 WTF::passed(std::move(data)))); | 433 WTF::passed(std::move(data)))); |
| 431 } | 434 } |
| 432 | 435 |
| 433 void Bridge::send(PassRefPtr<BlobDataHandle> data) { | 436 void Bridge::send(PassRefPtr<BlobDataHandle> data) { |
| 434 DCHECK(m_peer); | 437 DCHECK(m_peer); |
| 435 m_loaderProxy->postTaskToLoader( | 438 m_loaderProxy->postTaskToLoader( |
| 436 BLINK_FROM_HERE, | 439 BLINK_FROM_HERE, |
| 437 createCrossThreadTask(&Peer::sendBlob, m_peer, std::move(data))); | 440 crossThreadBind(&Peer::sendBlob, m_peer, std::move(data))); |
| 438 } | 441 } |
| 439 | 442 |
| 440 void Bridge::close(int code, const String& reason) { | 443 void Bridge::close(int code, const String& reason) { |
| 441 DCHECK(m_peer); | 444 DCHECK(m_peer); |
| 442 m_loaderProxy->postTaskToLoader( | 445 m_loaderProxy->postTaskToLoader( |
| 443 BLINK_FROM_HERE, | 446 BLINK_FROM_HERE, crossThreadBind(&Peer::close, m_peer, code, reason)); |
| 444 createCrossThreadTask(&Peer::close, m_peer, code, reason)); | |
| 445 } | 447 } |
| 446 | 448 |
| 447 void Bridge::fail(const String& reason, | 449 void Bridge::fail(const String& reason, |
| 448 MessageLevel level, | 450 MessageLevel level, |
| 449 std::unique_ptr<SourceLocation> location) { | 451 std::unique_ptr<SourceLocation> location) { |
| 450 DCHECK(m_peer); | 452 DCHECK(m_peer); |
| 451 m_loaderProxy->postTaskToLoader( | 453 m_loaderProxy->postTaskToLoader( |
| 452 BLINK_FROM_HERE, createCrossThreadTask(&Peer::fail, m_peer, reason, level, | 454 BLINK_FROM_HERE, |
| 453 WTF::passed(location->clone()))); | 455 crossThreadBind(&Peer::fail, m_peer, reason, level, |
| 456 WTF::passed(location->clone()))); |
| 454 } | 457 } |
| 455 | 458 |
| 456 void Bridge::disconnect() { | 459 void Bridge::disconnect() { |
| 457 if (!m_peer) | 460 if (!m_peer) |
| 458 return; | 461 return; |
| 459 | 462 |
| 460 m_loaderProxy->postTaskToLoader( | 463 m_loaderProxy->postTaskToLoader(BLINK_FROM_HERE, |
| 461 BLINK_FROM_HERE, createCrossThreadTask(&Peer::disconnect, m_peer)); | 464 crossThreadBind(&Peer::disconnect, m_peer)); |
| 462 | 465 |
| 463 m_client = nullptr; | 466 m_client = nullptr; |
| 464 m_peer = nullptr; | 467 m_peer = nullptr; |
| 465 m_workerGlobalScope.clear(); | 468 m_workerGlobalScope.clear(); |
| 466 } | 469 } |
| 467 | 470 |
| 468 DEFINE_TRACE(Bridge) { | 471 DEFINE_TRACE(Bridge) { |
| 469 visitor->trace(m_client); | 472 visitor->trace(m_client); |
| 470 visitor->trace(m_workerGlobalScope); | 473 visitor->trace(m_workerGlobalScope); |
| 471 } | 474 } |
| 472 | 475 |
| 473 } // namespace blink | 476 } // namespace blink |
| OLD | NEW |