Chromium Code Reviews| Index: third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp |
| diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp |
| index 797dab0005f0d01223e335dbcce54a896c9580de..688293b2df8f68f2189edc5d019f0497c057ff80 100644 |
| --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp |
| +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp |
| @@ -34,8 +34,6 @@ |
| #include "core/dom/Document.h" |
| #include "core/dom/ExecutionContext.h" |
| #include "core/fetch/UniqueIdentifier.h" |
| -#include "core/fileapi/FileReaderLoader.h" |
| -#include "core/fileapi/FileReaderLoaderClient.h" |
| #include "core/frame/LocalFrame.h" |
| #include "core/inspector/ConsoleMessage.h" |
| #include "core/inspector/InspectorInstrumentation.h" |
| @@ -60,60 +58,13 @@ using blink::WebSocketHandle; |
| namespace blink { |
| -class DocumentWebSocketChannel::BlobLoader final : public GarbageCollectedFinalized<DocumentWebSocketChannel::BlobLoader>, public FileReaderLoaderClient { |
| -public: |
| - BlobLoader(PassRefPtr<BlobDataHandle>, DocumentWebSocketChannel*); |
| - ~BlobLoader() override { } |
| - |
| - void cancel(); |
| - |
| - // FileReaderLoaderClient functions. |
| - void didStartLoading() override { } |
| - void didReceiveData() override { } |
| - void didFinishLoading() override; |
| - void didFail(FileError::ErrorCode) override; |
| - |
| - DEFINE_INLINE_TRACE() |
| - { |
| - visitor->trace(m_channel); |
| - } |
| - |
| -private: |
| - Member<DocumentWebSocketChannel> m_channel; |
| - FileReaderLoader m_loader; |
| -}; |
| - |
| -DocumentWebSocketChannel::BlobLoader::BlobLoader(PassRefPtr<BlobDataHandle> blobDataHandle, DocumentWebSocketChannel* channel) |
| - : m_channel(channel) |
| - , m_loader(FileReaderLoader::ReadAsArrayBuffer, this) |
| -{ |
| - m_loader.start(channel->executionContext(), blobDataHandle); |
| -} |
| - |
| -void DocumentWebSocketChannel::BlobLoader::cancel() |
| -{ |
| - m_loader.cancel(); |
| - // didFail will be called immediately. |
| - // |this| is deleted here. |
| -} |
| - |
| -void DocumentWebSocketChannel::BlobLoader::didFinishLoading() |
| -{ |
| - m_channel->didFinishLoadingBlob(m_loader.arrayBufferResult()); |
| - // |this| is deleted here. |
| -} |
| - |
| -void DocumentWebSocketChannel::BlobLoader::didFail(FileError::ErrorCode errorCode) |
| -{ |
| - m_channel->didFailLoadingBlob(errorCode); |
| - // |this| is deleted here. |
| -} |
| - |
| DocumentWebSocketChannel::DocumentWebSocketChannel(Document* document, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber, WebSocketHandle *handle) |
| : ContextLifecycleObserver(document) |
| , m_handle(adoptPtr(handle ? handle : Platform::current()->createWebSocketHandle())) |
| , m_client(client) |
| , m_identifier(createUniqueIdentifier()) |
| + , m_blobLoadingMode(false) |
| + , m_blobDataPending(0) |
| , m_sendingQuota(0) |
| , m_receivedDataSizeForFlowControl(receivedDataSizeForFlowControlHighWaterMark * 2) // initial quota |
| , m_sentSizeOfTopMessage(0) |
| @@ -124,7 +75,7 @@ DocumentWebSocketChannel::DocumentWebSocketChannel(Document* document, WebSocket |
| DocumentWebSocketChannel::~DocumentWebSocketChannel() |
| { |
| - ASSERT(!m_blobLoader); |
| + ASSERT(!m_blobLoadingMode); |
| } |
| bool DocumentWebSocketChannel::connect(const KURL& url, const String& protocol) |
| @@ -255,7 +206,7 @@ void DocumentWebSocketChannel::disconnect() |
| TRACE_EVENT_INSTANT1("devtools.timeline", "WebSocketDestroy", TRACE_EVENT_SCOPE_THREAD, "data", InspectorWebSocketEvent::data(document(), m_identifier)); |
| InspectorInstrumentation::didCloseWebSocket(document(), m_identifier); |
| } |
| - abortAsyncOperations(); |
| + m_blobLoadingMode = false; |
| m_handle.clear(); |
| m_client = nullptr; |
| m_identifier = 0; |
| @@ -308,11 +259,21 @@ void DocumentWebSocketChannel::sendInternal(WebSocketHandle::MessageType message |
| } |
| } |
| +void DocumentWebSocketChannel::sendBlob(const BlobDataHandle& blob) |
| +{ |
| + ASSERT(!m_blobLoadingMode); |
| + m_blobLoadingMode = true; |
| + m_blobDataPending = blob.size(); |
| + m_handle->sendBlob(blob.uuid(), blob.size()); |
| + // The message is still in |m_messages| so that the renderer holds a |
| + // reference to it until it is fully sent. |
| +} |
| + |
| void DocumentWebSocketChannel::processSendQueue() |
| { |
| ASSERT(m_handle); |
| uint64_t consumedBufferedAmount = 0; |
| - while (!m_messages.isEmpty() && !m_blobLoader) { |
| + while (!m_messages.isEmpty() && !m_blobLoadingMode) { |
| Message* message = m_messages.first().get(); |
| if (m_sendingQuota == 0 && message->type != MessageTypeClose) |
| break; |
| @@ -321,8 +282,7 @@ void DocumentWebSocketChannel::processSendQueue() |
| sendInternal(WebSocketHandle::MessageTypeText, message->text.data(), message->text.length(), &consumedBufferedAmount); |
| break; |
| case MessageTypeBlob: |
| - ASSERT(!m_blobLoader); |
| - m_blobLoader = new BlobLoader(message->blobDataHandle, this); |
| + sendBlob(*message->blobDataHandle); |
| break; |
| case MessageTypeArrayBuffer: |
| sendInternal(WebSocketHandle::MessageTypeBinary, static_cast<const char*>(message->arrayBuffer->data()), message->arrayBuffer->byteLength(), &consumedBufferedAmount); |
| @@ -356,18 +316,10 @@ void DocumentWebSocketChannel::flowControlIfNecessary() |
| m_receivedDataSizeForFlowControl = 0; |
| } |
| -void DocumentWebSocketChannel::abortAsyncOperations() |
| -{ |
| - if (m_blobLoader) { |
| - m_blobLoader->cancel(); |
| - m_blobLoader.clear(); |
| - } |
| -} |
| - |
| void DocumentWebSocketChannel::handleDidClose(bool wasClean, unsigned short code, const String& reason) |
| { |
| m_handle.clear(); |
| - abortAsyncOperations(); |
| + m_blobLoadingMode = false; |
| if (!m_client) { |
| return; |
| } |
| @@ -515,7 +467,17 @@ void DocumentWebSocketChannel::didReceiveFlowControl(WebSocketHandle* handle, in |
| ASSERT(quota >= 0); |
| m_sendingQuota += quota; |
| - processSendQueue(); |
| + if (m_blobLoadingMode) { |
| + uint64_t blobUsedQuota = std::min(static_cast<uint64_t>(quota), m_blobDataPending); |
| + if (blobUsedQuota > 0) { |
| + m_sendingQuota -= blobUsedQuota; |
| + m_blobDataPending -= blobUsedQuota; |
| + if (m_client) |
| + m_client->didConsumeBufferedAmount(blobUsedQuota); |
|
tyoshino (SeeGerritForStatus)
2016/02/09 14:29:10
IIUC, it's possible that this would process flow c
Adam Rice
2016/02/10 01:37:55
Correct. For example, if the user sends an 8KB Tex
tyoshino (SeeGerritForStatus)
2016/02/10 06:48:46
Right. bufferedAmount doesn't tell the actual memo
Adam Rice
2016/02/10 12:58:27
Comment added. I tried to keep it short to match B
|
| + } |
| + } else { |
| + processSendQueue(); |
| + } |
| } |
| void DocumentWebSocketChannel::didStartClosingHandshake(WebSocketHandle* handle) |
| @@ -529,32 +491,30 @@ void DocumentWebSocketChannel::didStartClosingHandshake(WebSocketHandle* handle) |
| m_client->didStartClosingHandshake(); |
| } |
| -void DocumentWebSocketChannel::didFinishLoadingBlob(PassRefPtr<DOMArrayBuffer> buffer) |
| +void DocumentWebSocketChannel::didCompleteSendingBlob(WebSocketHandle* handle) |
| { |
| - m_blobLoader.clear(); |
| - ASSERT(m_handle); |
| - // The loaded blob is always placed on m_messages[0]. |
| - ASSERT(m_messages.size() > 0 && m_messages.first()->type == MessageTypeBlob); |
| - // We replace it with the loaded blob. |
| - m_messages.first() = adoptPtr(new Message(buffer)); |
| - processSendQueue(); |
| -} |
| + WTF_LOG(Network, "DocumentWebSocketChannel %p didCompleteSendingBlob(%p)", this, handle); |
| -void DocumentWebSocketChannel::didFailLoadingBlob(FileError::ErrorCode errorCode) |
| -{ |
| - m_blobLoader.clear(); |
| - if (errorCode == FileError::ABORT_ERR) { |
| - // The error is caused by cancel(). |
| + // If the IPC was unexpected, do nothing. |
| + if (!m_blobLoadingMode) |
| return; |
| - } |
| - // FIXME: Generate human-friendly reason message. |
| - failAsError("Failed to load Blob: error code = " + String::number(errorCode)); |
| - // |this| can be deleted here. |
| + |
| + ASSERT(m_handle); |
| + ASSERT(handle == m_handle); |
| + ASSERT(m_sendingQuota >= m_blobDataPending); |
| + |
| + m_sendingQuota -= m_blobDataPending; |
| + if (m_blobDataPending && m_client) |
| + m_client->didConsumeBufferedAmount(m_blobDataPending); |
| + m_blobDataPending = 0; |
| + m_blobLoadingMode = false; |
| + // Remove the reference to the Blob. |
| + m_messages.removeFirst(); |
| + processSendQueue(); |
| } |
| DEFINE_TRACE(DocumentWebSocketChannel) |
| { |
| - visitor->trace(m_blobLoader); |
| visitor->trace(m_client); |
| WebSocketChannel::trace(visitor); |
| ContextLifecycleObserver::trace(visitor); |