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 |