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