| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 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 29 matching lines...) Expand all Loading... |
| 40 #include "core/platform/NotImplemented.h" | 40 #include "core/platform/NotImplemented.h" |
| 41 #include "modules/websockets/WebSocketChannel.h" | 41 #include "modules/websockets/WebSocketChannel.h" |
| 42 #include "modules/websockets/WebSocketChannelClient.h" | 42 #include "modules/websockets/WebSocketChannelClient.h" |
| 43 #include "public/platform/Platform.h" | 43 #include "public/platform/Platform.h" |
| 44 #include "public/platform/WebSocketHandle.h" | 44 #include "public/platform/WebSocketHandle.h" |
| 45 #include "public/platform/WebString.h" | 45 #include "public/platform/WebString.h" |
| 46 #include "public/platform/WebURL.h" | 46 #include "public/platform/WebURL.h" |
| 47 #include "public/platform/WebVector.h" | 47 #include "public/platform/WebVector.h" |
| 48 #include "weborigin/SecurityOrigin.h" | 48 #include "weborigin/SecurityOrigin.h" |
| 49 #include "wtf/ArrayBuffer.h" | 49 #include "wtf/ArrayBuffer.h" |
| 50 #include "wtf/Vector.h" |
| 50 #include "wtf/text/WTFString.h" | 51 #include "wtf/text/WTFString.h" |
| 51 | 52 |
| 52 // FIXME: We should implement Inspector notification. | 53 // FIXME: We should implement Inspector notification. |
| 53 // FIXME: We should implement suspend / resume. | |
| 54 // FIXME: We should add log messages. | 54 // FIXME: We should add log messages. |
| 55 | 55 |
| 56 using WebKit::WebSocketHandle; | 56 using WebKit::WebSocketHandle; |
| 57 | 57 |
| 58 namespace WebCore { | 58 namespace WebCore { |
| 59 | 59 |
| 60 namespace { | 60 namespace { |
| 61 | 61 |
| 62 struct PendingEvent { |
| 63 enum Type { |
| 64 DidConnectComplete, |
| 65 DidReceiveTextMessage, |
| 66 DidReceiveBinaryMessage, |
| 67 DidReceiveError, |
| 68 DidClose, |
| 69 }; |
| 70 Type type; |
| 71 Vector<char> message; // for DidReceiveTextMessage / DidReceiveBinaryMessage |
| 72 int closingCode; // for DidClose |
| 73 String closingReason; // for DidClose |
| 74 |
| 75 explicit PendingEvent(Type type) : type(type), closingCode(0) { } |
| 76 PendingEvent(Type, Vector<char>*); |
| 77 PendingEvent(int code, const String& reason) : type(DidClose), closingCode(c
ode), closingReason(reason) { } |
| 78 }; |
| 79 |
| 80 class PendingEventProcessor : public RefCounted<PendingEventProcessor> { |
| 81 public: |
| 82 PendingEventProcessor() : m_isAborted(false) { } |
| 83 virtual ~PendingEventProcessor() { } |
| 84 void abort() { m_isAborted = true; } |
| 85 void append(const PendingEvent& e) { m_events.append(e); } |
| 86 void process(NewWebSocketChannelImpl*); |
| 87 |
| 88 private: |
| 89 bool m_isAborted; |
| 90 Vector<PendingEvent> m_events; |
| 91 }; |
| 92 |
| 93 PendingEvent::PendingEvent(Type type, Vector<char>* data) |
| 94 : type(type) |
| 95 , closingCode(0) |
| 96 { |
| 97 ASSERT(type == DidReceiveTextMessage || type == DidReceiveBinaryMessage); |
| 98 message.swap(*data); |
| 99 } |
| 100 |
| 101 void PendingEventProcessor::process(NewWebSocketChannelImpl* channel) |
| 102 { |
| 103 RefPtr<PendingEventProcessor> protect(this); |
| 104 for (size_t i = 0; i < m_events.size() && !m_isAborted; ++i) { |
| 105 PendingEvent& event = m_events[i]; |
| 106 switch (event.type) { |
| 107 case PendingEvent::DidConnectComplete: |
| 108 channel->handleDidConnect(); |
| 109 // |this| can be detached here. |
| 110 break; |
| 111 case PendingEvent::DidReceiveTextMessage: |
| 112 channel->handleTextMessage(&event.message); |
| 113 // |this| can be detached here. |
| 114 break; |
| 115 case PendingEvent::DidReceiveBinaryMessage: |
| 116 channel->handleBinaryMessage(&event.message); |
| 117 // |this| can be detached here. |
| 118 break; |
| 119 case PendingEvent::DidReceiveError: |
| 120 channel->handleDidReceiveMessageError(); |
| 121 // |this| can be detached here. |
| 122 break; |
| 123 case PendingEvent::DidClose: |
| 124 channel->handleDidClose(event.closingCode, event.closingReason); |
| 125 // |this| can be detached here. |
| 126 break; |
| 127 } |
| 128 } |
| 129 m_events.clear(); |
| 130 } |
| 131 |
| 62 bool isClean(int code) | 132 bool isClean(int code) |
| 63 { | 133 { |
| 64 return code == WebSocketChannel::CloseEventCodeNormalClosure | 134 return code == WebSocketChannel::CloseEventCodeNormalClosure |
| 65 || (WebSocketChannel::CloseEventCodeMinimumUserDefined <= code | 135 || (WebSocketChannel::CloseEventCodeMinimumUserDefined <= code |
| 66 && code <= WebSocketChannel::CloseEventCodeMaximumUserDefined); | 136 && code <= WebSocketChannel::CloseEventCodeMaximumUserDefined); |
| 67 } | 137 } |
| 68 | 138 |
| 69 } // namespace | 139 } // namespace |
| 70 | 140 |
| 71 class NewWebSocketChannelImpl::BlobLoader : public FileReaderLoaderClient { | 141 class NewWebSocketChannelImpl::BlobLoader : public FileReaderLoaderClient { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 m_channel->didFinishLoadingBlob(m_loader.arrayBufferResult()); | 175 m_channel->didFinishLoadingBlob(m_loader.arrayBufferResult()); |
| 106 // |this| is deleted here. | 176 // |this| is deleted here. |
| 107 } | 177 } |
| 108 | 178 |
| 109 void NewWebSocketChannelImpl::BlobLoader::didFail(FileError::ErrorCode errorCode
) | 179 void NewWebSocketChannelImpl::BlobLoader::didFail(FileError::ErrorCode errorCode
) |
| 110 { | 180 { |
| 111 m_channel->didFailLoadingBlob(errorCode); | 181 m_channel->didFailLoadingBlob(errorCode); |
| 112 // |this| is deleted here. | 182 // |this| is deleted here. |
| 113 } | 183 } |
| 114 | 184 |
| 185 class NewWebSocketChannelImpl::Resumer { |
| 186 public: |
| 187 explicit Resumer(NewWebSocketChannelImpl*); |
| 188 ~Resumer(); |
| 189 |
| 190 void append(const PendingEvent&); |
| 191 void suspend(); |
| 192 void resumeLater(); |
| 193 void abort(); |
| 194 |
| 195 private: |
| 196 void resumeNow(Timer<Resumer>*); |
| 197 |
| 198 NewWebSocketChannelImpl* m_channel; |
| 199 RefPtr<PendingEventProcessor> m_pendingEventProcessor; |
| 200 Timer<Resumer> m_timer; |
| 201 bool m_isAborted; |
| 202 }; |
| 203 |
| 204 NewWebSocketChannelImpl::Resumer::Resumer(NewWebSocketChannelImpl* channel) |
| 205 : m_channel(channel) |
| 206 , m_pendingEventProcessor(adoptRef(new PendingEventProcessor)) |
| 207 , m_timer(this, &Resumer::resumeNow) |
| 208 , m_isAborted(false) { } |
| 209 |
| 210 NewWebSocketChannelImpl::Resumer::~Resumer() |
| 211 { |
| 212 abort(); |
| 213 } |
| 214 |
| 215 void NewWebSocketChannelImpl::Resumer::append(const PendingEvent& event) |
| 216 { |
| 217 if (m_isAborted) |
| 218 return; |
| 219 m_pendingEventProcessor->append(event); |
| 220 } |
| 221 |
| 222 void NewWebSocketChannelImpl::Resumer::suspend() |
| 223 { |
| 224 if (m_isAborted) |
| 225 return; |
| 226 m_timer.stop(); |
| 227 m_channel->m_isSuspended = true; |
| 228 } |
| 229 |
| 230 void NewWebSocketChannelImpl::Resumer::resumeLater() |
| 231 { |
| 232 if (m_isAborted) |
| 233 return; |
| 234 if (!m_timer.isActive()) |
| 235 m_timer.startOneShot(0); |
| 236 } |
| 237 |
| 238 void NewWebSocketChannelImpl::Resumer::abort() |
| 239 { |
| 240 if (m_isAborted) |
| 241 return; |
| 242 m_isAborted = true; |
| 243 m_timer.stop(); |
| 244 m_pendingEventProcessor->abort(); |
| 245 m_pendingEventProcessor = 0; |
| 246 } |
| 247 |
| 248 void NewWebSocketChannelImpl::Resumer::resumeNow(Timer<Resumer>*) |
| 249 { |
| 250 ASSERT(!m_isAborted); |
| 251 m_channel->m_isSuspended = false; |
| 252 |
| 253 ASSERT(m_channel->m_client); |
| 254 m_pendingEventProcessor->process(m_channel); |
| 255 // |this| can be aborted here. |
| 256 // |this| can be deleted here. |
| 257 } |
| 258 |
| 115 NewWebSocketChannelImpl::NewWebSocketChannelImpl(ScriptExecutionContext* context
, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) | 259 NewWebSocketChannelImpl::NewWebSocketChannelImpl(ScriptExecutionContext* context
, WebSocketChannelClient* client, const String& sourceURL, unsigned lineNumber) |
| 116 : ContextLifecycleObserver(context) | 260 : ContextLifecycleObserver(context) |
| 117 , m_handle(adoptPtr(WebKit::Platform::current()->createWebSocketHandle())) | 261 , m_handle(adoptPtr(WebKit::Platform::current()->createWebSocketHandle())) |
| 118 , m_client(client) | 262 , m_client(client) |
| 263 , m_resumer(adoptPtr(new Resumer(this))) |
| 264 , m_isSuspended(false) |
| 119 , m_sendingQuota(0) | 265 , m_sendingQuota(0) |
| 120 , m_receivedDataSizeForFlowControl(receivedDataSizeForFlowControlHighWaterMa
rk * 2) // initial quota | 266 , m_receivedDataSizeForFlowControl(receivedDataSizeForFlowControlHighWaterMa
rk * 2) // initial quota |
| 121 , m_bufferedAmount(0) | 267 , m_bufferedAmount(0) |
| 122 , m_sentSizeOfTopMessage(0) | 268 , m_sentSizeOfTopMessage(0) |
| 123 { | 269 { |
| 124 } | 270 } |
| 125 | 271 |
| 126 NewWebSocketChannelImpl::~NewWebSocketChannelImpl() | 272 NewWebSocketChannelImpl::~NewWebSocketChannelImpl() |
| 127 { | 273 { |
| 128 abortAsyncOperations(); | 274 abortAsyncOperations(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 { | 332 { |
| 187 ASSERT(m_handle); | 333 ASSERT(m_handle); |
| 188 m_handle->close(static_cast<unsigned short>(code), reason); | 334 m_handle->close(static_cast<unsigned short>(code), reason); |
| 189 } | 335 } |
| 190 | 336 |
| 191 void NewWebSocketChannelImpl::fail(const String& reason, MessageLevel level, con
st String& sourceURL, unsigned lineNumber) | 337 void NewWebSocketChannelImpl::fail(const String& reason, MessageLevel level, con
st String& sourceURL, unsigned lineNumber) |
| 192 { | 338 { |
| 193 // m_handle and m_client can be null here. | 339 // m_handle and m_client can be null here. |
| 194 if (m_client) | 340 if (m_client) |
| 195 m_client->didReceiveMessageError(); | 341 m_client->didReceiveMessageError(); |
| 196 handleDidClose(CloseEventCodeAbnormalClosure, reason); | 342 if (m_isSuspended) { |
| 197 // handleDidClose may delete this object. | 343 m_resumer->append(PendingEvent(CloseEventCodeAbnormalClosure, reason)); |
| 344 } else { |
| 345 handleDidClose(CloseEventCodeAbnormalClosure, reason); |
| 346 // handleDidClose may delete this object. |
| 347 } |
| 198 } | 348 } |
| 199 | 349 |
| 200 void NewWebSocketChannelImpl::disconnect() | 350 void NewWebSocketChannelImpl::disconnect() |
| 201 { | 351 { |
| 202 abortAsyncOperations(); | 352 abortAsyncOperations(); |
| 203 if (m_handle) | 353 if (m_handle) |
| 204 m_handle->close(CloseEventCodeAbnormalClosure, ""); | 354 m_handle->close(CloseEventCodeAbnormalClosure, ""); |
| 205 m_handle.clear(); | 355 m_handle.clear(); |
| 206 m_client = 0; | 356 m_client = 0; |
| 207 } | 357 } |
| 208 | 358 |
| 209 void NewWebSocketChannelImpl::suspend() | 359 void NewWebSocketChannelImpl::suspend() |
| 210 { | 360 { |
| 211 notImplemented(); | 361 m_resumer->suspend(); |
| 212 } | 362 } |
| 213 | 363 |
| 214 void NewWebSocketChannelImpl::resume() | 364 void NewWebSocketChannelImpl::resume() |
| 215 { | 365 { |
| 216 notImplemented(); | 366 m_resumer->resumeLater(); |
| 217 } | 367 } |
| 218 | 368 |
| 369 void NewWebSocketChannelImpl::handleDidConnect() |
| 370 { |
| 371 ASSERT(m_client); |
| 372 ASSERT(!m_isSuspended); |
| 373 m_client->didConnect(); |
| 374 } |
| 375 |
| 376 void NewWebSocketChannelImpl::handleTextMessage(Vector<char>* messageData) |
| 377 { |
| 378 ASSERT(m_client); |
| 379 ASSERT(!m_isSuspended); |
| 380 ASSERT(messageData); |
| 381 String message = String::fromUTF8(messageData->data(), messageData->size()); |
| 382 // For consistency with handleBinaryMessage, we clear |messageData|. |
| 383 messageData->clear(); |
| 384 if (message.isNull()) { |
| 385 failAsError("Could not decode a text frame as UTF-8."); |
| 386 // failAsError may delete this object. |
| 387 } else { |
| 388 m_client->didReceiveMessage(message); |
| 389 } |
| 390 } |
| 391 |
| 392 void NewWebSocketChannelImpl::handleBinaryMessage(Vector<char>* messageData) |
| 393 { |
| 394 ASSERT(m_client); |
| 395 ASSERT(!m_isSuspended); |
| 396 ASSERT(messageData); |
| 397 OwnPtr<Vector<char> > binaryData = adoptPtr(new Vector<char>); |
| 398 messageData->swap(*binaryData); |
| 399 m_client->didReceiveBinaryData(binaryData.release()); |
| 400 } |
| 401 |
| 402 void NewWebSocketChannelImpl::handleDidReceiveMessageError() |
| 403 { |
| 404 ASSERT(m_client); |
| 405 ASSERT(!m_isSuspended); |
| 406 m_client->didReceiveMessageError(); |
| 407 } |
| 408 |
| 409 void NewWebSocketChannelImpl::handleDidClose(unsigned short code, const String&
reason) |
| 410 { |
| 411 ASSERT(!m_isSuspended); |
| 412 m_handle.clear(); |
| 413 abortAsyncOperations(); |
| 414 if (!m_client) { |
| 415 return; |
| 416 } |
| 417 WebSocketChannelClient* client = m_client; |
| 418 m_client = 0; |
| 419 WebSocketChannelClient::ClosingHandshakeCompletionStatus status = |
| 420 isClean(code) ? WebSocketChannelClient::ClosingHandshakeComplete : WebSo
cketChannelClient::ClosingHandshakeIncomplete; |
| 421 client->didClose(m_bufferedAmount, status, code, reason); |
| 422 // client->didClose may delete this object. |
| 423 } |
| 424 |
| 425 |
| 219 NewWebSocketChannelImpl::Message::Message(const String& text) | 426 NewWebSocketChannelImpl::Message::Message(const String& text) |
| 220 : type(MessageTypeText) | 427 : type(MessageTypeText) |
| 221 , text(text.utf8(String::StrictConversionReplacingUnpairedSurrogatesWithFFFD
)) { } | 428 , text(text.utf8(String::StrictConversionReplacingUnpairedSurrogatesWithFFFD
)) { } |
| 222 | 429 |
| 223 NewWebSocketChannelImpl::Message::Message(const Blob& blob) | 430 NewWebSocketChannelImpl::Message::Message(const Blob& blob) |
| 224 : type(MessageTypeBlob) | 431 : type(MessageTypeBlob) |
| 225 , blob(Blob::create(blob.url(), blob.type(), blob.size())) { } | 432 , blob(Blob::create(blob.url(), blob.type(), blob.size())) { } |
| 226 | 433 |
| 227 NewWebSocketChannelImpl::Message::Message(PassRefPtr<ArrayBuffer> arrayBuffer) | 434 NewWebSocketChannelImpl::Message::Message(PassRefPtr<ArrayBuffer> arrayBuffer) |
| 228 : type(MessageTypeArrayBuffer) | 435 : type(MessageTypeArrayBuffer) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 m_handle->flowControl(m_receivedDataSizeForFlowControl); | 486 m_handle->flowControl(m_receivedDataSizeForFlowControl); |
| 280 m_receivedDataSizeForFlowControl = 0; | 487 m_receivedDataSizeForFlowControl = 0; |
| 281 } | 488 } |
| 282 | 489 |
| 283 void NewWebSocketChannelImpl::abortAsyncOperations() | 490 void NewWebSocketChannelImpl::abortAsyncOperations() |
| 284 { | 491 { |
| 285 if (m_blobLoader) { | 492 if (m_blobLoader) { |
| 286 m_blobLoader->cancel(); | 493 m_blobLoader->cancel(); |
| 287 m_blobLoader.clear(); | 494 m_blobLoader.clear(); |
| 288 } | 495 } |
| 496 m_resumer->abort(); |
| 289 } | 497 } |
| 290 | 498 |
| 291 void NewWebSocketChannelImpl::didConnect(WebSocketHandle* handle, bool succeed,
const WebKit::WebString& selectedProtocol, const WebKit::WebString& extensions) | 499 void NewWebSocketChannelImpl::didConnect(WebSocketHandle* handle, bool succeed,
const WebKit::WebString& selectedProtocol, const WebKit::WebString& extensions) |
| 292 { | 500 { |
| 293 if (!m_handle) { | 501 ASSERT(m_handle); |
| 294 return; | |
| 295 } | |
| 296 ASSERT(handle == m_handle); | 502 ASSERT(handle == m_handle); |
| 297 ASSERT(m_client); | 503 ASSERT(m_client); |
| 298 if (!succeed) { | 504 if (!succeed) { |
| 299 failAsError("Cannot connect to " + m_url.string() + "."); | 505 failAsError("Cannot connect to " + m_url.string() + "."); |
| 300 // failAsError may delete this object. | 506 // failAsError may delete this object. |
| 301 return; | 507 return; |
| 302 } | 508 } |
| 303 m_subprotocol = selectedProtocol; | 509 m_subprotocol = selectedProtocol; |
| 304 m_extensions = extensions; | 510 m_extensions = extensions; |
| 305 m_client->didConnect(); | 511 if (m_isSuspended) |
| 512 m_resumer->append(PendingEvent(PendingEvent::DidConnectComplete)); |
| 513 else |
| 514 m_client->didConnect(); |
| 306 } | 515 } |
| 307 | 516 |
| 308 void NewWebSocketChannelImpl::didReceiveData(WebSocketHandle* handle, WebSocketH
andle::MessageType type, const char* data, size_t size, bool fin) | 517 void NewWebSocketChannelImpl::didReceiveData(WebSocketHandle* handle, WebSocketH
andle::MessageType type, const char* data, size_t size, bool fin) |
| 309 { | 518 { |
| 310 if (!m_handle) { | 519 ASSERT(m_handle); |
| 311 return; | |
| 312 } | |
| 313 ASSERT(handle == m_handle); | 520 ASSERT(handle == m_handle); |
| 314 ASSERT(m_client); | 521 ASSERT(m_client); |
| 315 // Non-final frames cannot be empty. | 522 // Non-final frames cannot be empty. |
| 316 ASSERT(fin || size); | 523 ASSERT(fin || size); |
| 317 switch (type) { | 524 switch (type) { |
| 318 case WebSocketHandle::MessageTypeText: | 525 case WebSocketHandle::MessageTypeText: |
| 319 ASSERT(m_receivingMessageData.isEmpty()); | 526 ASSERT(m_receivingMessageData.isEmpty()); |
| 320 m_receivingMessageTypeIsText = true; | 527 m_receivingMessageTypeIsText = true; |
| 321 break; | 528 break; |
| 322 case WebSocketHandle::MessageTypeBinary: | 529 case WebSocketHandle::MessageTypeBinary: |
| 323 ASSERT(m_receivingMessageData.isEmpty()); | 530 ASSERT(m_receivingMessageData.isEmpty()); |
| 324 m_receivingMessageTypeIsText = false; | 531 m_receivingMessageTypeIsText = false; |
| 325 break; | 532 break; |
| 326 case WebSocketHandle::MessageTypeContinuation: | 533 case WebSocketHandle::MessageTypeContinuation: |
| 327 ASSERT(!m_receivingMessageData.isEmpty()); | 534 ASSERT(!m_receivingMessageData.isEmpty()); |
| 328 break; | 535 break; |
| 329 } | 536 } |
| 330 m_receivingMessageData.append(data, size); | 537 m_receivingMessageData.append(data, size); |
| 331 m_receivedDataSizeForFlowControl += size; | 538 m_receivedDataSizeForFlowControl += size; |
| 332 flowControlIfNecessary(); | 539 flowControlIfNecessary(); |
| 333 if (!fin) { | 540 if (!fin) { |
| 334 return; | 541 return; |
| 335 } | 542 } |
| 543 if (m_isSuspended) { |
| 544 PendingEvent::Type type = |
| 545 m_receivingMessageTypeIsText ? PendingEvent::DidReceiveTextMessage :
PendingEvent::DidReceiveBinaryMessage; |
| 546 m_resumer->append(PendingEvent(type, &m_receivingMessageData)); |
| 547 return; |
| 548 } |
| 336 Vector<char> messageData; | 549 Vector<char> messageData; |
| 337 messageData.swap(m_receivingMessageData); | 550 messageData.swap(m_receivingMessageData); |
| 338 if (m_receivingMessageTypeIsText) { | 551 if (m_receivingMessageTypeIsText) { |
| 339 handleTextMessage(&messageData); | 552 handleTextMessage(&messageData); |
| 340 // handleTextMessage may delete this object. | 553 // handleTextMessage may delete this object. |
| 341 } else { | 554 } else { |
| 342 handleBinaryMessage(&messageData); | 555 handleBinaryMessage(&messageData); |
| 343 } | 556 } |
| 344 } | 557 } |
| 345 | 558 |
| 346 | 559 |
| 347 void NewWebSocketChannelImpl::didClose(WebSocketHandle* handle, unsigned short c
ode, const WebKit::WebString& reason) | 560 void NewWebSocketChannelImpl::didClose(WebSocketHandle* handle, unsigned short c
ode, const WebKit::WebString& reason) |
| 348 { | 561 { |
| 562 ASSERT(m_handle); |
| 563 m_handle.clear(); |
| 349 // FIXME: Maybe we should notify an error to m_client for some didClose mess
ages. | 564 // FIXME: Maybe we should notify an error to m_client for some didClose mess
ages. |
| 350 handleDidClose(code, reason); | 565 if (m_isSuspended) { |
| 351 // handleDidClose may delete this object. | 566 m_resumer->append(PendingEvent(code, reason)); |
| 352 } | |
| 353 | |
| 354 void NewWebSocketChannelImpl::handleTextMessage(Vector<char>* messageData) | |
| 355 { | |
| 356 ASSERT(m_client); | |
| 357 ASSERT(messageData); | |
| 358 String message = ""; | |
| 359 if (m_receivingMessageData.size() > 0) { | |
| 360 message = String::fromUTF8(messageData->data(), messageData->size()); | |
| 361 } | |
| 362 // For consistency with handleBinaryMessage, we clear |messageData|. | |
| 363 messageData->clear(); | |
| 364 if (message.isNull()) { | |
| 365 failAsError("Could not decode a text frame as UTF-8."); | |
| 366 // failAsError may delete this object. | |
| 367 } else { | 567 } else { |
| 368 m_client->didReceiveMessage(message); | 568 handleDidClose(code, reason); |
| 569 // handleDidClose may delete this object. |
| 369 } | 570 } |
| 370 } | 571 } |
| 371 | 572 |
| 372 void NewWebSocketChannelImpl::handleBinaryMessage(Vector<char>* messageData) | |
| 373 { | |
| 374 ASSERT(m_client); | |
| 375 ASSERT(messageData); | |
| 376 OwnPtr<Vector<char> > binaryData = adoptPtr(new Vector<char>); | |
| 377 messageData->swap(*binaryData); | |
| 378 m_client->didReceiveBinaryData(binaryData.release()); | |
| 379 } | |
| 380 | |
| 381 void NewWebSocketChannelImpl::handleDidClose(unsigned short code, const String&
reason) | |
| 382 { | |
| 383 m_handle.clear(); | |
| 384 abortAsyncOperations(); | |
| 385 if (!m_client) { | |
| 386 return; | |
| 387 } | |
| 388 WebSocketChannelClient* client = m_client; | |
| 389 m_client = 0; | |
| 390 WebSocketChannelClient::ClosingHandshakeCompletionStatus status = | |
| 391 isClean(code) ? WebSocketChannelClient::ClosingHandshakeComplete : WebSo
cketChannelClient::ClosingHandshakeIncomplete; | |
| 392 client->didClose(m_bufferedAmount, status, code, reason); | |
| 393 // client->didClose may delete this object. | |
| 394 } | |
| 395 | |
| 396 void NewWebSocketChannelImpl::didFinishLoadingBlob(PassRefPtr<ArrayBuffer> buffe
r) | 573 void NewWebSocketChannelImpl::didFinishLoadingBlob(PassRefPtr<ArrayBuffer> buffe
r) |
| 397 { | 574 { |
| 398 m_blobLoader.clear(); | 575 m_blobLoader.clear(); |
| 399 ASSERT(m_handle); | 576 ASSERT(m_handle); |
| 400 // The loaded blob is always placed on m_messages[0]. | 577 // The loaded blob is always placed on m_messages[0]. |
| 401 ASSERT(m_messages.size() > 0 && m_messages.first().type == MessageTypeBlob); | 578 ASSERT(m_messages.size() > 0 && m_messages.first().type == MessageTypeBlob); |
| 402 // We replace it with the loaded blob. | 579 // We replace it with the loaded blob. |
| 403 m_messages.first() = Message(buffer); | 580 m_messages.first() = Message(buffer); |
| 404 sendInternal(); | 581 sendInternal(); |
| 405 } | 582 } |
| 406 | 583 |
| 407 void NewWebSocketChannelImpl::didFailLoadingBlob(FileError::ErrorCode errorCode) | 584 void NewWebSocketChannelImpl::didFailLoadingBlob(FileError::ErrorCode errorCode) |
| 408 { | 585 { |
| 409 m_blobLoader.clear(); | 586 m_blobLoader.clear(); |
| 410 if (errorCode == FileError::ABORT_ERR) { | 587 if (errorCode == FileError::ABORT_ERR) { |
| 411 // The error is caused by cancel(). | 588 // The error is caused by cancel(). |
| 412 return; | 589 return; |
| 413 } | 590 } |
| 414 // FIXME: Generate human-friendly reason message. | 591 // FIXME: Generate human-friendly reason message. |
| 415 failAsError("Failed to load Blob: error code = " + String::number(errorCode)
); | 592 failAsError("Failed to load Blob: error code = " + String::number(errorCode)
); |
| 416 // |this| can be deleted here. | 593 // |this| can be deleted here. |
| 417 } | 594 } |
| 418 | 595 |
| 419 } // namespace WebCore | 596 } // namespace WebCore |
| OLD | NEW |