Index: Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp |
diff --git a/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp b/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp |
index f66c0f15f6d66acb8b278374a6aceecec3760a6e..d6b7bbb3bcc0bd18589976664745620f65b5e849 100644 |
--- a/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp |
+++ b/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp |
@@ -37,7 +37,6 @@ |
#include "core/dom/CrossThreadTask.h" |
#include "core/dom/Document.h" |
#include "core/dom/ExecutionContext.h" |
-#include "core/dom/ExecutionContextTask.h" |
#include "core/fileapi/Blob.h" |
#include "core/inspector/ScriptCallFrame.h" |
#include "core/inspector/ScriptCallStack.h" |
@@ -120,10 +119,9 @@ private: |
unsigned long m_bufferedAmount; |
}; |
-WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalScope& context, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) |
- : m_workerGlobalScope(context) |
- , m_workerClientWrapper(ThreadableWebSocketChannelClientWrapper::create(client)) |
- , m_bridge(Bridge::create(m_workerClientWrapper, m_workerGlobalScope)) |
+WorkerThreadableWebSocketChannel::WorkerThreadableWebSocketChannel(WorkerGlobalScope& workerGlobalScope, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) |
+ : m_workerClientWrapper(ThreadableWebSocketChannelClientWrapper::create(client)) |
+ , m_bridge(Bridge::create(m_workerClientWrapper, workerGlobalScope)) |
, m_sourceURLAtConnection(sourceURL) |
, m_lineNumberAtConnection(lineNumber) |
{ |
@@ -229,12 +227,6 @@ void WorkerThreadableWebSocketChannel::resume() |
m_bridge->resume(); |
} |
-void WorkerThreadableWebSocketChannel::trace(Visitor* visitor) |
-{ |
- visitor->trace(m_workerGlobalScope); |
- WebSocketChannel::trace(visitor); |
-} |
- |
WorkerThreadableWebSocketChannel::Peer::Peer(PassRefPtr<WeakReference<Peer> > reference, PassRefPtr<ThreadableWebSocketChannelClientWrapper> clientWrapper, WorkerLoaderProxy& loaderProxy, ExecutionContext* context, const String& sourceURL, unsigned lineNumber, PassOwnPtr<ThreadableWebSocketChannelSyncHelper> syncHelper) |
: m_workerClientWrapper(clientWrapper) |
, m_loaderProxy(loaderProxy) |
@@ -463,7 +455,7 @@ void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError() |
m_loaderProxy.postTaskToWorkerGlobalScope(createCallbackTask(&workerGlobalScopeDidReceiveMessageError, m_workerClientWrapper)); |
} |
-WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, PassRefPtrWillBeRawPtr<WorkerGlobalScope> workerGlobalScope) |
+WorkerThreadableWebSocketChannel::Bridge::Bridge(PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, WorkerGlobalScope& workerGlobalScope) |
: m_workerClientWrapper(workerClientWrapper) |
, m_workerGlobalScope(workerGlobalScope) |
, m_loaderProxy(m_workerGlobalScope->thread()->workerLoaderProxy()) |
@@ -487,8 +479,7 @@ void WorkerThreadableWebSocketChannel::Bridge::initialize(const String& sourceUR |
m_syncHelper = syncHelper.get(); |
RefPtr<Bridge> protect(this); |
- m_loaderProxy.postTaskToLoader(createCallbackTask(&Peer::initialize, reference.release(), AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper, sourceURL, lineNumber, syncHelper.release())); |
- if (!waitForMethodCompletion()) { |
+ if (!waitForMethodCompletion(createCallbackTask(&Peer::initialize, reference.release(), AllowCrossThreadAccess(&m_loaderProxy), m_workerClientWrapper, sourceURL, lineNumber, syncHelper.release()))) { |
// The worker thread has been signalled to shutdown before method completion. |
terminatePeer(); |
} |
@@ -496,71 +487,82 @@ void WorkerThreadableWebSocketChannel::Bridge::initialize(const String& sourceUR |
bool WorkerThreadableWebSocketChannel::Bridge::connect(const KURL& url, const String& protocol) |
{ |
- if (!m_workerGlobalScope) |
+ if (hasTerminatedPeer()) |
return false; |
- ASSERT(m_syncHelper); |
- m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::connect, m_peer, url.copy(), protocol.isolatedCopy()))); |
+ |
RefPtr<Bridge> protect(this); |
- waitForMethodCompletion(); |
+ if (!waitForMethodCompletion(CallClosureTask::create(bind(&Peer::connect, m_peer, url.copy(), protocol.isolatedCopy())))) |
+ return false; |
+ |
return m_syncHelper->connectRequestResult(); |
} |
WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(const String& message) |
{ |
- if (!m_workerGlobalScope) |
+ if (hasTerminatedPeer()) |
return WebSocketChannel::SendFail; |
- ASSERT(m_syncHelper); |
- m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::send, m_peer, message.isolatedCopy()))); |
+ |
RefPtr<Bridge> protect(this); |
- waitForMethodCompletion(); |
+ if (!waitForMethodCompletion(CallClosureTask::create(bind(&Peer::send, m_peer, message.isolatedCopy())))) |
+ return WebSocketChannel::SendFail; |
+ |
return m_syncHelper->sendRequestResult(); |
} |
WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) |
{ |
- if (!m_workerGlobalScope) |
+ if (hasTerminatedPeer()) |
return WebSocketChannel::SendFail; |
- ASSERT(m_syncHelper); |
+ |
// ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied into Vector<char>. |
OwnPtr<Vector<char> > data = adoptPtr(new Vector<char>(byteLength)); |
if (binaryData.byteLength()) |
memcpy(data->data(), static_cast<const char*>(binaryData.data()) + byteOffset, byteLength); |
- m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::sendArrayBuffer, m_peer, data.release()))); |
RefPtr<Bridge> protect(this); |
- waitForMethodCompletion(); |
+ if (!waitForMethodCompletion(CallClosureTask::create(bind(&Peer::sendArrayBuffer, m_peer, data.release())))) |
+ return WebSocketChannel::SendFail; |
+ |
return m_syncHelper->sendRequestResult(); |
} |
WebSocketChannel::SendResult WorkerThreadableWebSocketChannel::Bridge::send(PassRefPtr<BlobDataHandle> data) |
{ |
- if (!m_workerGlobalScope) |
+ if (hasTerminatedPeer()) |
return WebSocketChannel::SendFail; |
- ASSERT(m_syncHelper); |
- m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::sendBlob, m_peer, data))); |
+ |
RefPtr<Bridge> protect(this); |
- waitForMethodCompletion(); |
+ if (!waitForMethodCompletion(CallClosureTask::create(bind(&Peer::sendBlob, m_peer, data)))) |
+ return WebSocketChannel::SendFail; |
+ |
return m_syncHelper->sendRequestResult(); |
} |
unsigned long WorkerThreadableWebSocketChannel::Bridge::bufferedAmount() |
{ |
- if (!m_workerGlobalScope) |
+ if (hasTerminatedPeer()) |
return 0; |
- ASSERT(m_syncHelper); |
- m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::bufferedAmount, m_peer))); |
+ |
RefPtr<Bridge> protect(this); |
- waitForMethodCompletion(); |
+ if (!waitForMethodCompletion(CallClosureTask::create(bind(&Peer::bufferedAmount, m_peer)))) |
+ return 0; |
+ |
return m_syncHelper->bufferedAmount(); |
} |
void WorkerThreadableWebSocketChannel::Bridge::close(int code, const String& reason) |
{ |
+ if (hasTerminatedPeer()) |
+ return; |
+ |
m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::close, m_peer, code, reason.isolatedCopy()))); |
} |
void WorkerThreadableWebSocketChannel::Bridge::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) |
{ |
+ if (hasTerminatedPeer()) |
+ return; |
+ |
m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::fail, m_peer, reason.isolatedCopy(), level, sourceURL.isolatedCopy(), lineNumber))); |
} |
@@ -572,11 +574,17 @@ void WorkerThreadableWebSocketChannel::Bridge::disconnect() |
void WorkerThreadableWebSocketChannel::Bridge::suspend() |
{ |
+ if (hasTerminatedPeer()) |
+ return; |
+ |
m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::suspend, m_peer))); |
} |
void WorkerThreadableWebSocketChannel::Bridge::resume() |
{ |
+ if (hasTerminatedPeer()) |
+ return; |
+ |
m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::resume, m_peer))); |
} |
@@ -587,10 +595,12 @@ void WorkerThreadableWebSocketChannel::Bridge::clearClientWrapper() |
// Caller of this function should hold a reference to the bridge, because this function may call WebSocket::didClose() in the end, |
// which causes the bridge to get disconnected from the WebSocket and deleted if there is no other reference. |
-bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion() |
+bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion(PassOwnPtr<ExecutionContextTask> task) |
{ |
- if (!m_syncHelper) |
- return true; |
+ ASSERT(m_workerGlobalScope); |
+ ASSERT(m_syncHelper); |
+ |
+ m_loaderProxy.postTaskToLoader(task); |
blink::WebWaitableEvent* shutdownEvent = m_workerGlobalScope->thread()->shutdownEvent(); |
Vector<blink::WebWaitableEvent*> events; |
@@ -605,8 +615,12 @@ bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion() |
void WorkerThreadableWebSocketChannel::Bridge::terminatePeer() |
{ |
m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::destroy, m_peer))); |
- m_workerGlobalScope = nullptr; |
+ // Peer::destroy() deletes m_peer and then m_syncHelper will be released. |
+ // We must not touch m_syncHelper any more. |
m_syncHelper = 0; |
+ |
+ // We won't use this any more. |
+ m_workerGlobalScope = nullptr; |
} |
} // namespace WebCore |