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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 , m_bufferedAmount(0) | 113 , m_bufferedAmount(0) |
114 { | 114 { |
115 } | 115 } |
116 | 116 |
117 OwnPtr<blink::WebWaitableEvent> m_event; | 117 OwnPtr<blink::WebWaitableEvent> m_event; |
118 bool m_connectRequestResult; | 118 bool m_connectRequestResult; |
119 WebSocketChannel::SendResult m_sendRequestResult; | 119 WebSocketChannel::SendResult m_sendRequestResult; |
120 unsigned long m_bufferedAmount; | 120 unsigned long m_bufferedAmount; |
121 }; | 121 }; |
122 | 122 |
123 WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalS cope& context, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) | 123 WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalS cope& workerGlobalScope, WebSocketChannelClient* client, const String& sourceURL , unsigned lineNumber) |
124 : m_workerGlobalScope(context) | 124 : m_workerClientWrapper(ThreadableWebSocketChannelClientWrapper::create(clie nt)) |
125 , m_workerClientWrapper(ThreadableWebSocketChannelClientWrapper::create(clie nt)) | 125 , m_bridge(Bridge::create(m_workerClientWrapper, workerGlobalScope)) |
126 , m_bridge(Bridge::create(m_workerClientWrapper, m_workerGlobalScope)) | |
127 , m_sourceURLAtConnection(sourceURL) | 126 , m_sourceURLAtConnection(sourceURL) |
128 , m_lineNumberAtConnection(lineNumber) | 127 , m_lineNumberAtConnection(lineNumber) |
129 { | 128 { |
130 ASSERT(m_workerClientWrapper.get()); | 129 ASSERT(m_workerClientWrapper.get()); |
131 m_bridge->initialize(sourceURL, lineNumber); | 130 m_bridge->initialize(sourceURL, lineNumber); |
132 } | 131 } |
133 | 132 |
134 WorkerThreadableWebSocketChannel::~WorkerThreadableWebSocketChannel() | 133 WorkerThreadableWebSocketChannel::~WorkerThreadableWebSocketChannel() |
135 { | 134 { |
136 if (m_bridge) | 135 if (m_bridge) |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); | 449 ASSERT_UNUSED(context, context->isWorkerGlobalScope()); |
451 workerClientWrapper->didReceiveMessageError(); | 450 workerClientWrapper->didReceiveMessageError(); |
452 } | 451 } |
453 | 452 |
454 void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError() | 453 void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError() |
455 { | 454 { |
456 ASSERT(isMainThread()); | 455 ASSERT(isMainThread()); |
457 m_loaderProxy.postTaskToWorkerGlobalScope(createCallbackTask(&workerGlobalSc opeDidReceiveMessageError, m_workerClientWrapper)); | 456 m_loaderProxy.postTaskToWorkerGlobalScope(createCallbackTask(&workerGlobalSc opeDidReceiveMessageError, m_workerClientWrapper)); |
458 } | 457 } |
459 | 458 |
460 WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtr<ThreadableWebSocketC hannelClientWrapper> workerClientWrapper, PassRefPtrWillBeRawPtr<WorkerGlobalSco pe> workerGlobalScope) | 459 WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtr<ThreadableWebSocketC hannelClientWrapper> workerClientWrapper, WorkerGlobalScope& workerGlobalScope) |
461 : m_workerClientWrapper(workerClientWrapper) | 460 : m_workerClientWrapper(workerClientWrapper) |
462 , m_workerGlobalScope(workerGlobalScope) | 461 , m_workerGlobalScope(workerGlobalScope) |
463 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) | 462 , m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) |
464 , m_syncHelper(0) | 463 , m_syncHelper(0) |
465 { | 464 { |
466 ASSERT(m_workerClientWrapper.get()); | 465 ASSERT(m_workerClientWrapper.get()); |
467 } | 466 } |
468 | 467 |
469 WorkerThreadableWebSocketChannel::Bridge::~Bridge() | 468 WorkerThreadableWebSocketChannel::Bridge::~Bridge() |
470 { | 469 { |
(...skipping 12 matching lines...) Expand all Loading... | |
483 RefPtr<Bridge> protect(this); | 482 RefPtr<Bridge> protect(this); |
484 m_loaderProxy.postTaskToLoader(createCallbackTask(&Peer::initialize, referen ce.release(), AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper, sou rceURL, lineNumber, syncHelper.release())); | 483 m_loaderProxy.postTaskToLoader(createCallbackTask(&Peer::initialize, referen ce.release(), AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper, sou rceURL, lineNumber, syncHelper.release())); |
485 if (!waitForMethodCompletion()) { | 484 if (!waitForMethodCompletion()) { |
486 // The worker thread has been signalled to shutdown before method comple tion. | 485 // The worker thread has been signalled to shutdown before method comple tion. |
487 terminatePeer(); | 486 terminatePeer(); |
488 } | 487 } |
489 } | 488 } |
490 | 489 |
491 bool WorkerThreadableWebSocketChannel::Bridge::connect(const KURL& url, const St ring& protocol) | 490 bool WorkerThreadableWebSocketChannel::Bridge::connect(const KURL& url, const St ring& protocol) |
492 { | 491 { |
493 if (!m_workerGlobalScope) | 492 if (hasTerminatedPeer()) |
494 return false; | 493 return false; |
495 ASSERT(m_syncHelper); | 494 |
495 RefPtr<Bridge> protect(this); | |
yhirano
2014/05/07 08:05:18
Can you tell me why this move is needed? I think p
tyoshino (SeeGerritForStatus)
2014/05/08 05:03:00
As discussed offline, it looks we no longer need t
| |
496 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::connect, m_peer, url.copy(), protocol.isolatedCopy()))); | 496 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::connect, m_peer, url.copy(), protocol.isolatedCopy()))); |
497 RefPtr<Bridge> protect(this); | 497 if (!waitForMethodCompletion()) |
yhirano
2014/05/07 08:05:18
[optional] We could have postTaskAndWait for this
tyoshino (SeeGerritForStatus)
2014/05/08 05:03:00
Done.
| |
498 waitForMethodCompletion(); | 498 return false; |
499 | |
499 return m_syncHelper->connectRequestResult(); | 500 return m_syncHelper->connectRequestResult(); |
500 } | 501 } |
501 | 502 |
502 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(cons t String& message) | 503 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(cons t String& message) |
503 { | 504 { |
504 if (!m_workerGlobalScope) | 505 if (hasTerminatedPeer()) |
505 return WebSocketChannel::SendFail; | 506 return WebSocketChannel::SendFail; |
506 ASSERT(m_syncHelper); | 507 |
508 RefPtr<Bridge> protect(this); | |
507 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::send, m_p eer, message.isolatedCopy()))); | 509 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::send, m_p eer, message.isolatedCopy()))); |
508 RefPtr<Bridge> protect(this); | 510 if (!waitForMethodCompletion()) |
509 waitForMethodCompletion(); | 511 return WebSocketChannel::SendFail; |
512 | |
510 return m_syncHelper->sendRequestResult(); | 513 return m_syncHelper->sendRequestResult(); |
511 } | 514 } |
512 | 515 |
513 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(cons t ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) | 516 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(cons t ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) |
514 { | 517 { |
515 if (!m_workerGlobalScope) | 518 if (hasTerminatedPeer()) |
516 return WebSocketChannel::SendFail; | 519 return WebSocketChannel::SendFail; |
517 ASSERT(m_syncHelper); | 520 |
518 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied into Vector<char>. | 521 // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied into Vector<char>. |
519 OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); | 522 OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); |
520 if (binaryData.byteLength()) | 523 if (binaryData.byteLength()) |
521 memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteO ffset, byteLength); | 524 memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteO ffset, byteLength); |
522 | 525 |
526 RefPtr<Bridge> protect(this); | |
523 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::sendArray Buffer, m_peer, data.release()))); | 527 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::sendArray Buffer, m_peer, data.release()))); |
524 RefPtr<Bridge> protect(this); | 528 if (!waitForMethodCompletion()) |
525 waitForMethodCompletion(); | 529 return WebSocketChannel::SendFail; |
530 | |
526 return m_syncHelper->sendRequestResult(); | 531 return m_syncHelper->sendRequestResult(); |
527 } | 532 } |
528 | 533 |
529 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(Pass RefPtr<BlobDataHandle> data) | 534 WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(Pass RefPtr<BlobDataHandle> data) |
530 { | 535 { |
531 if (!m_workerGlobalScope) | 536 if (hasTerminatedPeer()) |
532 return WebSocketChannel::SendFail; | 537 return WebSocketChannel::SendFail; |
533 ASSERT(m_syncHelper); | 538 |
539 RefPtr<Bridge> protect(this); | |
534 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::sendBlob, m_peer, data))); | 540 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::sendBlob, m_peer, data))); |
535 RefPtr<Bridge> protect(this); | 541 if (!waitForMethodCompletion()) |
536 waitForMethodCompletion(); | 542 return WebSocketChannel::SendFail; |
543 | |
537 return m_syncHelper->sendRequestResult(); | 544 return m_syncHelper->sendRequestResult(); |
538 } | 545 } |
539 | 546 |
540 unsigned long WorkerThreadableWebSocketChannel::Bridge::bufferedAmount() | 547 unsigned long WorkerThreadableWebSocketChannel::Bridge::bufferedAmount() |
541 { | 548 { |
542 if (!m_workerGlobalScope) | 549 if (hasTerminatedPeer()) |
543 return 0; | 550 return 0; |
544 ASSERT(m_syncHelper); | 551 |
552 RefPtr<Bridge> protect(this); | |
545 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::bufferedA mount, m_peer))); | 553 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::bufferedA mount, m_peer))); |
546 RefPtr<Bridge> protect(this); | 554 if (!waitForMethodCompletion()) |
547 waitForMethodCompletion(); | 555 return 0; |
556 | |
548 return m_syncHelper->bufferedAmount(); | 557 return m_syncHelper->bufferedAmount(); |
549 } | 558 } |
550 | 559 |
551 void WorkerThreadableWebSocketChannel::Bridge::close(int code, const String& rea son) | 560 void WorkerThreadableWebSocketChannel::Bridge::close(int code, const String& rea son) |
552 { | 561 { |
562 if (hasTerminatedPeer()) | |
563 return; | |
564 | |
553 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::close, m_ peer, code, reason.isolatedCopy()))); | 565 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::close, m_ peer, code, reason.isolatedCopy()))); |
554 } | 566 } |
555 | 567 |
556 void WorkerThreadableWebSocketChannel::Bridge::fail(const String& reason, Messag eLevel level, const String& sourceURL, unsigned lineNumber) | 568 void WorkerThreadableWebSocketChannel::Bridge::fail(const String& reason, Messag eLevel level, const String& sourceURL, unsigned lineNumber) |
557 { | 569 { |
570 if (hasTerminatedPeer()) | |
571 return; | |
572 | |
558 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::fail, m_p eer, reason.isolatedCopy(), level, sourceURL.isolatedCopy(), lineNumber))); | 573 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::fail, m_p eer, reason.isolatedCopy(), level, sourceURL.isolatedCopy(), lineNumber))); |
559 } | 574 } |
560 | 575 |
561 void WorkerThreadableWebSocketChannel::Bridge::disconnect() | 576 void WorkerThreadableWebSocketChannel::Bridge::disconnect() |
562 { | 577 { |
563 clearClientWrapper(); | 578 clearClientWrapper(); |
564 terminatePeer(); | 579 terminatePeer(); |
565 } | 580 } |
566 | 581 |
567 void WorkerThreadableWebSocketChannel::Bridge::suspend() | 582 void WorkerThreadableWebSocketChannel::Bridge::suspend() |
568 { | 583 { |
584 if (hasTerminatedPeer()) | |
585 return; | |
586 | |
569 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::suspend, m_peer))); | 587 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::suspend, m_peer))); |
570 } | 588 } |
571 | 589 |
572 void WorkerThreadableWebSocketChannel::Bridge::resume() | 590 void WorkerThreadableWebSocketChannel::Bridge::resume() |
573 { | 591 { |
592 if (hasTerminatedPeer()) | |
593 return; | |
594 | |
574 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::resume, m _peer))); | 595 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::resume, m _peer))); |
575 } | 596 } |
576 | 597 |
577 void WorkerThreadableWebSocketChannel::Bridge::clearClientWrapper() | 598 void WorkerThreadableWebSocketChannel::Bridge::clearClientWrapper() |
578 { | 599 { |
579 m_workerClientWrapper->clearClient(); | 600 m_workerClientWrapper->clearClient(); |
580 } | 601 } |
581 | 602 |
582 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end, | 603 // Caller of this function should hold a reference to the bridge, because this f unction may call WebSocket::didClose() in the end, |
583 // which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. | 604 // which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. |
584 bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion() | 605 bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion() |
585 { | 606 { |
586 if (!m_syncHelper) | 607 ASSERT(m_workerGlobalScope); |
587 return true; | 608 ASSERT(m_syncHelper); |
588 | 609 |
589 blink::WebWaitableEvent* shutdownEvent = m_workerGlobalScope->thread()->shut downEvent(); | 610 blink::WebWaitableEvent* shutdownEvent = m_workerGlobalScope->thread()->shut downEvent(); |
590 Vector<blink::WebWaitableEvent*> events; | 611 Vector<blink::WebWaitableEvent*> events; |
591 events.append(shutdownEvent); | 612 events.append(shutdownEvent); |
592 events.append(m_syncHelper->event()); | 613 events.append(m_syncHelper->event()); |
593 | 614 |
594 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); | 615 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack); |
595 blink::WebWaitableEvent* signalled = blink::Platform::current()->waitMultipl eEvents(events); | 616 blink::WebWaitableEvent* signalled = blink::Platform::current()->waitMultipl eEvents(events); |
596 return signalled != shutdownEvent; | 617 return signalled != shutdownEvent; |
597 } | 618 } |
598 | 619 |
599 void WorkerThreadableWebSocketChannel::Bridge::terminatePeer() | 620 void WorkerThreadableWebSocketChannel::Bridge::terminatePeer() |
600 { | 621 { |
601 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::destroy, m_peer))); | 622 m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::destroy, m_peer))); |
623 // Peer::destroy() deletes m_peer and then m_syncHelper will be released. | |
624 // We must not touch m_syncHelper any more. | |
625 m_syncHelper = 0; | |
626 | |
627 // We won't use this any more. | |
602 m_workerGlobalScope = nullptr; | 628 m_workerGlobalScope = nullptr; |
603 m_syncHelper = 0; | |
604 } | 629 } |
605 | 630 |
606 } // namespace WebCore | 631 } // namespace WebCore |
OLD | NEW |