Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(564)

Side by Side Diff: Source/modules/websockets/MainThreadWebSocketChannel.cpp

Issue 14657008: Make websocket error messages look better at the devtools console. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 #include "wtf/text/CString.h" 65 #include "wtf/text/CString.h"
66 #include "wtf/text/StringHash.h" 66 #include "wtf/text/StringHash.h"
67 #include "wtf/text/WTFString.h" 67 #include "wtf/text/WTFString.h"
68 68
69 using namespace std; 69 using namespace std;
70 70
71 namespace WebCore { 71 namespace WebCore {
72 72
73 const double TCPMaximumSegmentLifetime = 2 * 60.0; 73 const double TCPMaximumSegmentLifetime = 2 * 60.0;
74 74
75 MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSo cketChannelClient* client) 75 MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSo cketChannelClient* client, const ScriptCallFrame& callFrame)
76 : m_document(document) 76 : m_document(document)
77 , m_client(client) 77 , m_client(client)
78 , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired) 78 , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired)
79 , m_suspended(false) 79 , m_suspended(false)
80 , m_closing(false) 80 , m_closing(false)
81 , m_didFailOfClientAlreadyRun(false) 81 , m_didFailOfClientAlreadyRun(false)
82 , m_receivedClosingHandshake(false) 82 , m_receivedClosingHandshake(false)
83 , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) 83 , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired)
84 , m_closed(false) 84 , m_closed(false)
85 , m_shouldDiscardReceivedData(false) 85 , m_shouldDiscardReceivedData(false)
86 , m_unhandledBufferedAmount(0) 86 , m_unhandledBufferedAmount(0)
87 , m_identifier(0) 87 , m_identifier(0)
88 , m_hasContinuousFrame(false) 88 , m_hasContinuousFrame(false)
89 , m_closeEventCode(CloseEventCodeAbnormalClosure) 89 , m_closeEventCode(CloseEventCodeAbnormalClosure)
90 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) 90 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen)
91 , m_blobLoaderStatus(BlobLoaderNotStarted) 91 , m_blobLoaderStatus(BlobLoaderNotStarted)
92 , m_callFrameAtConnection("", "", 0) 92 , m_callFrameAtConnection(callFrame)
93 { 93 {
94 if (Page* page = m_document->page()) 94 if (Page* page = m_document->page())
95 m_identifier = createUniqueIdentifier(); 95 m_identifier = createUniqueIdentifier();
96 } 96 }
97 97
98 MainThreadWebSocketChannel::~MainThreadWebSocketChannel() 98 MainThreadWebSocketChannel::~MainThreadWebSocketChannel()
99 { 99 {
100 } 100 }
101 101
102 void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol ) 102 void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol )
103 { 103 {
104 LOG(Network, "MainThreadWebSocketChannel %p connect()", this); 104 LOG(Network, "MainThreadWebSocketChannel %p connect()", this);
105 ASSERT(!m_handle); 105 ASSERT(!m_handle);
106 ASSERT(!m_suspended); 106 ASSERT(!m_suspended);
107 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); 107 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document));
108 m_handshake->reset(); 108 m_handshake->reset();
109 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor( )); 109 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor( ));
110 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled()) 110 if (RuntimeEnabledFeatures::experimentalWebSocketEnabled())
111 m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionPr ocessor()); 111 m_handshake->addExtensionProcessor(m_perMessageDeflate.createExtensionPr ocessor());
112 if (m_identifier) 112 if (m_identifier)
113 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, u rl, m_document->url(), protocol); 113 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, u rl, m_document->url(), protocol);
114 ref(); 114 ref();
115 m_handle = SocketStreamHandle::create(m_handshake->url(), this); 115 m_handle = SocketStreamHandle::create(m_handshake->url(), this);
116 RefPtr<ScriptCallStack> callstack = createScriptCallStack(1, true); 116 RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true);
117 m_callFrameAtConnection = callstack && callstack->size() > 0 ? callstack->at (0) : ScriptCallFrame("", "", 0); 117 if (callStack && callStack->size() > 0)
118 m_callFrameAtConnection = callStack->at(0);
118 } 119 }
119 120
120 String MainThreadWebSocketChannel::subprotocol() 121 String MainThreadWebSocketChannel::subprotocol()
121 { 122 {
122 LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this); 123 LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this);
123 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) 124 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected)
124 return ""; 125 return "";
125 String serverProtocol = m_handshake->serverWebSocketProtocol(); 126 String serverProtocol = m_handshake->serverWebSocketProtocol();
126 if (serverProtocol.isNull()) 127 if (serverProtocol.isNull())
127 return ""; 128 return "";
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 { 191 {
191 LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", th is, code, reason.utf8().data()); 192 LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", th is, code, reason.utf8().data());
192 ASSERT(!m_suspended); 193 ASSERT(!m_suspended);
193 if (!m_handle) 194 if (!m_handle)
194 return; 195 return;
195 startClosingHandshake(code, reason); 196 startClosingHandshake(code, reason);
196 if (m_closing && !m_closingTimer.isActive()) 197 if (m_closing && !m_closingTimer.isActive())
197 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); 198 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime);
198 } 199 }
199 200
200 void MainThreadWebSocketChannel::fail(const String& reason) 201 void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level)
202 {
203 fail(reason, level, PassOwnPtr<CallStackWrapper>());
204 }
205
206 void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, PassOwnPtr<CallStackWrapper> wrapper)
201 { 207 {
202 LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reaso n.utf8().data()); 208 LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reaso n.utf8().data());
203 ASSERT(!m_suspended); 209 ASSERT(!m_suspended);
204 if (m_document) { 210 if (m_document) {
205 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_id entifier, reason); 211 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_id entifier, reason);
206 const String message = "WebSocket connection to '" + m_handshake->url(). elidedString() + "' failed: " + reason; 212 const String message = "WebSocket connection to '" + m_handshake->url(). elidedString() + "' failed: " + reason;
207 RefPtr<ScriptCallStack> callstack = createScriptCallStack(1, true); 213 RefPtr<ScriptCallStack> callStack = wrapper ? wrapper->createCallStack() : 0;
208 if (callstack && callstack->size() > 0) { 214 if (callStack && callStack->size() > 0) {
209 // We are in a JS callstack. 215 String url = callStack->at(0).sourceURL();
210 // So, the addConsoleMessage method will show the stack appropriatel y. 216 unsigned lineNumber = callStack->at(0).lineNumber();
211 m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, me ssage); 217 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMessage( JSMessageSource, level, message, url, lineNumber);
212 } else { 218 } else {
213 // We are not in a JS callstack. 219 RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true);
214 // Then show the source file and the line number at the connection i nitiation. 220 if (callStack && callStack->size() > 0) {
215 const String& url = m_callFrameAtConnection.sourceURL(); 221 // We are in a JS callstack.
216 unsigned lineNumber = m_callFrameAtConnection.lineNumber(); 222 // So, the addConsoleMessage method will show the stack appropri ately.
217 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMessage( JSMessageSource, ErrorMessageLevel, message, url, lineNumber, 0, 0); 223 m_document->addConsoleMessage(JSMessageSource, level, message);
224 } else {
225 // We are not in a JS callstack.
226 // Then show the source file and the line number at the connecti on initiation.
227 const String& url = m_callFrameAtConnection.sourceURL();
228 unsigned lineNumber = m_callFrameAtConnection.lineNumber();
229 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMess age(JSMessageSource, level, message, url, lineNumber);
230 }
218 } 231 }
219 } 232 }
233 failInternal();
234 }
220 235
236 void MainThreadWebSocketChannel::failInternal()
237 {
221 // Hybi-10 specification explicitly states we must not continue to handle in coming data 238 // Hybi-10 specification explicitly states we must not continue to handle in coming data
222 // once the WebSocket connection is failed (section 7.1.7). 239 // once the WebSocket connection is failed (section 7.1.7).
223 RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close th e channel, potentially removing the last reference. 240 RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close th e channel, potentially removing the last reference.
224 m_shouldDiscardReceivedData = true; 241 m_shouldDiscardReceivedData = true;
225 if (!m_buffer.isEmpty()) 242 if (!m_buffer.isEmpty())
226 skipBuffer(m_buffer.size()); // Save memory. 243 skipBuffer(m_buffer.size()); // Save memory.
227 m_deflateFramer.didFail(); 244 m_deflateFramer.didFail();
228 m_perMessageDeflate.didFail(); 245 m_perMessageDeflate.didFail();
229 m_hasContinuousFrame = false; 246 m_hasContinuousFrame = false;
230 m_continuousFrameData.clear(); 247 m_continuousFrameData.clear();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) 290 void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle)
274 { 291 {
275 LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); 292 LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this);
276 ASSERT(handle == m_handle); 293 ASSERT(handle == m_handle);
277 if (!m_document) 294 if (!m_document)
278 return; 295 return;
279 if (m_identifier) 296 if (m_identifier)
280 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, *m_handshake->clientHandshakeRequest()); 297 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, *m_handshake->clientHandshakeRequest());
281 CString handshakeMessage = m_handshake->clientHandshakeMessage(); 298 CString handshakeMessage = m_handshake->clientHandshakeMessage();
282 if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) 299 if (!handle->send(handshakeMessage.data(), handshakeMessage.length()))
283 fail("Failed to send WebSocket handshake."); 300 failAsError("Failed to send WebSocket handshake.");
284 } 301 }
285 302
286 void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle ) 303 void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle )
287 { 304 {
288 LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); 305 LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this);
289 if (m_identifier && m_document) 306 if (m_identifier && m_document)
290 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); 307 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier);
291 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); 308 ASSERT_UNUSED(handle, handle == m_handle || !m_handle);
292 m_closed = true; 309 m_closed = true;
293 if (m_closingTimer.isActive()) 310 if (m_closingTimer.isActive())
(...skipping 27 matching lines...) Expand all
321 } 338 }
322 if (!m_client) { 339 if (!m_client) {
323 m_shouldDiscardReceivedData = true; 340 m_shouldDiscardReceivedData = true;
324 handle->disconnect(); 341 handle->disconnect();
325 return; 342 return;
326 } 343 }
327 if (m_shouldDiscardReceivedData) 344 if (m_shouldDiscardReceivedData)
328 return; 345 return;
329 if (!appendToBuffer(data, len)) { 346 if (!appendToBuffer(data, len)) {
330 m_shouldDiscardReceivedData = true; 347 m_shouldDiscardReceivedData = true;
331 fail("Ran out of memory while receiving WebSocket data."); 348 failAsError("Ran out of memory while receiving WebSocket data.");
332 return; 349 return;
333 } 350 }
334 while (!m_suspended && m_client && !m_buffer.isEmpty()) 351 while (!m_suspended && m_client && !m_buffer.isEmpty())
335 if (!processBuffer()) 352 if (!processBuffer())
336 break; 353 break;
337 } 354 }
338 355
339 void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, si ze_t bufferedAmount) 356 void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, si ze_t bufferedAmount)
340 { 357 {
341 if (m_client) 358 if (m_client)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 deref(); 409 deref();
393 } 410 }
394 411
395 void MainThreadWebSocketChannel::didFail(int errorCode) 412 void MainThreadWebSocketChannel::didFail(int errorCode)
396 { 413 {
397 LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, e rrorCode); 414 LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, e rrorCode);
398 ASSERT(m_blobLoader); 415 ASSERT(m_blobLoader);
399 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); 416 ASSERT(m_blobLoaderStatus == BlobLoaderStarted);
400 m_blobLoader.clear(); 417 m_blobLoader.clear();
401 m_blobLoaderStatus = BlobLoaderFailed; 418 m_blobLoaderStatus = BlobLoaderFailed;
402 fail("Failed to load Blob: error code = " + String::number(errorCode)); // F IXME: Generate human-friendly reason message. 419 failAsError("Failed to load Blob: error code = " + String::number(errorCode) ); // FIXME: Generate human-friendly reason message.
403 deref(); 420 deref();
404 } 421 }
405 422
406 bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) 423 bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len)
407 { 424 {
408 size_t newBufferSize = m_buffer.size() + len; 425 size_t newBufferSize = m_buffer.size() + len;
409 if (newBufferSize < m_buffer.size()) { 426 if (newBufferSize < m_buffer.size()) {
410 LOG(Network, "MainThreadWebSocketChannel %p appendToBuffer() Buffer over flow (%lu bytes already in receive buffer and appending %lu bytes)", this, stati c_cast<unsigned long>(m_buffer.size()), static_cast<unsigned long>(len)); 427 LOG(Network, "MainThreadWebSocketChannel %p appendToBuffer() Buffer over flow (%lu bytes already in receive buffer and appending %lu bytes)", this, stati c_cast<unsigned long>(m_buffer.size()), static_cast<unsigned long>(len));
411 return false; 428 return false;
412 } 429 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 LOG(Network, "MainThreadWebSocketChannel %p Connected", this); 472 LOG(Network, "MainThreadWebSocketChannel %p Connected", this);
456 skipBuffer(headerLength); 473 skipBuffer(headerLength);
457 m_client->didConnect(); 474 m_client->didConnect();
458 LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m _buffer", this, static_cast<unsigned long>(m_buffer.size())); 475 LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m _buffer", this, static_cast<unsigned long>(m_buffer.size()));
459 return !m_buffer.isEmpty(); 476 return !m_buffer.isEmpty();
460 } 477 }
461 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); 478 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed);
462 LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); 479 LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this);
463 skipBuffer(headerLength); 480 skipBuffer(headerLength);
464 m_shouldDiscardReceivedData = true; 481 m_shouldDiscardReceivedData = true;
465 fail(m_handshake->failureReason()); 482 failAsError(m_handshake->failureReason());
466 return false; 483 return false;
467 } 484 }
468 if (m_handshake->mode() != WebSocketHandshake::Connected) 485 if (m_handshake->mode() != WebSocketHandshake::Connected)
469 return false; 486 return false;
470 487
471 return processFrame(); 488 return processFrame();
472 } 489 }
473 490
474 void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann el>* timer) 491 void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann el>* timer)
475 { 492 {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 { 536 {
520 ASSERT(!m_buffer.isEmpty()); 537 ASSERT(!m_buffer.isEmpty());
521 538
522 WebSocketFrame frame; 539 WebSocketFrame frame;
523 const char* frameEnd; 540 const char* frameEnd;
524 String errorString; 541 String errorString;
525 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffe r.data(), m_buffer.size(), frame, frameEnd, errorString); 542 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffe r.data(), m_buffer.size(), frame, frameEnd, errorString);
526 if (result == WebSocketFrame::FrameIncomplete) 543 if (result == WebSocketFrame::FrameIncomplete)
527 return false; 544 return false;
528 if (result == WebSocketFrame::FrameError) { 545 if (result == WebSocketFrame::FrameError) {
529 fail(errorString); 546 failAsError(errorString);
530 return false; 547 return false;
531 } 548 }
532 549
533 ASSERT(m_buffer.data() < frameEnd); 550 ASSERT(m_buffer.data() < frameEnd);
534 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); 551 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size());
535 552
536 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); 553 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame);
537 if (!inflateResult->succeeded()) { 554 if (!inflateResult->succeeded()) {
538 fail(inflateResult->failureReason()); 555 failAsError(inflateResult->failureReason());
539 return false; 556 return false;
540 } 557 }
541 if (!m_perMessageDeflate.inflate(frame)) { 558 if (!m_perMessageDeflate.inflate(frame)) {
542 fail(m_perMessageDeflate.failureReason()); 559 failAsError(m_perMessageDeflate.failureReason());
543 return false; 560 return false;
544 } 561 }
545 562
546 // Validate the frame data. 563 // Validate the frame data.
547 if (WebSocketFrame::isReservedOpCode(frame.opCode)) { 564 if (WebSocketFrame::isReservedOpCode(frame.opCode)) {
548 fail("Unrecognized frame opcode: " + String::number(frame.opCode)); 565 failAsError("Unrecognized frame opcode: " + String::number(frame.opCode) );
549 return false; 566 return false;
550 } 567 }
551 568
552 if (frame.compress || frame.reserved2 || frame.reserved3) { 569 if (frame.compress || frame.reserved2 || frame.reserved3) {
553 fail("One or more reserved bits are on: reserved1 = " + String::number(f rame.compress) + ", reserved2 = " + String::number(frame.reserved2) + ", reserve d3 = " + String::number(frame.reserved3)); 570 failAsError("One or more reserved bits are on: reserved1 = " + String::n umber(frame.compress) + ", reserved2 = " + String::number(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3));
554 return false; 571 return false;
555 } 572 }
556 573
557 if (frame.masked) { 574 if (frame.masked) {
558 fail("A server must not mask any frames that it sends to the client."); 575 failAsError("A server must not mask any frames that it sends to the clie nt.");
559 return false; 576 return false;
560 } 577 }
561 578
562 // All control frames must not be fragmented. 579 // All control frames must not be fragmented.
563 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { 580 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) {
564 fail("Received fragmented control frame: opcode = " + String::number(fra me.opCode)); 581 failAsError("Received fragmented control frame: opcode = " + String::num ber(frame.opCode));
565 return false; 582 return false;
566 } 583 }
567 584
568 // All control frames must have a payload of 125 bytes or less, which means the frame must not contain 585 // 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. 586 // the "extended payload length" field.
570 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsEx tendedLengthField(frame.payloadLength)) { 587 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsEx tendedLengthField(frame.payloadLength)) {
571 fail("Received control frame having too long payload: " + String::number (frame.payloadLength) + " bytes"); 588 failAsError("Received control frame having too long payload: " + String: :number(frame.payloadLength) + " bytes");
572 return false; 589 return false;
573 } 590 }
574 591
575 // A new data frame is received before the previous continuous frame finishe s. 592 // A new data frame is received before the previous continuous frame finishe s.
576 // Note that control frames are allowed to come in the middle of continuous frames. 593 // Note that control frames are allowed to come in the middle of continuous frames.
577 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuati on && !WebSocketFrame::isControlOpCode(frame.opCode)) { 594 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuati on && !WebSocketFrame::isControlOpCode(frame.opCode)) {
578 fail("Received new data frame but previous continuous frame is unfinishe d."); 595 failAsError("Received new data frame but previous continuous frame is un finished.");
579 return false; 596 return false;
580 } 597 }
581 598
582 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame); 599 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame);
583 600
584 switch (frame.opCode) { 601 switch (frame.opCode) {
585 case WebSocketFrame::OpCodeContinuation: 602 case WebSocketFrame::OpCodeContinuation:
586 // An unexpected continuation frame is received without any leading fram e. 603 // An unexpected continuation frame is received without any leading fram e.
587 if (!m_hasContinuousFrame) { 604 if (!m_hasContinuousFrame) {
588 fail("Received unexpected continuation frame."); 605 failAsError("Received unexpected continuation frame.");
589 return false; 606 return false;
590 } 607 }
591 m_continuousFrameData.append(frame.payload, frame.payloadLength); 608 m_continuousFrameData.append(frame.payload, frame.payloadLength);
592 skipBuffer(frameEnd - m_buffer.data()); 609 skipBuffer(frameEnd - m_buffer.data());
593 if (frame.final) { 610 if (frame.final) {
594 // onmessage handler may eventually call the other methods of this c hannel, 611 // onmessage handler may eventually call the other methods of this c hannel,
595 // so we should pretend that we have finished to read this frame and 612 // 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 bef ore 613 // make sure that the member variables are in a consistent state bef ore
597 // the handler is invoked. 614 // the handler is invoked.
598 // Vector<char>::swap() is used here to clear m_continuousFrameData. 615 // Vector<char>::swap() is used here to clear m_continuousFrameData.
599 OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char >); 616 OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char >);
600 m_continuousFrameData.swap(*continuousFrameData); 617 m_continuousFrameData.swap(*continuousFrameData);
601 m_hasContinuousFrame = false; 618 m_hasContinuousFrame = false;
602 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { 619 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) {
603 String message; 620 String message;
604 if (continuousFrameData->size()) 621 if (continuousFrameData->size())
605 message = String::fromUTF8(continuousFrameData->data(), cont inuousFrameData->size()); 622 message = String::fromUTF8(continuousFrameData->data(), cont inuousFrameData->size());
606 else 623 else
607 message = ""; 624 message = "";
608 if (message.isNull()) 625 if (message.isNull())
609 fail("Could not decode a text frame as UTF-8."); 626 failAsError("Could not decode a text frame as UTF-8.");
610 else 627 else
611 m_client->didReceiveMessage(message); 628 m_client->didReceiveMessage(message);
612 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) 629 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary)
613 m_client->didReceiveBinaryData(continuousFrameData.release()); 630 m_client->didReceiveBinaryData(continuousFrameData.release());
614 } 631 }
615 break; 632 break;
616 633
617 case WebSocketFrame::OpCodeText: 634 case WebSocketFrame::OpCodeText:
618 if (frame.final) { 635 if (frame.final) {
619 String message; 636 String message;
620 if (frame.payloadLength) 637 if (frame.payloadLength)
621 message = String::fromUTF8(frame.payload, frame.payloadLength); 638 message = String::fromUTF8(frame.payload, frame.payloadLength);
622 else 639 else
623 message = ""; 640 message = "";
624 skipBuffer(frameEnd - m_buffer.data()); 641 skipBuffer(frameEnd - m_buffer.data());
625 if (message.isNull()) 642 if (message.isNull())
626 fail("Could not decode a text frame as UTF-8."); 643 failAsError("Could not decode a text frame as UTF-8.");
627 else 644 else
628 m_client->didReceiveMessage(message); 645 m_client->didReceiveMessage(message);
629 } else { 646 } else {
630 m_hasContinuousFrame = true; 647 m_hasContinuousFrame = true;
631 m_continuousFrameOpCode = WebSocketFrame::OpCodeText; 648 m_continuousFrameOpCode = WebSocketFrame::OpCodeText;
632 ASSERT(m_continuousFrameData.isEmpty()); 649 ASSERT(m_continuousFrameData.isEmpty());
633 m_continuousFrameData.append(frame.payload, frame.payloadLength); 650 m_continuousFrameData.append(frame.payload, frame.payloadLength);
634 skipBuffer(frameEnd - m_buffer.data()); 651 skipBuffer(frameEnd - m_buffer.data());
635 } 652 }
636 break; 653 break;
(...skipping 11 matching lines...) Expand all
648 m_continuousFrameData.append(frame.payload, frame.payloadLength); 665 m_continuousFrameData.append(frame.payload, frame.payloadLength);
649 skipBuffer(frameEnd - m_buffer.data()); 666 skipBuffer(frameEnd - m_buffer.data());
650 } 667 }
651 break; 668 break;
652 669
653 case WebSocketFrame::OpCodeClose: 670 case WebSocketFrame::OpCodeClose:
654 if (!frame.payloadLength) 671 if (!frame.payloadLength)
655 m_closeEventCode = CloseEventCodeNoStatusRcvd; 672 m_closeEventCode = CloseEventCodeNoStatusRcvd;
656 else if (frame.payloadLength == 1) { 673 else if (frame.payloadLength == 1) {
657 m_closeEventCode = CloseEventCodeAbnormalClosure; 674 m_closeEventCode = CloseEventCodeAbnormalClosure;
658 fail("Received a broken close frame containing an invalid size body. "); 675 failAsError("Received a broken close frame containing an invalid siz e body.");
659 return false; 676 return false;
660 } else { 677 } else {
661 unsigned char highByte = static_cast<unsigned char>(frame.payload[0] ); 678 unsigned char highByte = static_cast<unsigned char>(frame.payload[0] );
662 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]) ; 679 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]) ;
663 m_closeEventCode = highByte << 8 | lowByte; 680 m_closeEventCode = highByte << 8 | lowByte;
664 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCo de == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHand shake) { 681 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCo de == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHand shake) {
665 m_closeEventCode = CloseEventCodeAbnormalClosure; 682 m_closeEventCode = CloseEventCodeAbnormalClosure;
666 fail("Received a broken close frame containing a reserved status code."); 683 failAsError("Received a broken close frame containing a reserved status code.");
667 return false; 684 return false;
668 } 685 }
669 } 686 }
670 if (frame.payloadLength >= 3) 687 if (frame.payloadLength >= 3)
671 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.paylo adLength - 2); 688 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.paylo adLength - 2);
672 else 689 else
673 m_closeEventReason = ""; 690 m_closeEventReason = "";
674 skipBuffer(frameEnd - m_buffer.data()); 691 skipBuffer(frameEnd - m_buffer.data());
675 m_receivedClosingHandshake = true; 692 m_receivedClosingHandshake = true;
676 startClosingHandshake(m_closeEventCode, m_closeEventReason); 693 startClosingHandshake(m_closeEventCode, m_closeEventReason);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 void MainThreadWebSocketChannel::processOutgoingFrameQueue() 754 void MainThreadWebSocketChannel::processOutgoingFrameQueue()
738 { 755 {
739 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) 756 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed)
740 return; 757 return;
741 758
742 while (!m_outgoingFrameQueue.isEmpty()) { 759 while (!m_outgoingFrameQueue.isEmpty()) {
743 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); 760 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst();
744 switch (frame->frameType) { 761 switch (frame->frameType) {
745 case QueuedFrameTypeString: { 762 case QueuedFrameTypeString: {
746 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->strin gData.length())) 763 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->strin gData.length()))
747 fail("Failed to send WebSocket frame."); 764 failAsError("Failed to send WebSocket frame.");
748 break; 765 break;
749 } 766 }
750 767
751 case QueuedFrameTypeVector: 768 case QueuedFrameTypeVector:
752 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vecto rData.size())) 769 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vecto rData.size()))
753 fail("Failed to send WebSocket frame."); 770 failAsError("Failed to send WebSocket frame.");
754 break; 771 break;
755 772
756 case QueuedFrameTypeBlob: { 773 case QueuedFrameTypeBlob: {
757 switch (m_blobLoaderStatus) { 774 switch (m_blobLoaderStatus) {
758 case BlobLoaderNotStarted: 775 case BlobLoaderNotStarted:
759 ref(); // Will be derefed after didFinishLoading() or didFail(). 776 ref(); // Will be derefed after didFinishLoading() or didFail().
760 ASSERT(!m_blobLoader); 777 ASSERT(!m_blobLoader);
761 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::R eadAsArrayBuffer, this)); 778 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::R eadAsArrayBuffer, this));
762 m_blobLoaderStatus = BlobLoaderStarted; 779 m_blobLoaderStatus = BlobLoaderStarted;
763 m_blobLoader->start(m_document, frame->blobData.get()); 780 m_blobLoader->start(m_document, frame->blobData.get());
764 m_outgoingFrameQueue.prepend(frame.release()); 781 m_outgoingFrameQueue.prepend(frame.release());
765 return; 782 return;
766 783
767 case BlobLoaderStarted: 784 case BlobLoaderStarted:
768 case BlobLoaderFailed: 785 case BlobLoaderFailed:
769 m_outgoingFrameQueue.prepend(frame.release()); 786 m_outgoingFrameQueue.prepend(frame.release());
770 return; 787 return;
771 788
772 case BlobLoaderFinished: { 789 case BlobLoaderFinished: {
773 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); 790 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult();
774 m_blobLoader.clear(); 791 m_blobLoader.clear();
775 m_blobLoaderStatus = BlobLoaderNotStarted; 792 m_blobLoaderStatus = BlobLoaderNotStarted;
776 if (!sendFrame(frame->opCode, static_cast<const char*>(result->d ata()), result->byteLength())) 793 if (!sendFrame(frame->opCode, static_cast<const char*>(result->d ata()), result->byteLength()))
777 fail("Failed to send WebSocket frame."); 794 failAsError("Failed to send WebSocket frame.");
778 break; 795 break;
779 } 796 }
780 } 797 }
781 break; 798 break;
782 } 799 }
783 800
784 default: 801 default:
785 ASSERT_NOT_REACHED(); 802 ASSERT_NOT_REACHED();
786 break; 803 break;
787 } 804 }
(...skipping 19 matching lines...) Expand all
807 bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) 824 bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
808 { 825 {
809 ASSERT(m_handle); 826 ASSERT(m_handle);
810 ASSERT(!m_suspended); 827 ASSERT(!m_suspended);
811 828
812 WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSo cketFrame::Masked); 829 WebSocketFrame frame(opCode, data, dataLength, WebSocketFrame::Final | WebSo cketFrame::Masked);
813 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, fr ame); 830 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, fr ame);
814 831
815 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); 832 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame);
816 if (!deflateResult->succeeded()) { 833 if (!deflateResult->succeeded()) {
817 fail(deflateResult->failureReason()); 834 failAsError(deflateResult->failureReason());
818 return false; 835 return false;
819 } 836 }
820 837
821 if (!m_perMessageDeflate.deflate(frame)) { 838 if (!m_perMessageDeflate.deflate(frame)) {
822 fail(m_perMessageDeflate.failureReason()); 839 failAsError(m_perMessageDeflate.failureReason());
823 return false; 840 return false;
824 } 841 }
825 842
826 Vector<char> frameData; 843 Vector<char> frameData;
827 frame.makeFrameData(frameData); 844 frame.makeFrameData(frameData);
828 845
829 m_perMessageDeflate.resetDeflateBuffer(); 846 m_perMessageDeflate.resetDeflateBuffer();
830 return m_handle->send(frameData.data(), frameData.size()); 847 return m_handle->send(frameData.data(), frameData.size());
831 } 848 }
832 849
833 } // namespace WebCore 850 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/modules/websockets/MainThreadWebSocketChannel.h ('k') | Source/modules/websockets/WebSocket.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698