Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 , m_hasContinuousFrame(false) | 87 , m_hasContinuousFrame(false) |
| 88 , m_closeEventCode(CloseEventCodeAbnormalClosure) | 88 , m_closeEventCode(CloseEventCodeAbnormalClosure) |
| 89 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) | 89 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) |
| 90 , m_blobLoaderStatus(BlobLoaderNotStarted) | 90 , m_blobLoaderStatus(BlobLoaderNotStarted) |
| 91 , m_callFrameAtConnection("", "", 0) | 91 , m_callFrameAtConnection("", "", 0) |
| 92 { | 92 { |
| 93 if (Page* page = m_document->page()) | 93 if (Page* page = m_document->page()) |
| 94 m_identifier = createUniqueIdentifier(); | 94 m_identifier = createUniqueIdentifier(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 MainThreadWebSocketChannel::MainThreadWebSocketChannel(Document* document, WebSo cketChannelClient* client, const ScriptCallFrame& callFrame) | |
| 98 : m_document(document) | |
| 99 , m_client(client) | |
| 100 , m_resumeTimer(this, &MainThreadWebSocketChannel::resumeTimerFired) | |
| 101 , m_suspended(false) | |
| 102 , m_closing(false) | |
| 103 , m_didFailOfClientAlreadyRun(false) | |
| 104 , m_receivedClosingHandshake(false) | |
| 105 , m_closingTimer(this, &MainThreadWebSocketChannel::closingTimerFired) | |
| 106 , m_closed(false) | |
| 107 , m_shouldDiscardReceivedData(false) | |
| 108 , m_unhandledBufferedAmount(0) | |
| 109 , m_identifier(0) | |
| 110 , m_hasContinuousFrame(false) | |
| 111 , m_closeEventCode(CloseEventCodeAbnormalClosure) | |
| 112 , m_outgoingFrameQueueStatus(OutgoingFrameQueueOpen) | |
| 113 , m_blobLoaderStatus(BlobLoaderNotStarted) | |
| 114 , m_callFrameAtConnection(callFrame) | |
| 115 { | |
| 116 if (Page* page = m_document->page()) | |
| 117 m_identifier = createUniqueIdentifier(); | |
| 118 } | |
| 119 | |
| 97 MainThreadWebSocketChannel::~MainThreadWebSocketChannel() | 120 MainThreadWebSocketChannel::~MainThreadWebSocketChannel() |
| 98 { | 121 { |
| 99 } | 122 } |
| 100 | 123 |
| 101 void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol ) | 124 void MainThreadWebSocketChannel::connect(const KURL& url, const String& protocol ) |
| 102 { | 125 { |
| 103 LOG(Network, "MainThreadWebSocketChannel %p connect()", this); | 126 LOG(Network, "MainThreadWebSocketChannel %p connect()", this); |
| 104 ASSERT(!m_handle); | 127 ASSERT(!m_handle); |
| 105 ASSERT(!m_suspended); | 128 ASSERT(!m_suspended); |
| 106 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); | 129 m_handshake = adoptPtr(new WebSocketHandshake(url, protocol, m_document)); |
| 107 m_handshake->reset(); | 130 m_handshake->reset(); |
| 108 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor( )); | 131 m_handshake->addExtensionProcessor(m_deflateFramer.createExtensionProcessor( )); |
| 109 if (m_identifier) | 132 if (m_identifier) |
| 110 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, u rl, m_document->url(), protocol); | 133 InspectorInstrumentation::didCreateWebSocket(m_document, m_identifier, u rl, m_document->url(), protocol); |
| 111 ref(); | 134 ref(); |
| 112 m_handle = SocketStreamHandle::create(m_handshake->url(), this); | 135 m_handle = SocketStreamHandle::create(m_handshake->url(), this); |
| 113 RefPtr<ScriptCallStack> callstack = createScriptCallStack(1, true); | 136 RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); |
| 114 m_callFrameAtConnection = callstack && callstack->size() > 0 ? callstack->at (0) : ScriptCallFrame("", "", 0); | 137 if (callStack && callStack->size() > 0) |
| 138 m_callFrameAtConnection = callStack->at(0); | |
| 115 } | 139 } |
| 116 | 140 |
| 117 String MainThreadWebSocketChannel::subprotocol() | 141 String MainThreadWebSocketChannel::subprotocol() |
| 118 { | 142 { |
| 119 LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this); | 143 LOG(Network, "MainThreadWebSocketChannel %p subprotocol()", this); |
| 120 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) | 144 if (!m_handshake || m_handshake->mode() != WebSocketHandshake::Connected) |
| 121 return ""; | 145 return ""; |
| 122 String serverProtocol = m_handshake->serverWebSocketProtocol(); | 146 String serverProtocol = m_handshake->serverWebSocketProtocol(); |
| 123 if (serverProtocol.isNull()) | 147 if (serverProtocol.isNull()) |
| 124 return ""; | 148 return ""; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 { | 211 { |
| 188 LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", th is, code, reason.utf8().data()); | 212 LOG(Network, "MainThreadWebSocketChannel %p close() code=%d reason='%s'", th is, code, reason.utf8().data()); |
| 189 ASSERT(!m_suspended); | 213 ASSERT(!m_suspended); |
| 190 if (!m_handle) | 214 if (!m_handle) |
| 191 return; | 215 return; |
| 192 startClosingHandshake(code, reason); | 216 startClosingHandshake(code, reason); |
| 193 if (m_closing && !m_closingTimer.isActive()) | 217 if (m_closing && !m_closingTimer.isActive()) |
| 194 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); | 218 m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime); |
| 195 } | 219 } |
| 196 | 220 |
| 197 void MainThreadWebSocketChannel::fail(const String& reason) | 221 void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level) |
| 222 { | |
| 223 fail(reason, level, 0); | |
| 224 } | |
| 225 | |
| 226 void MainThreadWebSocketChannel::fail(const String& reason, MessageLevel level, PassOwnPtr<CallStackWrapper> wrapper) | |
| 198 { | 227 { |
| 199 LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reaso n.utf8().data()); | 228 LOG(Network, "MainThreadWebSocketChannel %p fail() reason='%s'", this, reaso n.utf8().data()); |
| 200 ASSERT(!m_suspended); | 229 ASSERT(!m_suspended); |
| 201 if (m_document) { | 230 if (m_document) { |
| 202 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_id entifier, reason); | 231 InspectorInstrumentation::didReceiveWebSocketFrameError(m_document, m_id entifier, reason); |
| 203 const String message = "WebSocket connection to '" + m_handshake->url(). elidedString() + "' failed: " + reason; | 232 const String message = "WebSocket connection to '" + m_handshake->url(). elidedString() + "' failed: " + reason; |
| 204 RefPtr<ScriptCallStack> callstack = createScriptCallStack(1, true); | 233 RefPtr<ScriptCallStack> callStack = wrapper ? wrapper->callStack() : ado ptRef<ScriptCallStack>(0); |
|
Use mkwst_at_chromium.org plz.
2013/05/01 14:55:02
Can't you just return 0 in the second case?
yhirano
2013/05/02 02:33:01
Done.
| |
| 205 if (callstack && callstack->size() > 0) { | 234 if (callStack && callStack->size() > 0) { |
| 206 // We are in a JS callstack. | 235 String url = callStack->at(0).sourceURL(); |
| 207 // So, the addConsoleMessage method will show the stack appropriatel y. | 236 unsigned lineNumber = callStack->at(0).lineNumber(); |
| 208 m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, me ssage); | 237 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMessage( JSMessageSource, level, message, url, lineNumber); |
|
Use mkwst_at_chromium.org plz.
2013/05/01 14:55:02
You shouldn't need this cast: Document subclasses
yhirano
2013/05/02 02:33:01
Document::addConsoleMessage(shorter one) hides Scr
| |
| 209 } else { | 238 } else { |
| 210 // We are not in a JS callstack. | 239 RefPtr<ScriptCallStack> callStack = createScriptCallStack(1, true); |
| 211 // Then show the source file and the line number at the connection i nitiation. | 240 if (callStack && callStack->size() > 0) { |
| 212 const String& url = m_callFrameAtConnection.sourceURL(); | 241 // We are in a JS callstack. |
|
Use mkwst_at_chromium.org plz.
2013/05/01 14:55:02
I believe you can always take the second branch: t
yhirano
2013/05/02 02:33:01
You are right, but I would like to fix this in ano
| |
| 213 unsigned lineNumber = m_callFrameAtConnection.lineNumber(); | 242 // So, the addConsoleMessage method will show the stack appropri ately. |
| 214 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMessage( JSMessageSource, ErrorMessageLevel, message, url, lineNumber, 0, 0); | 243 m_document->addConsoleMessage(JSMessageSource, level, message); |
| 244 } else { | |
| 245 // We are not in a JS callstack. | |
| 246 // Then show the source file and the line number at the connecti on initiation. | |
| 247 const String& url = m_callFrameAtConnection.sourceURL(); | |
| 248 unsigned lineNumber = m_callFrameAtConnection.lineNumber(); | |
| 249 static_cast<ScriptExecutionContext*>(m_document)->addConsoleMess age(JSMessageSource, level, message, url, lineNumber, 0, 0); | |
|
tyoshino (SeeGerritForStatus)
2013/05/01 11:41:52
remove ", 0, 0" here too?
yhirano
2013/05/02 02:04:58
Done.
| |
| 250 } | |
| 215 } | 251 } |
| 216 } | 252 } |
| 253 failInternal(); | |
| 254 } | |
| 217 | 255 |
| 256 void MainThreadWebSocketChannel::failInternal() | |
| 257 { | |
| 218 // Hybi-10 specification explicitly states we must not continue to handle in coming data | 258 // Hybi-10 specification explicitly states we must not continue to handle in coming data |
| 219 // once the WebSocket connection is failed (section 7.1.7). | 259 // once the WebSocket connection is failed (section 7.1.7). |
| 220 RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close th e channel, potentially removing the last reference. | 260 RefPtr<MainThreadWebSocketChannel> protect(this); // The client can close th e channel, potentially removing the last reference. |
| 221 m_shouldDiscardReceivedData = true; | 261 m_shouldDiscardReceivedData = true; |
| 222 if (!m_buffer.isEmpty()) | 262 if (!m_buffer.isEmpty()) |
| 223 skipBuffer(m_buffer.size()); // Save memory. | 263 skipBuffer(m_buffer.size()); // Save memory. |
| 224 m_deflateFramer.didFail(); | 264 m_deflateFramer.didFail(); |
| 225 m_hasContinuousFrame = false; | 265 m_hasContinuousFrame = false; |
| 226 m_continuousFrameData.clear(); | 266 m_continuousFrameData.clear(); |
| 227 if (!m_didFailOfClientAlreadyRun) { | 267 if (!m_didFailOfClientAlreadyRun) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) | 309 void MainThreadWebSocketChannel::didOpenSocketStream(SocketStreamHandle* handle) |
| 270 { | 310 { |
| 271 LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); | 311 LOG(Network, "MainThreadWebSocketChannel %p didOpenSocketStream()", this); |
| 272 ASSERT(handle == m_handle); | 312 ASSERT(handle == m_handle); |
| 273 if (!m_document) | 313 if (!m_document) |
| 274 return; | 314 return; |
| 275 if (m_identifier) | 315 if (m_identifier) |
| 276 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, *m_handshake->clientHandshakeRequest()); | 316 InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document, m_identifier, *m_handshake->clientHandshakeRequest()); |
| 277 CString handshakeMessage = m_handshake->clientHandshakeMessage(); | 317 CString handshakeMessage = m_handshake->clientHandshakeMessage(); |
| 278 if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) | 318 if (!handle->send(handshakeMessage.data(), handshakeMessage.length())) |
| 279 fail("Failed to send WebSocket handshake."); | 319 failAsError("Failed to send WebSocket handshake."); |
| 280 } | 320 } |
| 281 | 321 |
| 282 void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle ) | 322 void MainThreadWebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle ) |
| 283 { | 323 { |
| 284 LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); | 324 LOG(Network, "MainThreadWebSocketChannel %p didCloseSocketStream()", this); |
| 285 if (m_identifier && m_document) | 325 if (m_identifier && m_document) |
| 286 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); | 326 InspectorInstrumentation::didCloseWebSocket(m_document, m_identifier); |
| 287 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); | 327 ASSERT_UNUSED(handle, handle == m_handle || !m_handle); |
| 288 m_closed = true; | 328 m_closed = true; |
| 289 if (m_closingTimer.isActive()) | 329 if (m_closingTimer.isActive()) |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 317 } | 357 } |
| 318 if (!m_client) { | 358 if (!m_client) { |
| 319 m_shouldDiscardReceivedData = true; | 359 m_shouldDiscardReceivedData = true; |
| 320 handle->disconnect(); | 360 handle->disconnect(); |
| 321 return; | 361 return; |
| 322 } | 362 } |
| 323 if (m_shouldDiscardReceivedData) | 363 if (m_shouldDiscardReceivedData) |
| 324 return; | 364 return; |
| 325 if (!appendToBuffer(data, len)) { | 365 if (!appendToBuffer(data, len)) { |
| 326 m_shouldDiscardReceivedData = true; | 366 m_shouldDiscardReceivedData = true; |
| 327 fail("Ran out of memory while receiving WebSocket data."); | 367 failAsError("Ran out of memory while receiving WebSocket data."); |
| 328 return; | 368 return; |
| 329 } | 369 } |
| 330 while (!m_suspended && m_client && !m_buffer.isEmpty()) | 370 while (!m_suspended && m_client && !m_buffer.isEmpty()) |
| 331 if (!processBuffer()) | 371 if (!processBuffer()) |
| 332 break; | 372 break; |
| 333 } | 373 } |
| 334 | 374 |
| 335 void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, si ze_t bufferedAmount) | 375 void MainThreadWebSocketChannel::didUpdateBufferedAmount(SocketStreamHandle*, si ze_t bufferedAmount) |
| 336 { | 376 { |
| 337 if (m_client) | 377 if (m_client) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 deref(); | 428 deref(); |
| 389 } | 429 } |
| 390 | 430 |
| 391 void MainThreadWebSocketChannel::didFail(int errorCode) | 431 void MainThreadWebSocketChannel::didFail(int errorCode) |
| 392 { | 432 { |
| 393 LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, e rrorCode); | 433 LOG(Network, "MainThreadWebSocketChannel %p didFail() errorCode=%d", this, e rrorCode); |
| 394 ASSERT(m_blobLoader); | 434 ASSERT(m_blobLoader); |
| 395 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); | 435 ASSERT(m_blobLoaderStatus == BlobLoaderStarted); |
| 396 m_blobLoader.clear(); | 436 m_blobLoader.clear(); |
| 397 m_blobLoaderStatus = BlobLoaderFailed; | 437 m_blobLoaderStatus = BlobLoaderFailed; |
| 398 fail("Failed to load Blob: error code = " + String::number(errorCode)); // F IXME: Generate human-friendly reason message. | 438 failAsError("Failed to load Blob: error code = " + String::number(errorCode) ); // FIXME: Generate human-friendly reason message. |
| 399 deref(); | 439 deref(); |
| 400 } | 440 } |
| 401 | 441 |
| 402 bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) | 442 bool MainThreadWebSocketChannel::appendToBuffer(const char* data, size_t len) |
| 403 { | 443 { |
| 404 size_t newBufferSize = m_buffer.size() + len; | 444 size_t newBufferSize = m_buffer.size() + len; |
| 405 if (newBufferSize < m_buffer.size()) { | 445 if (newBufferSize < m_buffer.size()) { |
| 406 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)); | 446 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)); |
| 407 return false; | 447 return false; |
| 408 } | 448 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 451 LOG(Network, "MainThreadWebSocketChannel %p Connected", this); | 491 LOG(Network, "MainThreadWebSocketChannel %p Connected", this); |
| 452 skipBuffer(headerLength); | 492 skipBuffer(headerLength); |
| 453 m_client->didConnect(); | 493 m_client->didConnect(); |
| 454 LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m _buffer", this, static_cast<unsigned long>(m_buffer.size())); | 494 LOG(Network, "MainThreadWebSocketChannel %p %lu bytes remaining in m _buffer", this, static_cast<unsigned long>(m_buffer.size())); |
| 455 return !m_buffer.isEmpty(); | 495 return !m_buffer.isEmpty(); |
| 456 } | 496 } |
| 457 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); | 497 ASSERT(m_handshake->mode() == WebSocketHandshake::Failed); |
| 458 LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); | 498 LOG(Network, "MainThreadWebSocketChannel %p Connection failed", this); |
| 459 skipBuffer(headerLength); | 499 skipBuffer(headerLength); |
| 460 m_shouldDiscardReceivedData = true; | 500 m_shouldDiscardReceivedData = true; |
| 461 fail(m_handshake->failureReason()); | 501 failAsError(m_handshake->failureReason()); |
| 462 return false; | 502 return false; |
| 463 } | 503 } |
| 464 if (m_handshake->mode() != WebSocketHandshake::Connected) | 504 if (m_handshake->mode() != WebSocketHandshake::Connected) |
| 465 return false; | 505 return false; |
| 466 | 506 |
| 467 return processFrame(); | 507 return processFrame(); |
| 468 } | 508 } |
| 469 | 509 |
| 470 void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann el>* timer) | 510 void MainThreadWebSocketChannel::resumeTimerFired(Timer<MainThreadWebSocketChann el>* timer) |
| 471 { | 511 { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 { | 555 { |
| 516 ASSERT(!m_buffer.isEmpty()); | 556 ASSERT(!m_buffer.isEmpty()); |
| 517 | 557 |
| 518 WebSocketFrame frame; | 558 WebSocketFrame frame; |
| 519 const char* frameEnd; | 559 const char* frameEnd; |
| 520 String errorString; | 560 String errorString; |
| 521 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffe r.data(), m_buffer.size(), frame, frameEnd, errorString); | 561 WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_buffe r.data(), m_buffer.size(), frame, frameEnd, errorString); |
| 522 if (result == WebSocketFrame::FrameIncomplete) | 562 if (result == WebSocketFrame::FrameIncomplete) |
| 523 return false; | 563 return false; |
| 524 if (result == WebSocketFrame::FrameError) { | 564 if (result == WebSocketFrame::FrameError) { |
| 525 fail(errorString); | 565 failAsError(errorString); |
| 526 return false; | 566 return false; |
| 527 } | 567 } |
| 528 | 568 |
| 529 ASSERT(m_buffer.data() < frameEnd); | 569 ASSERT(m_buffer.data() < frameEnd); |
| 530 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); | 570 ASSERT(frameEnd <= m_buffer.data() + m_buffer.size()); |
| 531 | 571 |
| 532 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); | 572 OwnPtr<InflateResultHolder> inflateResult = m_deflateFramer.inflate(frame); |
| 533 if (!inflateResult->succeeded()) { | 573 if (!inflateResult->succeeded()) { |
| 534 fail(inflateResult->failureReason()); | 574 failAsError(inflateResult->failureReason()); |
| 535 return false; | 575 return false; |
| 536 } | 576 } |
| 537 | 577 |
| 538 // Validate the frame data. | 578 // Validate the frame data. |
| 539 if (WebSocketFrame::isReservedOpCode(frame.opCode)) { | 579 if (WebSocketFrame::isReservedOpCode(frame.opCode)) { |
| 540 fail("Unrecognized frame opcode: " + String::number(frame.opCode)); | 580 failAsError("Unrecognized frame opcode: " + String::number(frame.opCode) ); |
| 541 return false; | 581 return false; |
| 542 } | 582 } |
| 543 | 583 |
| 544 if (frame.reserved2 || frame.reserved3) { | 584 if (frame.reserved2 || frame.reserved3) { |
| 545 fail("One or more reserved bits are on: reserved2 = " + String::number(f rame.reserved2) + ", reserved3 = " + String::number(frame.reserved3)); | 585 failAsError("One or more reserved bits are on: reserved2 = " + String::n umber(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3)); |
| 546 return false; | 586 return false; |
| 547 } | 587 } |
| 548 | 588 |
| 549 if (frame.masked) { | 589 if (frame.masked) { |
| 550 fail("A server must not mask any frames that it sends to the client."); | 590 failAsError("A server must not mask any frames that it sends to the clie nt."); |
| 551 return false; | 591 return false; |
| 552 } | 592 } |
| 553 | 593 |
| 554 // All control frames must not be fragmented. | 594 // All control frames must not be fragmented. |
| 555 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { | 595 if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) { |
| 556 fail("Received fragmented control frame: opcode = " + String::number(fra me.opCode)); | 596 failAsError("Received fragmented control frame: opcode = " + String::num ber(frame.opCode)); |
| 557 return false; | 597 return false; |
| 558 } | 598 } |
| 559 | 599 |
| 560 // All control frames must have a payload of 125 bytes or less, which means the frame must not contain | 600 // All control frames must have a payload of 125 bytes or less, which means the frame must not contain |
| 561 // the "extended payload length" field. | 601 // the "extended payload length" field. |
| 562 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsEx tendedLengthField(frame.payloadLength)) { | 602 if (WebSocketFrame::isControlOpCode(frame.opCode) && WebSocketFrame::needsEx tendedLengthField(frame.payloadLength)) { |
| 563 fail("Received control frame having too long payload: " + String::number (frame.payloadLength) + " bytes"); | 603 failAsError("Received control frame having too long payload: " + String: :number(frame.payloadLength) + " bytes"); |
| 564 return false; | 604 return false; |
| 565 } | 605 } |
| 566 | 606 |
| 567 // A new data frame is received before the previous continuous frame finishe s. | 607 // A new data frame is received before the previous continuous frame finishe s. |
| 568 // Note that control frames are allowed to come in the middle of continuous frames. | 608 // Note that control frames are allowed to come in the middle of continuous frames. |
| 569 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuati on && !WebSocketFrame::isControlOpCode(frame.opCode)) { | 609 if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuati on && !WebSocketFrame::isControlOpCode(frame.opCode)) { |
| 570 fail("Received new data frame but previous continuous frame is unfinishe d."); | 610 failAsError("Received new data frame but previous continuous frame is un finished."); |
| 571 return false; | 611 return false; |
| 572 } | 612 } |
| 573 | 613 |
| 574 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame); | 614 InspectorInstrumentation::didReceiveWebSocketFrame(m_document, m_identifier, frame); |
| 575 | 615 |
| 576 switch (frame.opCode) { | 616 switch (frame.opCode) { |
| 577 case WebSocketFrame::OpCodeContinuation: | 617 case WebSocketFrame::OpCodeContinuation: |
| 578 // An unexpected continuation frame is received without any leading fram e. | 618 // An unexpected continuation frame is received without any leading fram e. |
| 579 if (!m_hasContinuousFrame) { | 619 if (!m_hasContinuousFrame) { |
| 580 fail("Received unexpected continuation frame."); | 620 failAsError("Received unexpected continuation frame."); |
| 581 return false; | 621 return false; |
| 582 } | 622 } |
| 583 m_continuousFrameData.append(frame.payload, frame.payloadLength); | 623 m_continuousFrameData.append(frame.payload, frame.payloadLength); |
| 584 skipBuffer(frameEnd - m_buffer.data()); | 624 skipBuffer(frameEnd - m_buffer.data()); |
| 585 if (frame.final) { | 625 if (frame.final) { |
| 586 // onmessage handler may eventually call the other methods of this c hannel, | 626 // onmessage handler may eventually call the other methods of this c hannel, |
| 587 // so we should pretend that we have finished to read this frame and | 627 // so we should pretend that we have finished to read this frame and |
| 588 // make sure that the member variables are in a consistent state bef ore | 628 // make sure that the member variables are in a consistent state bef ore |
| 589 // the handler is invoked. | 629 // the handler is invoked. |
| 590 // Vector<char>::swap() is used here to clear m_continuousFrameData. | 630 // Vector<char>::swap() is used here to clear m_continuousFrameData. |
| 591 OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char >); | 631 OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char >); |
| 592 m_continuousFrameData.swap(*continuousFrameData); | 632 m_continuousFrameData.swap(*continuousFrameData); |
| 593 m_hasContinuousFrame = false; | 633 m_hasContinuousFrame = false; |
| 594 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { | 634 if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) { |
| 595 String message; | 635 String message; |
| 596 if (continuousFrameData->size()) | 636 if (continuousFrameData->size()) |
| 597 message = String::fromUTF8(continuousFrameData->data(), cont inuousFrameData->size()); | 637 message = String::fromUTF8(continuousFrameData->data(), cont inuousFrameData->size()); |
| 598 else | 638 else |
| 599 message = ""; | 639 message = ""; |
| 600 if (message.isNull()) | 640 if (message.isNull()) |
| 601 fail("Could not decode a text frame as UTF-8."); | 641 failAsError("Could not decode a text frame as UTF-8."); |
| 602 else | 642 else |
| 603 m_client->didReceiveMessage(message); | 643 m_client->didReceiveMessage(message); |
| 604 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) | 644 } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary) |
| 605 m_client->didReceiveBinaryData(continuousFrameData.release()); | 645 m_client->didReceiveBinaryData(continuousFrameData.release()); |
| 606 } | 646 } |
| 607 break; | 647 break; |
| 608 | 648 |
| 609 case WebSocketFrame::OpCodeText: | 649 case WebSocketFrame::OpCodeText: |
| 610 if (frame.final) { | 650 if (frame.final) { |
| 611 String message; | 651 String message; |
| 612 if (frame.payloadLength) | 652 if (frame.payloadLength) |
| 613 message = String::fromUTF8(frame.payload, frame.payloadLength); | 653 message = String::fromUTF8(frame.payload, frame.payloadLength); |
| 614 else | 654 else |
| 615 message = ""; | 655 message = ""; |
| 616 skipBuffer(frameEnd - m_buffer.data()); | 656 skipBuffer(frameEnd - m_buffer.data()); |
| 617 if (message.isNull()) | 657 if (message.isNull()) |
| 618 fail("Could not decode a text frame as UTF-8."); | 658 failAsError("Could not decode a text frame as UTF-8."); |
| 619 else | 659 else |
| 620 m_client->didReceiveMessage(message); | 660 m_client->didReceiveMessage(message); |
| 621 } else { | 661 } else { |
| 622 m_hasContinuousFrame = true; | 662 m_hasContinuousFrame = true; |
| 623 m_continuousFrameOpCode = WebSocketFrame::OpCodeText; | 663 m_continuousFrameOpCode = WebSocketFrame::OpCodeText; |
| 624 ASSERT(m_continuousFrameData.isEmpty()); | 664 ASSERT(m_continuousFrameData.isEmpty()); |
| 625 m_continuousFrameData.append(frame.payload, frame.payloadLength); | 665 m_continuousFrameData.append(frame.payload, frame.payloadLength); |
| 626 skipBuffer(frameEnd - m_buffer.data()); | 666 skipBuffer(frameEnd - m_buffer.data()); |
| 627 } | 667 } |
| 628 break; | 668 break; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 640 m_continuousFrameData.append(frame.payload, frame.payloadLength); | 680 m_continuousFrameData.append(frame.payload, frame.payloadLength); |
| 641 skipBuffer(frameEnd - m_buffer.data()); | 681 skipBuffer(frameEnd - m_buffer.data()); |
| 642 } | 682 } |
| 643 break; | 683 break; |
| 644 | 684 |
| 645 case WebSocketFrame::OpCodeClose: | 685 case WebSocketFrame::OpCodeClose: |
| 646 if (!frame.payloadLength) | 686 if (!frame.payloadLength) |
| 647 m_closeEventCode = CloseEventCodeNoStatusRcvd; | 687 m_closeEventCode = CloseEventCodeNoStatusRcvd; |
| 648 else if (frame.payloadLength == 1) { | 688 else if (frame.payloadLength == 1) { |
| 649 m_closeEventCode = CloseEventCodeAbnormalClosure; | 689 m_closeEventCode = CloseEventCodeAbnormalClosure; |
| 650 fail("Received a broken close frame containing an invalid size body. "); | 690 failAsError("Received a broken close frame containing an invalid siz e body."); |
| 651 return false; | 691 return false; |
| 652 } else { | 692 } else { |
| 653 unsigned char highByte = static_cast<unsigned char>(frame.payload[0] ); | 693 unsigned char highByte = static_cast<unsigned char>(frame.payload[0] ); |
| 654 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]) ; | 694 unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]) ; |
| 655 m_closeEventCode = highByte << 8 | lowByte; | 695 m_closeEventCode = highByte << 8 | lowByte; |
| 656 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCo de == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHand shake) { | 696 if (m_closeEventCode == CloseEventCodeNoStatusRcvd || m_closeEventCo de == CloseEventCodeAbnormalClosure || m_closeEventCode == CloseEventCodeTLSHand shake) { |
| 657 m_closeEventCode = CloseEventCodeAbnormalClosure; | 697 m_closeEventCode = CloseEventCodeAbnormalClosure; |
| 658 fail("Received a broken close frame containing a reserved status code."); | 698 failAsError("Received a broken close frame containing a reserved status code."); |
| 659 return false; | 699 return false; |
| 660 } | 700 } |
| 661 } | 701 } |
| 662 if (frame.payloadLength >= 3) | 702 if (frame.payloadLength >= 3) |
| 663 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.paylo adLength - 2); | 703 m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.paylo adLength - 2); |
| 664 else | 704 else |
| 665 m_closeEventReason = ""; | 705 m_closeEventReason = ""; |
| 666 skipBuffer(frameEnd - m_buffer.data()); | 706 skipBuffer(frameEnd - m_buffer.data()); |
| 667 m_receivedClosingHandshake = true; | 707 m_receivedClosingHandshake = true; |
| 668 startClosingHandshake(m_closeEventCode, m_closeEventReason); | 708 startClosingHandshake(m_closeEventCode, m_closeEventReason); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 void MainThreadWebSocketChannel::processOutgoingFrameQueue() | 768 void MainThreadWebSocketChannel::processOutgoingFrameQueue() |
| 729 { | 769 { |
| 730 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) | 770 if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed) |
| 731 return; | 771 return; |
| 732 | 772 |
| 733 while (!m_outgoingFrameQueue.isEmpty()) { | 773 while (!m_outgoingFrameQueue.isEmpty()) { |
| 734 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); | 774 OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst(); |
| 735 switch (frame->frameType) { | 775 switch (frame->frameType) { |
| 736 case QueuedFrameTypeString: { | 776 case QueuedFrameTypeString: { |
| 737 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->strin gData.length())) | 777 if (!sendFrame(frame->opCode, frame->stringData.data(), frame->strin gData.length())) |
| 738 fail("Failed to send WebSocket frame."); | 778 failAsError("Failed to send WebSocket frame."); |
| 739 break; | 779 break; |
| 740 } | 780 } |
| 741 | 781 |
| 742 case QueuedFrameTypeVector: | 782 case QueuedFrameTypeVector: |
| 743 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vecto rData.size())) | 783 if (!sendFrame(frame->opCode, frame->vectorData.data(), frame->vecto rData.size())) |
| 744 fail("Failed to send WebSocket frame."); | 784 failAsError("Failed to send WebSocket frame."); |
| 745 break; | 785 break; |
| 746 | 786 |
| 747 case QueuedFrameTypeBlob: { | 787 case QueuedFrameTypeBlob: { |
| 748 switch (m_blobLoaderStatus) { | 788 switch (m_blobLoaderStatus) { |
| 749 case BlobLoaderNotStarted: | 789 case BlobLoaderNotStarted: |
| 750 ref(); // Will be derefed after didFinishLoading() or didFail(). | 790 ref(); // Will be derefed after didFinishLoading() or didFail(). |
| 751 ASSERT(!m_blobLoader); | 791 ASSERT(!m_blobLoader); |
| 752 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::R eadAsArrayBuffer, this)); | 792 m_blobLoader = adoptPtr(new FileReaderLoader(FileReaderLoader::R eadAsArrayBuffer, this)); |
| 753 m_blobLoaderStatus = BlobLoaderStarted; | 793 m_blobLoaderStatus = BlobLoaderStarted; |
| 754 m_blobLoader->start(m_document, frame->blobData.get()); | 794 m_blobLoader->start(m_document, frame->blobData.get()); |
| 755 m_outgoingFrameQueue.prepend(frame.release()); | 795 m_outgoingFrameQueue.prepend(frame.release()); |
| 756 return; | 796 return; |
| 757 | 797 |
| 758 case BlobLoaderStarted: | 798 case BlobLoaderStarted: |
| 759 case BlobLoaderFailed: | 799 case BlobLoaderFailed: |
| 760 m_outgoingFrameQueue.prepend(frame.release()); | 800 m_outgoingFrameQueue.prepend(frame.release()); |
| 761 return; | 801 return; |
| 762 | 802 |
| 763 case BlobLoaderFinished: { | 803 case BlobLoaderFinished: { |
| 764 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); | 804 RefPtr<ArrayBuffer> result = m_blobLoader->arrayBufferResult(); |
| 765 m_blobLoader.clear(); | 805 m_blobLoader.clear(); |
| 766 m_blobLoaderStatus = BlobLoaderNotStarted; | 806 m_blobLoaderStatus = BlobLoaderNotStarted; |
| 767 if (!sendFrame(frame->opCode, static_cast<const char*>(result->d ata()), result->byteLength())) | 807 if (!sendFrame(frame->opCode, static_cast<const char*>(result->d ata()), result->byteLength())) |
| 768 fail("Failed to send WebSocket frame."); | 808 failAsError("Failed to send WebSocket frame."); |
| 769 break; | 809 break; |
| 770 } | 810 } |
| 771 } | 811 } |
| 772 break; | 812 break; |
| 773 } | 813 } |
| 774 | 814 |
| 775 default: | 815 default: |
| 776 ASSERT_NOT_REACHED(); | 816 ASSERT_NOT_REACHED(); |
| 777 break; | 817 break; |
| 778 } | 818 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 798 bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) | 838 bool MainThreadWebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength) |
| 799 { | 839 { |
| 800 ASSERT(m_handle); | 840 ASSERT(m_handle); |
| 801 ASSERT(!m_suspended); | 841 ASSERT(!m_suspended); |
| 802 | 842 |
| 803 WebSocketFrame frame(opCode, true, false, true, data, dataLength); | 843 WebSocketFrame frame(opCode, true, false, true, data, dataLength); |
| 804 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, fr ame); | 844 InspectorInstrumentation::didSendWebSocketFrame(m_document, m_identifier, fr ame); |
| 805 | 845 |
| 806 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); | 846 OwnPtr<DeflateResultHolder> deflateResult = m_deflateFramer.deflate(frame); |
| 807 if (!deflateResult->succeeded()) { | 847 if (!deflateResult->succeeded()) { |
| 808 fail(deflateResult->failureReason()); | 848 failAsError(deflateResult->failureReason()); |
| 809 return false; | 849 return false; |
| 810 } | 850 } |
| 811 | 851 |
| 812 Vector<char> frameData; | 852 Vector<char> frameData; |
| 813 frame.makeFrameData(frameData); | 853 frame.makeFrameData(frameData); |
| 814 | 854 |
| 815 return m_handle->send(frameData.data(), frameData.size()); | 855 return m_handle->send(frameData.data(), frameData.size()); |
| 816 } | 856 } |
| 817 | 857 |
| 818 } // namespace WebCore | 858 } // namespace WebCore |
| OLD | NEW |