15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011, 2012 Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/MainThreadWebSocketChannel.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h" 361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/dom/ExecutionContext.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/Blob.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/fileapi/FileReaderLoader.h" 39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h" 40e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "core/inspector/ConsoleMessage.h" 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h" 42f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "core/inspector/InspectorTraceEvents.h" 4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoader.h" 4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/FrameLoaderClient.h" 45f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "core/loader/MixedContentChecker.h" 4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/UniqueIdentifier.h" 4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Page.h" 4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/websockets/WebSocketChannelClient.h" 491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Logging.h" 501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/network/SocketStreamError.h" 511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/network/SocketStreamHandle.h" 5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/ArrayBuffer.h" 5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/FastMalloc.h" 5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/HashMap.h" 5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/OwnPtr.h" 5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/StringHash.h" 5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/WTFString.h" 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 59c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double TCPMaximumSegmentLifetime = 2 * 60.0; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_document(document) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_client(client) 6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_suspended(false) 6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) , m_didFailOfClientAlreadyRun(false) 6951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) , m_hasCalledDisconnectOnHandle(false) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_receivedClosingHandshake(false) 7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) 725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) , m_state(ChannelIdle) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_shouldDiscardReceivedData(false) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_identifier(0) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_hasContinuousFrame(false) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_closeEventCode(CloseEventCodeAbnormalClosure) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) 7876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) , m_numConsumedBytesInCurrentFrame(0) 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_blobLoaderStatus(BlobLoaderNotStarted) 80a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) , m_sourceURLAtConstruction(sourceURL) 81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) , m_lineNumberAtConstruction(lineNumber) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (m_document->page()) 8453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_identifier = createUniqueIdentifier(); 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)MainThreadWebSocketChannel::~MainThreadWebSocketChannel() 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 91f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liubool MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p connect()", this); 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_handle); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 96f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 97f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_document->frame() && !m_document->frame()->loader().mixedContentChecker()->canConnectInsecureWebSocket(m_document->securityOrigin(), url)) 98f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return false; 99f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (MixedContentChecker::isMixedContent(m_document->securityOrigin(), url)) { 100f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu String message = "Connecting to a non-secure WebSocket server from a secure origin is deprecated."; 101e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_document->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); 102f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 103f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_handshake = new WebSocketHandshake(url, protocol, m_document); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_handshake->reset(); 106bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionProcessor()); 10781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor()); 108f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier) { 109f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketCreate", "data", InspectorWebSocketCreateEvent::data(m_document, m_identifier, url, protocol)); 110323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 111f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 11293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, url, protocol); 113f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ref(); 115f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 116f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_handle = SocketStreamHandle::create(this); 117f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) ASSERT(m_handle); 118f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (m_document->frame()) { 119f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_document->frame()->loader().client()->dispatchWillOpenSocketStream(m_handle.get()); 120f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 121f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_handle->connect(m_handshake->url()); 122f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 123f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return true; 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void MainThreadWebSocketChannel::send(const String& message) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 128a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending String '%s'", this, message.utf8().data()); 12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CString utf8 = message.utf8(StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueTextFrame(utf8); 13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 134c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void MainThreadWebSocketChannel::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 136a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending ArrayBuffer %p byteOffset=%u byteLength=%u", this, &binaryData, byteOffset, byteLength); 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()) + byteOffset, byteLength); 13853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void MainThreadWebSocketChannel::send(PassRefPtr<BlobDataHandle> binaryData) 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 143a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending Blob '%s'", this, binaryData->uuid().utf8().data()); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData); 14553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void MainThreadWebSocketChannel::send(PassOwnPtr<Vector<char> > data) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 150d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p send() Sending Vector %p", this, data.get()); 151d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) enqueueVector(WebSocketFrame::OpCodeBinary, data); 15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::close(int code, const String& reason) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 157a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", this, code, reason.utf8().data()); 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_handle) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startClosingHandshake(code, reason); 162521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (!m_closingTimer.isActive()) 163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime, FROM_HERE); 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MainThreadWebSocketChannel::clearDocument() 16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (m_handshake) 16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_handshake->clearDocument(); 170197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_document = nullptr; 17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 17351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void MainThreadWebSocketChannel::disconnectHandle() 17451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){ 17551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (!m_handle) 17651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return; 17751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) m_hasCalledDisconnectOnHandle = true; 17851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) m_handle->disconnect(); 17951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)} 18051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 181d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void MainThreadWebSocketChannel::callDidReceiveMessageError() 182d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 183d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!m_client || m_didFailOfClientAlreadyRun) 184d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return; 185d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_didFailOfClientAlreadyRun = true; 186d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_client->didReceiveMessageError(); 187d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 188d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 18981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, const String& sourceURL, unsigned lineNumber) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 191a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reason.utf8().data()); 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_document) { 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_identifier, reason); 19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) const String message = "WebSocket connection to '" + m_handshake->url().elidedString() + "' failed: " + reason; 195e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_document->addConsoleMessage(ConsoleMessage::create(JSMessageSource, level, message, sourceURL, lineNumber)); 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Hybi-10 specification explicitly states we must not continue to handle incoming data 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // once the WebSocket connection is failed (section 7.1.7). 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_buffer.isEmpty()) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(m_buffer.size()); // Save memory. 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_deflateFramer.didFail(); 20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_perMessageDeflate.didFail(); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = false; 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.clear(); 206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 207d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) callDidReceiveMessageError(); 208d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 20951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (m_state != ChannelClosed) 21051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); // Will call didCloseSocketStream(). 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 21353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::disconnect() 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 215a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p disconnect()", this); 216f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier && m_document) { 217f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 218323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 219f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 221f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) clearDocument(); 22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 225197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_client = nullptr; 22651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 22953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::suspend() 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_suspended = true; 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 23453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::resume() 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_suspended = false; 2375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if ((!m_buffer.isEmpty() || (m_state == ChannelClosed)) && m_client && !m_resumeTimer.isActive()) 238d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_resumeTimer.startOneShot(0, FROM_HERE); 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 24153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 243a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(handle == m_handle); 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_document) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 247f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier) { 248f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketSendHandshakeRequest", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 249323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 250f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 251d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, m_handshake->clientHandshakeRequest().get()); 252f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CString handshakeMessage = m_handshake->clientHandshakeMessage(); 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) 25581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket handshake."); 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle) 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 260a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); 261f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier && m_document) { 262f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketDestroy", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 263323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); 264f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 266f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 26851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 26951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) // Show error message on JS console if this is unexpected connection close 27051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) // during opening handshake. 27151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (!m_hasCalledDisconnectOnHandle && m_handshake->mode() == WebSocketHandshake::Incomplete && m_document) { 27251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) const String message = "WebSocket connection to '" + m_handshake->url().elidedString() + "' failed: Connection closed before receiving a handshake response"; 273e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_document->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message, m_sourceURLAtConstruction, m_lineNumberAtConstruction)); 27451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 27551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 2765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_state = ChannelClosed; 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_closingTimer.isActive()) 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closingTimer.stop(); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_outgoingFrameQueueStatus != OutgoingFrameQueueClosed) 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) abortOutgoingFrameQueue(); 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handle) { 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WebSocketChannelClient* client = m_client; 283197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_client = nullptr; 28409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) clearDocument(); 285d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_handle = nullptr; 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (client) 28776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) client->didClose(m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deref(); 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle* handle, const char* data, int len) 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 294a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didReceiveSocketStreamData() Received %d bytes", this, len); 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(handle == m_handle); 29653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m_document) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (len <= 0) { 29951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_client) { 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 30451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_shouldDiscardReceivedData) 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!appendToBuffer(data, len)) { 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 31181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Ran out of memory while receiving WebSocket data."); 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 314f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) processBuffer(); 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)void MainThreadWebSocketChannel::didConsumeBufferedAmount(SocketStreamHandle*, size_t consumed) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 31976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (m_framingOverheadQueue.isEmpty()) { 32076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // Ignore the handshake consumption. 32176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) return; 32276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 32376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (!m_client || m_state == ChannelClosed) 32476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) return; 32576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) size_t remain = consumed; 32676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) while (remain > 0) { 32776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) ASSERT(!m_framingOverheadQueue.isEmpty()); 32876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) const FramingOverhead& frame = m_framingOverheadQueue.first(); 32976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) 33076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) ASSERT(m_numConsumedBytesInCurrentFrame <= frame.frameDataSize()); 33176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) size_t consumedInThisFrame = std::min(remain, frame.frameDataSize() - m_numConsumedBytesInCurrentFrame); 33276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) remain -= consumedInThisFrame; 33376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_numConsumedBytesInCurrentFrame += consumedInThisFrame; 33476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) 33576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (m_numConsumedBytesInCurrentFrame == frame.frameDataSize()) { 33676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) if (m_client && WebSocketFrame::isNonControlOpCode(frame.opcode())) { 33776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // FIXME: As |consumed| is the number of possibly compressed 33876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // bytes, we can't determine the number of consumed original 33976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) // bytes in the middle of a frame. 34076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_client->didConsumeBufferedAmount(frame.originalPayloadLength()); 34176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 34276c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_framingOverheadQueue.takeFirst(); 34376c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_numConsumedBytesInCurrentFrame = 0; 34476c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 34576c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) } 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 34853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didFailSocketStream(SocketStreamHandle* handle, const SocketStreamError& error) 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 350a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didFailSocketStream()", this); 35153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 35353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) String message; 35453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (error.isNull()) 35553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) message = "WebSocket network error"; 35653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else if (error.localizedDescription().isNull()) 35753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) message = "WebSocket network error: error code " + String::number(error.errorCode()); 35853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) else 35953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) message = "WebSocket network error: error code " + String::number(error.errorCode()) + ", " + error.localizedDescription(); 36053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) String failingURL = error.failingURL(); 36153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT(failingURL.isNull() || m_handshake->url().string() == failingURL); 36253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (failingURL.isNull()) 36353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) failingURL = m_handshake->url().string(); 364a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "Error Message: '%s', FailURL: '%s'", message.utf8().data(), failingURL.utf8().data()); 365d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 366d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (m_state != ChannelClosing && m_state != ChannelClosed) 367d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) callDidReceiveMessageError(); 368d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 36951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (m_state != ChannelClosed) 37051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 37353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didStartLoading() 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 375a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didStartLoading()", this); 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didReceiveData() 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 382a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didReceiveData()", this); 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::didFinishLoading() 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 389a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didFinishLoading()", this); 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderFinished; 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) processOutgoingFrameQueue(); 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deref(); 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 397591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid MainThreadWebSocketChannel::didFail(FileError::ErrorCode errorCode) 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 399a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, errorCode); 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoader); 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader.clear(); 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderFailed; 40481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to load Blob: error code = " + String::number(errorCode)); // FIXME: Generate human-friendly reason message. 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deref(); 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t newBufferSize = m_buffer.size() + len; 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (newBufferSize < m_buffer.size()) { 412a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p appendToBuffer() Buffer overflow (%lu bytes already in receive buffer and appending %lu bytes)", this, static_cast<unsigned long>(m_buffer.size()), static_cast<unsigned long>(len)); 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.append(data, len); 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 41953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::skipBuffer(size_t len) 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ASSERT_WITH_SECURITY_IMPLICATION(len <= m_buffer.size()); 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memmove(m_buffer.data(), m_buffer.data() + len, m_buffer.size() - len); 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer.resize(m_buffer.size() - len); 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 426f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void MainThreadWebSocketChannel::processBuffer() 427f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){ 428f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) while (!m_suspended && m_client && !m_buffer.isEmpty()) { 429f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) if (!processOneItemFromBuffer()) 430f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) break; 431f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 432f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} 433f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 434f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)bool MainThreadWebSocketChannel::processOneItemFromBuffer() 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_client); 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_buffer.isEmpty()); 439a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p processBuffer() Receive buffer has %lu bytes", this, static_cast<unsigned long>(m_buffer.size())); 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_shouldDiscardReceivedData) 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_receivedClosingHandshake) { 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(m_buffer.size()); 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handshake->mode() == WebSocketHandshake::Incomplete) { 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int headerLength = m_handshake->readServerHandshake(m_buffer.data(), m_buffer.size()); 4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (headerLength <= 0) 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handshake->mode() == WebSocketHandshake::Connected) { 454f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu if (m_identifier) { 455323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "WebSocketReceiveHandshakeResponse", "data", InspectorWebSocketEvent::data(m_document, m_identifier)); 456f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 457d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document, m_identifier, 0, &m_handshake->serverHandshakeResponse()); 458f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 45951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 46051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (m_deflateFramer.enabled() && m_document) { 46151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) const String message = "WebSocket extension \"x-webkit-deflate-frame\" is deprecated"; 462e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_document->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message, m_sourceURLAtConstruction, m_lineNumberAtConstruction)); 46351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) } 46451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 465a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p Connected", this); 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(headerLength); 4675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) String subprotocol = m_handshake->serverWebSocketProtocol(); 4685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) String extensions = m_handshake->acceptedExtensions(); 4695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) m_client->didConnect(subprotocol.isNull() ? "" : subprotocol, extensions.isNull() ? "" : extensions); 470a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m_buffer", this, static_cast<unsigned long>(m_buffer.size())); 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !m_buffer.isEmpty(); 4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); 474a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); 4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(headerLength); 4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_shouldDiscardReceivedData = true; 47781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(m_handshake->failureReason()); 4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_handshake->mode() != WebSocketHandshake::Connected) 4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return processFrame(); 4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 48653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChannel>* timer) 4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(timer, timer == &m_resumeTimer); 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 490f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) processBuffer(); 4915267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!m_suspended && m_client && (m_state == ChannelClosed) && m_handle) 4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didCloseSocketStream(m_handle.get()); 4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 49553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::startClosingHandshake(int code, const String& reason) 4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 497a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p startClosingHandshake() code=%d m_state=%d m_receivedClosingHandshake=%d", this, code, m_state, m_receivedClosingHandshake); 4985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (m_state == ChannelClosing || m_state == ChannelClosed) 4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_handle); 5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<char> buf; 5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_receivedClosingHandshake && code != CloseEventCodeNotSpecified) { 5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char highByte = code >> 8; 5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char lowByte = code; 5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf.append(static_cast<char>(highByte)); 5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf.append(static_cast<char>(lowByte)); 5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) buf.append(reason.utf8().data(), reason.utf8().length()); 5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size()); 51153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_state = ChannelClosing; 5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_client) 5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didStartClosingHandshake(); 5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 51853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::closingTimerFired(Timer<MainThreadWebSocketChannel>* timer) 5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 520a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(Network, "MainThreadWebSocketChannel %p closingTimerFired()", this); 5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_UNUSED(timer, &m_closingTimer == timer); 52251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) disconnectHandle(); 5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 52653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool MainThreadWebSocketChannel::processFrame() 5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_buffer.isEmpty()); 5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WebSocketFrame frame; 5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const char* frameEnd; 5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String errorString; 5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffer.data(), m_buffer.size(), frame, frameEnd, errorString); 5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == WebSocketFrame::FrameIncomplete) 5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result == WebSocketFrame::FrameError) { 53781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(errorString); 5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_buffer.data() < frameEnd); 5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); 5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); 5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!inflateResult->succeeded()) { 54681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(inflateResult->failureReason()); 5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 54953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m_perMessageDeflate.inflate(frame)) { 55081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(m_perMessageDeflate.failureReason()); 55153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return false; 55253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Validate the frame data. 5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (WebSocketFrame::isReservedOpCode(frame.opCode)) { 55681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Unrecognized frame opcode: " + String::number(frame.opCode)); 5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (frame.compress || frame.reserved2 || frame.reserved3) { 56181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("One or more reserved bits are on: reserved1 = " + String::number(frame.compress) + ", reserved2 = " + String::number(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3)); 5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.masked) { 56681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("A server must not mask any frames that it sends to the client."); 5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // All control frames must not be fragmented. 5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { 57281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received fragmented control frame: opcode = " + String::number(frame.opCode)); 5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // All control frames must have a payload of 125 bytes or less, which means the frame must not contain 5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the "extended payload length" field. 5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsExtendedLengthField(frame.payloadLength)) { 57981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received control frame having too long payload: " + String::number(frame.payloadLength) + " bytes"); 5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // A new data frame is received before the previous continuous frame finishes. 5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Note that control frames are allowed to come in the middle of continuous frames. 5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) { 58609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) failAsError("Received start of new message but previous message is unfinished."); 5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 59009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); 5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (frame.opCode) { 5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeContinuation: 5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // An unexpected continuation frame is received without any leading frame. 5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_hasContinuousFrame) { 59681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received unexpected continuation frame."); 5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.append(frame.payload, frame.payloadLength); 6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.final) { 6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // onmessage handler may eventually call the other methods of this channel, 6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // so we should pretend that we have finished to read this frame and 6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // make sure that the member variables are in a consistent state before 6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the handler is invoked. 6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Vector<char>::swap() is used here to clear m_continuousFrameData. 6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char>); 6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.swap(*continuousFrameData); 6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = false; 6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { 6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String message; 6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (continuousFrameData->size()) 6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = String::fromUTF8(continuousFrameData->data(), continuousFrameData->size()); 6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = ""; 6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (message.isNull()) 61781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Could not decode a text frame as UTF-8."); 6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveMessage(message); 620d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) { 6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveBinaryData(continuousFrameData.release()); 622d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeText: 6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.final) { 6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String message; 6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.payloadLength) 6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = String::fromUTF8(frame.payload, frame.payloadLength); 6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) message = ""; 6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (message.isNull()) 63581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Could not decode a text frame as UTF-8."); 6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveMessage(message); 6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = true; 6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameOpCode = WebSocketFrame::OpCodeText; 6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_continuousFrameData.isEmpty()); 6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.append(frame.payload, frame.payloadLength); 6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeBinary: 6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.final) { 6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<Vector<char> > binaryData = adoptPtr(new Vector<char>(frame.payloadLength)); 6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(binaryData->data(), frame.payload, frame.payloadLength); 6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_client->didReceiveBinaryData(binaryData.release()); 6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_hasContinuousFrame = true; 6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameOpCode = WebSocketFrame::OpCodeBinary; 6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_continuousFrameData.isEmpty()); 6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_continuousFrameData.append(frame.payload, frame.payloadLength); 6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodeClose: 663d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!frame.payloadLength) { 6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = CloseEventCodeNoStatusRcvd; 665d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else if (frame.payloadLength == 1) { 6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = CloseEventCodeAbnormalClosure; 66781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received a broken close frame containing an invalid size body."); 6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char highByte = static_cast<unsigned char>(frame.payload[0]); 6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]); 6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = highByte << 8 | lowByte; 6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCode == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHandshake) { 6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventCode = CloseEventCodeAbnormalClosure; 67581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Received a broken close frame containing a reserved status code."); 6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (frame.payloadLength >= 3) 6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2); 6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_closeEventReason = ""; 6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_receivedClosingHandshake = true; 6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startClosingHandshake(m_closeEventCode, m_closeEventReason); 686521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) m_outgoingFrameQueueStatus = OutgoingFrameQueueClosing; 687521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) processOutgoingFrameQueue(); 6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodePing: 6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength); 6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 69353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) processOutgoingFrameQueue(); 6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case WebSocketFrame::OpCodePong: 6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // A server may send a pong in response to our ping, or an unsolicited pong which is not associated with 6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // any specific ping. Either way, there's nothing to do on receipt of pong. 6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: 7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) skipBuffer(frameEnd - m_buffer.data()); 7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 70853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_perMessageDeflate.resetInflateBuffer(); 7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !m_buffer.isEmpty(); 7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 71253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueTextFrame(const CString& string) 7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 715d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->opCode = WebSocketFrame::OpCodeText; 7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->frameType = QueuedFrameTypeString; 7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->stringData = string; 7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 72353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 726d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->opCode = opCode; 7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->frameType = QueuedFrameTypeVector; 7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->vectorData.resize(dataLength); 7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dataLength) 7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(frame->vectorData.data(), data, dataLength); 7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 736d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueVector(WebSocketFrame::OpCode opCode, PassOwnPtr<Vector<char> > data) 737d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 738d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 739d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 740d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 741d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) frame->opCode = opCode; 742d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) frame->frameType = QueuedFrameTypeVector; 743d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) frame->vectorData.swap(*data); 744d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 745d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 746d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void MainThreadWebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, PassRefPtr<BlobDataHandle> blobData) 7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen); 750d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame); 7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->opCode = opCode; 7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame->frameType = QueuedFrameTypeBlob; 7541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) frame->blobData = blobData; 7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.append(frame.release()); 7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::processOutgoingFrameQueue() 7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) 7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!m_outgoingFrameQueue.isEmpty()) { 7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); 7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (frame->frameType) { 7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case QueuedFrameTypeString: { 7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sendFrame(frame->opCode, frame->stringData.data(), frame->stringData.length())) 76881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket frame."); 7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case QueuedFrameTypeVector: 7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vectorData.size())) 77481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket frame."); 7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case QueuedFrameTypeBlob: { 7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (m_blobLoaderStatus) { 7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderNotStarted: 7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ref(); // Will be derefed after didFinishLoading() or didFail(). 7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_blobLoader); 7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::ReadAsArrayBuffer, this)); 7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderStarted; 7841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) m_blobLoader->start(m_document, frame->blobData); 7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.prepend(frame.release()); 7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderStarted: 7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderFailed: 7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.prepend(frame.release()); 7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case BlobLoaderFinished: { 7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); 7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader.clear(); 7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoaderStatus = BlobLoaderNotStarted; 7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!sendFrame(frame->opCode, static_cast<const char*>(result->data()), result->byteLength())) 79881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError("Failed to send WebSocket frame."); 7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: 8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_outgoingFrameQueue.isEmpty()); 8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosing) { 8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed; 8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_handle->close(); 8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 81853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void MainThreadWebSocketChannel::abortOutgoingFrameQueue() 8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueue.clear(); 8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed; 8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_blobLoaderStatus == BlobLoaderStarted) { 8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blobLoader->cancel(); 8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) didFail(FileError::ABORT_ERR); 8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 82853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_handle); 8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_suspended); 8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 83353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSocketFrame::Masked); 83409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, frame.opCode, frame.masked, frame.payload, frame.payloadLength); 8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); 8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!deflateResult->succeeded()) { 83881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(deflateResult->failureReason()); 8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 84253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!m_perMessageDeflate.deflate(frame)) { 84381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) failAsError(m_perMessageDeflate.failureReason()); 84453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return false; 84553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 84653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<char> frameData; 8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) frame.makeFrameData(frameData); 84976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles) m_framingOverheadQueue.append(FramingOverhead(opCode, frameData.size(), dataLength)); 8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 85153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) m_perMessageDeflate.resetDeflateBuffer(); 8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_handle->send(frameData.data(), frameData.size()); 8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 855197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid MainThreadWebSocketChannel::trace(Visitor* visitor) 856197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 857197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch visitor->trace(m_document); 858197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch visitor->trace(m_client); 859197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch visitor->trace(m_handshake); 860197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch visitor->trace(m_handle); 861197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch WebSocketChannel::trace(visitor); 862197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch SocketStreamHandleClient::trace(visitor); 863197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 864197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 865c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 866