Reduce use of SessionID::defaultSessionID() in WebKit
[WebKit-https.git] / Source / WebCore / Modules / websockets / WebSocketChannel.cpp
1 /*
2  * Copyright (C) 2011, 2012 Google Inc.  All rights reserved.
3  * Copyright (C) 2018 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "WebSocketChannel.h"
34
35 #include "Blob.h"
36 #include "ContentRuleListResults.h"
37 #include "CookieJar.h"
38 #include "Document.h"
39 #include "FileError.h"
40 #include "FileReaderLoader.h"
41 #include "Frame.h"
42 #include "FrameLoader.h"
43 #include "InspectorInstrumentation.h"
44 #include "Logging.h"
45 #include "NetworkingContext.h"
46 #include "Page.h"
47 #include "ProgressTracker.h"
48 #include "ResourceRequest.h"
49 #include "ScriptExecutionContext.h"
50 #include "SocketProvider.h"
51 #include "SocketStreamError.h"
52 #include "SocketStreamHandle.h"
53 #include "UserContentProvider.h"
54 #include "WebSocketChannelClient.h"
55 #include "WebSocketHandshake.h"
56 #include <JavaScriptCore/ArrayBuffer.h>
57 #include <wtf/FastMalloc.h>
58 #include <wtf/HashMap.h>
59 #include <wtf/text/CString.h>
60 #include <wtf/text/StringHash.h>
61
62 namespace WebCore {
63
64 const Seconds TCPMaximumSegmentLifetime { 2_min };
65
66 WebSocketChannel::WebSocketChannel(Document& document, WebSocketChannelClient& client, SocketProvider& provider)
67     : m_document(makeWeakPtr(document))
68     , m_client(makeWeakPtr(client))
69     , m_resumeTimer(*this, &WebSocketChannel::resumeTimerFired)
70     , m_closingTimer(*this, &WebSocketChannel::closingTimerFired)
71     , m_socketProvider(provider)
72 {
73     if (Page* page = document.page())
74         m_identifier = page->progress().createUniqueIdentifier();
75
76     LOG(Network, "WebSocketChannel %p ctor, identifier %u", this, m_identifier);
77 }
78
79 WebSocketChannel::~WebSocketChannel()
80 {
81     LOG(Network, "WebSocketChannel %p dtor", this);
82 }
83
84 WebSocketChannel::ConnectStatus WebSocketChannel::connect(const URL& requestedURL, const String& protocol)
85 {
86     LOG(Network, "WebSocketChannel %p connect()", this);
87
88     auto validatedURL = validateURL(*m_document, requestedURL);
89     if (!validatedURL)
90         return ConnectStatus::KO;
91     ASSERT(!m_handle);
92     ASSERT(!m_suspended);
93
94     if (validatedURL->url != requestedURL && m_client)
95         m_client->didUpgradeURL();
96
97     m_allowCookies = validatedURL->areCookiesAllowed;
98     String userAgent = m_document->userAgent(m_document->url());
99     String clientOrigin = m_document->securityOrigin().toString();
100     m_handshake = makeUnique<WebSocketHandshake>(validatedURL->url, protocol, userAgent, clientOrigin, m_allowCookies);
101     m_handshake->reset();
102     if (m_deflateFramer.canDeflate())
103         m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor());
104     if (m_identifier)
105         InspectorInstrumentation::didCreateWebSocket(m_document.get(), m_identifier, validatedURL->url);
106
107     auto* frame = m_document->frame();
108     auto* page = m_document->page();
109     if (!frame || !page)
110         return ConnectStatus::KO;
111
112     ref();
113     String partition = m_document->domainForCachePartition();
114     m_handle = m_socketProvider->createSocketStreamHandle(m_handshake->url(), *this, page->sessionID(), partition, frame->loader().networkingContext());
115     return ConnectStatus::OK;
116 }
117
118 Document* WebSocketChannel::document()
119 {
120     return m_document.get();
121 }
122
123 String WebSocketChannel::subprotocol()
124 {
125     LOG(Network, "WebSocketChannel %p subprotocol()", this);
126     if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected)
127         return emptyString();
128     String serverProtocol = m_handshake->serverWebSocketProtocol();
129     if (serverProtocol.isNull())
130         return emptyString();
131     return serverProtocol;
132 }
133
134 String WebSocketChannel::extensions()
135 {
136     LOG(Network, "WebSocketChannel %p extensions()", this);
137     if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected)
138         return emptyString();
139     String extensions = m_handshake->acceptedExtensions();
140     if (extensions.isNull())
141         return emptyString();
142     return extensions;
143 }
144
145 ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const String& message)
146 {
147     LOG(Network, "WebSocketChannel %p send() Sending String '%s'", this, message.utf8().data());
148     CString utf8 = message.utf8(StrictConversionReplacingUnpairedSurrogatesWithFFFD);
149     enqueueTextFrame(utf8);
150     processOutgoingFrameQueue();
151     // According to WebSocket API specification, WebSocket.send() should return void instead
152     // of boolean. However, our implementation still returns boolean due to compatibility
153     // concern (see bug 65850).
154     // m_channel->send() may happen later, thus it's not always possible to know whether
155     // the message has been sent to the socket successfully. In this case, we have no choice
156     // but to return true.
157     return ThreadableWebSocketChannel::SendSuccess;
158 }
159
160 ThreadableWebSocketChannel::SendResult WebSocketChannel::send(const ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength)
161 {
162     LOG(Network, "WebSocketChannel %p send() Sending ArrayBuffer %p byteOffset=%u byteLength=%u", this, &binaryData, byteOffset, byteLength);
163     enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()) + byteOffset, byteLength);
164     processOutgoingFrameQueue();
165     return ThreadableWebSocketChannel::SendSuccess;
166 }
167
168 ThreadableWebSocketChannel::SendResult WebSocketChannel::send(Blob& binaryData)
169 {
170     LOG(Network, "WebSocketChannel %p send() Sending Blob '%s'", this, binaryData.url().string().utf8().data());
171     enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData);
172     processOutgoingFrameQueue();
173     return ThreadableWebSocketChannel::SendSuccess;
174 }
175
176 bool WebSocketChannel::send(const char* data, int length)
177 {
178     LOG(Network, "WebSocketChannel %p send() Sending char* data=%p length=%d", this, data, length);
179     enqueueRawFrame(WebSocketFrame::OpCodeBinary, data, length);
180     processOutgoingFrameQueue();
181     return true;
182 }
183
184 unsigned WebSocketChannel::bufferedAmount() const
185 {
186     LOG(Network, "WebSocketChannel %p bufferedAmount()", this);
187     ASSERT(m_handle);
188     ASSERT(!m_suspended);
189     return m_handle->bufferedAmount();
190 }
191
192 void WebSocketChannel::close(int code, const String& reason)
193 {
194     LOG(Network, "WebSocketChannel %p close() code=%d reason='%s'", this, code, reason.utf8().data());
195     ASSERT(!m_suspended);
196     if (!m_handle)
197         return;
198     Ref<WebSocketChannel> protectedThis(*this); // An attempt to send closing handshake may fail, which will get the channel closed and dereferenced.
199     startClosingHandshake(code, reason);
200     if (m_closing && !m_closingTimer.isActive())
201         m_closingTimer.startOneShot(TCPMaximumSegmentLifetime * 2);
202 }
203
204 void WebSocketChannel::fail(const String& reason)
205 {
206     LOG(Network, "WebSocketChannel %p fail() reason='%s'", this, reason.utf8().data());
207     ASSERT(!m_suspended);
208     if (m_document) {
209         InspectorInstrumentation::didReceiveWebSocketFrameError(m_document.get(), m_identifier, reason);
210
211         String consoleMessage;
212         if (m_handshake)
213             consoleMessage = makeString("WebSocket connection to '", m_handshake->url().stringCenterEllipsizedToLength(), "' failed: ", reason);
214         else
215             consoleMessage = makeString("WebSocket connection failed: ", reason);
216
217         m_document->addConsoleMessage(MessageSource::Network, MessageLevel::Error, consoleMessage);
218     }
219
220     // Hybi-10 specification explicitly states we must not continue to handle incoming data
221     // once the WebSocket connection is failed (section 7.1.7).
222     Ref<WebSocketChannel> protectedThis(*this); // The client can close the channel, potentially removing the last reference.
223     m_shouldDiscardReceivedData = true;
224     if (!m_buffer.isEmpty())
225         skipBuffer(m_buffer.size()); // Save memory.
226     m_deflateFramer.didFail();
227     m_hasContinuousFrame = false;
228     m_continuousFrameData.clear();
229     if (m_client)
230         m_client->didReceiveMessageError();
231
232     if (m_handle && !m_closed)
233         m_handle->disconnect(); // Will call didCloseSocketStream() but maybe not synchronously.
234 }
235
236 void WebSocketChannel::disconnect()
237 {
238     LOG(Network, "WebSocketChannel %p disconnect()", this);
239     if (m_identifier && m_document)
240         InspectorInstrumentation::didCloseWebSocket(m_document.get(), m_identifier);
241     m_client = nullptr;
242     m_document = nullptr;
243     if (m_handle)
244         m_handle->disconnect();
245 }
246
247 void WebSocketChannel::suspend()
248 {
249     m_suspended = true;
250 }
251
252 void WebSocketChannel::resume()
253 {
254     m_suspended = false;
255     if ((!m_buffer.isEmpty() || m_closed) && m_client && !m_resumeTimer.isActive())
256         m_resumeTimer.startOneShot(0_s);
257 }
258
259 void WebSocketChannel::didOpenSocketStream(SocketStreamHandle& handle)
260 {
261     LOG(Network, "WebSocketChannel %p didOpenSocketStream()", this);
262     ASSERT(&handle == m_handle);
263     if (!m_document)
264         return;
265     if (m_identifier && UNLIKELY(InspectorInstrumentation::hasFrontends())) {
266         auto cookieRequestHeaderFieldValue = [document = m_document] (const URL& url) -> String {
267             if (!document || !document->page())
268                 return { };
269             return document->page()->cookieJar().cookieRequestHeaderFieldValue(*document, url);
270         };
271         InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document.get(), m_identifier, m_handshake->clientHandshakeRequest(WTFMove(cookieRequestHeaderFieldValue)));
272     }
273     auto handshakeMessage = m_handshake->clientHandshakeMessage();
274     Optional<CookieRequestHeaderFieldProxy> cookieRequestHeaderFieldProxy;
275     if (m_allowCookies)
276         cookieRequestHeaderFieldProxy = CookieJar::cookieRequestHeaderFieldProxy(*m_document, m_handshake->httpURLForAuthenticationAndCookies());
277     handle.sendHandshake(WTFMove(handshakeMessage), WTFMove(cookieRequestHeaderFieldProxy), [this, protectedThis = makeRef(*this)] (bool success, bool didAccessSecureCookies) {
278         if (!success)
279             fail("Failed to send WebSocket handshake.");
280
281         if (didAccessSecureCookies && m_document)
282             m_document->setSecureCookiesAccessed();
283     });
284 }
285
286 void WebSocketChannel::didCloseSocketStream(SocketStreamHandle& handle)
287 {
288     LOG(Network, "WebSocketChannel %p didCloseSocketStream()", this);
289     if (m_identifier && m_document)
290         InspectorInstrumentation::didCloseWebSocket(m_document.get(), m_identifier);
291     ASSERT_UNUSED(handle, &handle == m_handle || !m_handle);
292     m_closed = true;
293     if (m_closingTimer.isActive())
294         m_closingTimer.stop();
295     if (m_outgoingFrameQueueStatus != OutgoingFrameQueueClosed)
296         abortOutgoingFrameQueue();
297     if (m_handle) {
298         m_unhandledBufferedAmount = m_handle->bufferedAmount();
299         if (m_suspended)
300             return;
301         WebSocketChannelClient* client = m_client.get();
302         m_client = nullptr;
303         m_document = nullptr;
304         m_handle = nullptr;
305         if (client)
306             client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason);
307     }
308     deref();
309 }
310
311 void WebSocketChannel::didReceiveSocketStreamData(SocketStreamHandle& handle, const char* data, size_t length)
312 {
313     LOG(Network, "WebSocketChannel %p didReceiveSocketStreamData() Received %zu bytes", this, length);
314     Ref<WebSocketChannel> protectedThis(*this); // The client can close the channel, potentially removing the last reference.
315     ASSERT(&handle == m_handle);
316     if (!m_document) {
317         return;
318     }
319     if (!length) {
320         handle.disconnect();
321         return;
322     }
323     if (!m_client) {
324         m_shouldDiscardReceivedData = true;
325         handle.disconnect();
326         return;
327     }
328     if (m_shouldDiscardReceivedData)
329         return;
330     if (!appendToBuffer(data, length)) {
331         m_shouldDiscardReceivedData = true;
332         fail("Ran out of memory while receiving WebSocket data.");
333         return;
334     }
335     while (!m_suspended && m_client && !m_buffer.isEmpty()) {
336         if (!processBuffer())
337             break;
338     }
339 }
340
341 void WebSocketChannel::didFailToReceiveSocketStreamData(SocketStreamHandle& handle)
342 {
343     handle.disconnect();
344 }
345
346 void WebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle&, size_t bufferedAmount)
347 {
348     if (m_client)
349         m_client->didUpdateBufferedAmount(bufferedAmount);
350 }
351
352 void WebSocketChannel::didFailSocketStream(SocketStreamHandle& handle, const SocketStreamError& error)
353 {
354     LOG(Network, "WebSocketChannel %p didFailSocketStream()", this);
355     ASSERT(&handle == m_handle || !m_handle);
356     if (m_document) {
357         String message;
358         if (error.isNull())
359             message = "WebSocket network error"_s;
360         else if (error.localizedDescription().isNull())
361             message = makeString("WebSocket network error: error code ", error.errorCode());
362         else
363             message = "WebSocket network error: " + error.localizedDescription();
364         InspectorInstrumentation::didReceiveWebSocketFrameError(m_document.get(), m_identifier, message);
365         m_document->addConsoleMessage(MessageSource::Network, MessageLevel::Error, message);
366     }
367     m_shouldDiscardReceivedData = true;
368     if (m_client)
369         m_client->didReceiveMessageError();
370     handle.disconnect();
371 }
372
373 void WebSocketChannel::didStartLoading()
374 {
375     LOG(Network, "WebSocketChannel %p didStartLoading()", this);
376     ASSERT(m_blobLoader);
377     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
378 }
379
380 void WebSocketChannel::didReceiveData()
381 {
382     LOG(Network, "WebSocketChannel %p didReceiveData()", this);
383     ASSERT(m_blobLoader);
384     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
385 }
386
387 void WebSocketChannel::didFinishLoading()
388 {
389     LOG(Network, "WebSocketChannel %p didFinishLoading()", this);
390     ASSERT(m_blobLoader);
391     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
392     m_blobLoaderStatus = BlobLoaderFinished;
393     processOutgoingFrameQueue();
394     deref();
395 }
396
397 void WebSocketChannel::didFail(int errorCode)
398 {
399     LOG(Network, "WebSocketChannel %p didFail() errorCode=%d", this, errorCode);
400     ASSERT(m_blobLoader);
401     ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
402     m_blobLoader = nullptr;
403     m_blobLoaderStatus = BlobLoaderFailed;
404     fail(makeString("Failed to load Blob: error code = ", errorCode)); // FIXME: Generate human-friendly reason message.
405     deref();
406 }
407
408 bool WebSocketChannel::appendToBuffer(const char* data, size_t len)
409 {
410     size_t newBufferSize = m_buffer.size() + len;
411     if (newBufferSize < m_buffer.size()) {
412         LOG(Network, "WebSocketChannel %p appendToBuffer() Buffer overflow (%u bytes already in receive buffer and appending %u bytes)", this, static_cast<unsigned>(m_buffer.size()), static_cast<unsigned>(len));
413         return false;
414     }
415     m_buffer.append(data, len);
416     return true;
417 }
418
419 void WebSocketChannel::skipBuffer(size_t len)
420 {
421     ASSERT_WITH_SECURITY_IMPLICATION(len <= m_buffer.size());
422     memmove(m_buffer.data(), m_buffer.data() + len, m_buffer.size() - len);
423     m_buffer.shrink(m_buffer.size() - len);
424 }
425
426 bool WebSocketChannel::processBuffer()
427 {
428     ASSERT(!m_suspended);
429     ASSERT(m_client);
430     ASSERT(!m_buffer.isEmpty());
431     LOG(Network, "WebSocketChannel %p processBuffer() Receive buffer has %u bytes", this, static_cast<unsigned>(m_buffer.size()));
432
433     if (m_shouldDiscardReceivedData)
434         return false;
435
436     if (m_receivedClosingHandshake) {
437         skipBuffer(m_buffer.size());
438         return false;
439     }
440
441     Ref<WebSocketChannel> protectedThis(*this); // The client can close the channel, potentially removing the last reference.
442
443     if (m_handshake->mode() == WebSocketHandshake::Incomplete) {
444         int headerLength = m_handshake->readServerHandshake(m_buffer.data(), m_buffer.size());
445         if (headerLength <= 0)
446             return false;
447         if (m_handshake->mode() == WebSocketHandshake::Connected) {
448             if (m_identifier)
449                 InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document.get(), m_identifier, m_handshake->serverHandshakeResponse());
450             String serverSetCookie = m_handshake->serverSetCookie();
451             if (!serverSetCookie.isEmpty()) {
452                 if (m_document && m_document->page() && m_document->page()->cookieJar().cookiesEnabled(*m_document))
453                     m_document->page()->cookieJar().setCookies(*m_document, m_handshake->httpURLForAuthenticationAndCookies(), serverSetCookie);
454             }
455             LOG(Network, "WebSocketChannel %p Connected", this);
456             skipBuffer(headerLength);
457             m_client->didConnect();
458             LOG(Network, "WebSocketChannel %p %u bytes remaining in m_buffer", this, static_cast<unsigned>(m_buffer.size()));
459             return !m_buffer.isEmpty();
460         }
461         ASSERT(m_handshake->mode() == WebSocketHandshake::Failed);
462         LOG(Network, "WebSocketChannel %p Connection failed", this);
463         skipBuffer(headerLength);
464         m_shouldDiscardReceivedData = true;
465         fail(m_handshake->failureReason());
466         return false;
467     }
468     if (m_handshake->mode() != WebSocketHandshake::Connected)
469         return false;
470
471     return processFrame();
472 }
473
474 void WebSocketChannel::resumeTimerFired()
475 {
476     Ref<WebSocketChannel> protectedThis(*this); // The client can close the channel, potentially removing the last reference.
477     while (!m_suspended && m_client && !m_buffer.isEmpty())
478         if (!processBuffer())
479             break;
480     if (!m_suspended && m_client && m_closed && m_handle)
481         didCloseSocketStream(*m_handle);
482 }
483
484 void WebSocketChannel::startClosingHandshake(int code, const String& reason)
485 {
486     LOG(Network, "WebSocketChannel %p startClosingHandshake() code=%d m_receivedClosingHandshake=%d", this, m_closing, m_receivedClosingHandshake);
487     ASSERT(!m_closed);
488     if (m_closing)
489         return;
490     ASSERT(m_handle);
491
492     Vector<char> buf;
493     if (!m_receivedClosingHandshake && code != CloseEventCodeNotSpecified) {
494         unsigned char highByte = code >> 8;
495         unsigned char lowByte = code;
496         buf.append(static_cast<char>(highByte));
497         buf.append(static_cast<char>(lowByte));
498         auto reasonUTF8 = reason.utf8();
499         buf.append(reasonUTF8.data(), reasonUTF8.length());
500     }
501     enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size());
502     Ref<WebSocketChannel> protectedThis(*this); // An attempt to send closing handshake may fail, which will get the channel closed and dereferenced.
503     processOutgoingFrameQueue();
504
505     if (m_closed) {
506         // The channel got closed because processOutgoingFrameQueue() failed.
507         return;
508     }
509
510     m_closing = true;
511     if (m_client)
512         m_client->didStartClosingHandshake();
513 }
514
515 void WebSocketChannel::closingTimerFired()
516 {
517     LOG(Network, "WebSocketChannel %p closingTimerFired()", this);
518     if (m_handle)
519         m_handle->disconnect();
520 }
521
522
523 bool WebSocketChannel::processFrame()
524 {
525     ASSERT(!m_buffer.isEmpty());
526
527     WebSocketFrame frame;
528     const char* frameEnd;
529     String errorString;
530     WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffer.data(), m_buffer.size(), frame, frameEnd, errorString);
531     if (result == WebSocketFrame::FrameIncomplete)
532         return false;
533     if (result == WebSocketFrame::FrameError) {
534         fail(errorString);
535         return false;
536     }
537
538     ASSERT(m_buffer.data() < frameEnd);
539     ASSERT(frameEnd <= m_buffer.data() + m_buffer.size());
540
541     auto inflateResult = m_deflateFramer.inflate(frame);
542     if (!inflateResult->succeeded()) {
543         fail(inflateResult->failureReason());
544         return false;
545     }
546
547     // Validate the frame data.
548     if (WebSocketFrame::isReservedOpCode(frame.opCode)) {
549         fail(makeString("Unrecognized frame opcode: ", static_cast<unsigned>(frame.opCode)));
550         return false;
551     }
552
553     if (frame.reserved2 || frame.reserved3) {
554         fail(makeString("One or more reserved bits are on: reserved2 = ", static_cast<unsigned>(frame.reserved2), ", reserved3 = ", static_cast<unsigned>(frame.reserved3)));
555         return false;
556     }
557
558     if (frame.masked) {
559         fail("A server must not mask any frames that it sends to the client.");
560         return false;
561     }
562
563     // All control frames must not be fragmented.
564     if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) {
565         fail(makeString("Received fragmented control frame: opcode = ", static_cast<unsigned>(frame.opCode)));
566         return false;
567     }
568
569     // All control frames must have a payload of 125 bytes or less, which means the frame must not contain
570     // the "extended payload length" field.
571     if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsExtendedLengthField(frame.payloadLength)) {
572         fail(makeString("Received control frame having too long payload: ", frame.payloadLength, " bytes"));
573         return false;
574     }
575
576     // A new data frame is received before the previous continuous frame finishes.
577     // Note that control frames are allowed to come in the middle of continuous frames.
578     if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) {
579         fail("Received new data frame but previous continuous frame is unfinished.");
580         return false;
581     }
582
583     InspectorInstrumentation::didReceiveWebSocketFrame(m_document.get(), m_identifier, frame);
584
585     switch (frame.opCode) {
586     case WebSocketFrame::OpCodeContinuation:
587         // An unexpected continuation frame is received without any leading frame.
588         if (!m_hasContinuousFrame) {
589             fail("Received unexpected continuation frame.");
590             return false;
591         }
592         m_continuousFrameData.append(frame.payload, frame.payloadLength);
593         skipBuffer(frameEnd - m_buffer.data());
594         if (frame.final) {
595             // onmessage handler may eventually call the other methods of this channel,
596             // so we should pretend that we have finished to read this frame and
597             // make sure that the member variables are in a consistent state before
598             // the handler is invoked.
599             Vector<uint8_t> continuousFrameData = WTFMove(m_continuousFrameData);
600             m_hasContinuousFrame = false;
601             if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) {
602                 String message;
603                 if (continuousFrameData.size())
604                     message = String::fromUTF8(continuousFrameData.data(), continuousFrameData.size());
605                 else
606                     message = emptyString();
607                 if (message.isNull())
608                     fail("Could not decode a text frame as UTF-8.");
609                 else
610                     m_client->didReceiveMessage(message);
611             } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary)
612                 m_client->didReceiveBinaryData(WTFMove(continuousFrameData));
613         }
614         break;
615
616     case WebSocketFrame::OpCodeText:
617         if (frame.final) {
618             String message;
619             if (frame.payloadLength)
620                 message = String::fromUTF8(frame.payload, frame.payloadLength);
621             else
622                 message = emptyString();
623             skipBuffer(frameEnd - m_buffer.data());
624             if (message.isNull())
625                 fail("Could not decode a text frame as UTF-8.");
626             else
627                 m_client->didReceiveMessage(message);
628         } else {
629             m_hasContinuousFrame = true;
630             m_continuousFrameOpCode = WebSocketFrame::OpCodeText;
631             ASSERT(m_continuousFrameData.isEmpty());
632             m_continuousFrameData.append(frame.payload, frame.payloadLength);
633             skipBuffer(frameEnd - m_buffer.data());
634         }
635         break;
636
637     case WebSocketFrame::OpCodeBinary:
638         if (frame.final) {
639             Vector<uint8_t> binaryData(frame.payloadLength);
640             memcpy(binaryData.data(), frame.payload, frame.payloadLength);
641             skipBuffer(frameEnd - m_buffer.data());
642             m_client->didReceiveBinaryData(WTFMove(binaryData));
643         } else {
644             m_hasContinuousFrame = true;
645             m_continuousFrameOpCode = WebSocketFrame::OpCodeBinary;
646             ASSERT(m_continuousFrameData.isEmpty());
647             m_continuousFrameData.append(frame.payload, frame.payloadLength);
648             skipBuffer(frameEnd - m_buffer.data());
649         }
650         break;
651
652     case WebSocketFrame::OpCodeClose:
653         if (!frame.payloadLength)
654             m_closeEventCode = CloseEventCodeNoStatusRcvd;
655         else if (frame.payloadLength == 1) {
656             m_closeEventCode = CloseEventCodeAbnormalClosure;
657             fail("Received a broken close frame containing an invalid size body.");
658             return false;
659         } else {
660             unsigned char highByte = static_cast<unsigned char>(frame.payload[0]);
661             unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]);
662             m_closeEventCode = highByte << 8 | lowByte;
663             if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCode == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHandshake) {
664                 m_closeEventCode = CloseEventCodeAbnormalClosure;
665                 fail("Received a broken close frame containing a reserved status code.");
666                 return false;
667             }
668         }
669         if (frame.payloadLength >= 3)
670             m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2);
671         else
672             m_closeEventReason = emptyString();
673         skipBuffer(frameEnd - m_buffer.data());
674         m_receivedClosingHandshake = true;
675         startClosingHandshake(m_closeEventCode, m_closeEventReason);
676         if (m_closing) {
677             if (m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen)
678                 m_outgoingFrameQueueStatus = OutgoingFrameQueueClosing;
679             processOutgoingFrameQueue();
680         }
681         break;
682
683     case WebSocketFrame::OpCodePing:
684         enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength);
685         skipBuffer(frameEnd - m_buffer.data());
686         processOutgoingFrameQueue();
687         break;
688
689     case WebSocketFrame::OpCodePong:
690         // A server may send a pong in response to our ping, or an unsolicited pong which is not associated with
691         // any specific ping. Either way, there's nothing to do on receipt of pong.
692         skipBuffer(frameEnd - m_buffer.data());
693         break;
694
695     default:
696         ASSERT_NOT_REACHED();
697         skipBuffer(frameEnd - m_buffer.data());
698         break;
699     }
700
701     return !m_buffer.isEmpty();
702 }
703
704 void WebSocketChannel::enqueueTextFrame(const CString& string)
705 {
706     ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
707     auto frame = makeUnique<QueuedFrame>();
708     frame->opCode = WebSocketFrame::OpCodeText;
709     frame->frameType = QueuedFrameTypeString;
710     frame->stringData = string;
711     m_outgoingFrameQueue.append(WTFMove(frame));
712 }
713
714 void WebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
715 {
716     ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
717     auto frame = makeUnique<QueuedFrame>();
718     frame->opCode = opCode;
719     frame->frameType = QueuedFrameTypeVector;
720     frame->vectorData.resize(dataLength);
721     if (dataLength)
722         memcpy(frame->vectorData.data(), data, dataLength);
723     m_outgoingFrameQueue.append(WTFMove(frame));
724 }
725
726 void WebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, Blob& blob)
727 {
728     ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
729     auto frame = makeUnique<QueuedFrame>();
730     frame->opCode = opCode;
731     frame->frameType = QueuedFrameTypeBlob;
732     frame->blobData = &blob;
733     m_outgoingFrameQueue.append(WTFMove(frame));
734 }
735
736 void WebSocketChannel::processOutgoingFrameQueue()
737 {
738     if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed)
739         return;
740
741     Ref<WebSocketChannel> protectedThis(*this); // Any call to fail() will get the channel closed and dereferenced.
742
743     while (!m_outgoingFrameQueue.isEmpty()) {
744         auto frame = m_outgoingFrameQueue.takeFirst();
745         switch (frame->frameType) {
746         case QueuedFrameTypeString: {
747             sendFrame(frame->opCode, frame->stringData.data(), frame->stringData.length(), [this, protectedThis = makeRef(*this)] (bool success) {
748                 if (!success)
749                     fail("Failed to send WebSocket frame.");
750             });
751             break;
752         }
753
754         case QueuedFrameTypeVector:
755             sendFrame(frame->opCode, frame->vectorData.data(), frame->vectorData.size(), [this, protectedThis = makeRef(*this)] (bool success) {
756                 if (!success)
757                     fail("Failed to send WebSocket frame.");
758             });
759             break;
760
761         case QueuedFrameTypeBlob: {
762             switch (m_blobLoaderStatus) {
763             case BlobLoaderNotStarted:
764                 ref(); // Will be derefed after didFinishLoading() or didFail().
765                 ASSERT(!m_blobLoader);
766                 ASSERT(frame->blobData);
767                 m_blobLoader = makeUnique<FileReaderLoader>(FileReaderLoader::ReadAsArrayBuffer, this);
768                 m_blobLoaderStatus = BlobLoaderStarted;
769                 m_blobLoader->start(m_document.get(), *frame->blobData);
770                 m_outgoingFrameQueue.prepend(WTFMove(frame));
771                 return;
772
773             case BlobLoaderStarted:
774             case BlobLoaderFailed:
775                 m_outgoingFrameQueue.prepend(WTFMove(frame));
776                 return;
777
778             case BlobLoaderFinished: {
779                 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult();
780                 m_blobLoader = nullptr;
781                 m_blobLoaderStatus = BlobLoaderNotStarted;
782                 sendFrame(frame->opCode, static_cast<const char*>(result->data()), result->byteLength(), [this, protectedThis = makeRef(*this)] (bool success) {
783                     if (!success)
784                         fail("Failed to send WebSocket frame.");
785                 });
786                 break;
787             }
788             }
789             break;
790         }
791
792         default:
793             ASSERT_NOT_REACHED();
794             break;
795         }
796     }
797
798     ASSERT(m_outgoingFrameQueue.isEmpty());
799     if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosing) {
800         m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed;
801         m_handle->close();
802     }
803 }
804
805 void WebSocketChannel::abortOutgoingFrameQueue()
806 {
807     m_outgoingFrameQueue.clear();
808     m_outgoingFrameQueueStatus = OutgoingFrameQueueClosed;
809     if (m_blobLoaderStatus == BlobLoaderStarted) {
810         m_blobLoader->cancel();
811         didFail(FileError::ABORT_ERR);
812     }
813 }
814
815 void WebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength, WTF::Function<void(bool)> completionHandler)
816 {
817     ASSERT(m_handle);
818     ASSERT(!m_suspended);
819
820     WebSocketFrame frame(opCode, true, false, true, data, dataLength);
821     InspectorInstrumentation::didSendWebSocketFrame(m_document.get(), m_identifier, frame);
822
823     auto deflateResult = m_deflateFramer.deflate(frame);
824     if (!deflateResult->succeeded()) {
825         fail(deflateResult->failureReason());
826         return completionHandler(false);
827     }
828
829     Vector<char> frameData;
830     frame.makeFrameData(frameData);
831
832     m_handle->sendData(frameData.data(), frameData.size(), WTFMove(completionHandler));
833 }
834
835 ResourceRequest WebSocketChannel::clientHandshakeRequest(Function<String(const URL&)>&& cookieRequestHeaderFieldValue)
836 {
837     return m_handshake->clientHandshakeRequest(WTFMove(cookieRequestHeaderFieldValue));
838 }
839
840 const ResourceResponse& WebSocketChannel::serverHandshakeResponse() const
841 {
842     return m_handshake->serverHandshakeResponse();
843 }
844
845 WebSocketHandshake::Mode WebSocketChannel::handshakeMode() const
846 {
847     return m_handshake->mode();
848 }
849
850 } // namespace WebCore