| 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..e03f57cbcb4f908bc42d09fcff798090c85cdacb 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,21 @@ 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) {
|
| + // Reflect bufferedAmount. If non-Blob messages were sent
|
| + // immediately before the Blob, their quota refresh will still be
|
| + // counted against bufferedAmount. However, bufferedAmount will
|
| + // always be correct when blob loading mode finishes.
|
| + m_sendingQuota -= blobUsedQuota;
|
| + m_blobDataPending -= blobUsedQuota;
|
| + if (m_client)
|
| + m_client->didConsumeBufferedAmount(blobUsedQuota);
|
| + }
|
| + } else {
|
| + processSendQueue();
|
| + }
|
| }
|
|
|
| void DocumentWebSocketChannel::didStartClosingHandshake(WebSocketHandle* handle)
|
| @@ -529,32 +495,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);
|
|
|