Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/plugins/ppapi/ppb_websocket_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_websocket_impl.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "googleurl/src/gurl.h" | 12 #include "googleurl/src/gurl.h" |
| 13 #include "net/base/net_util.h" | 13 #include "net/base/net_util.h" |
| 14 #include "ppapi/c/dev/ppb_var_array_buffer_dev.h" | 14 #include "ppapi/c/dev/ppb_var_array_buffer_dev.h" |
| 15 #include "ppapi/c/pp_completion_callback.h" | 15 #include "ppapi/c/pp_completion_callback.h" |
| 16 #include "ppapi/c/pp_errors.h" | 16 #include "ppapi/c/pp_errors.h" |
| 17 #include "ppapi/c/pp_var.h" | 17 #include "ppapi/c/pp_var.h" |
| 18 #include "ppapi/c/ppb_var.h" | 18 #include "ppapi/c/ppb_var.h" |
| 19 #include "ppapi/shared_impl/var.h" | 19 #include "ppapi/shared_impl/var.h" |
| 20 #include "ppapi/shared_impl/var_tracker.h" | 20 #include "ppapi/shared_impl/var_tracker.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebData.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
| 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" | 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
| 25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
| 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" |
| 27 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" |
| 28 #include "webkit/plugins/ppapi/host_array_buffer_var.h" | |
| 28 #include "webkit/plugins/ppapi/host_globals.h" | 29 #include "webkit/plugins/ppapi/host_globals.h" |
| 29 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 30 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 30 #include "webkit/plugins/ppapi/resource_helper.h" | 31 #include "webkit/plugins/ppapi/resource_helper.h" |
| 31 | 32 |
| 32 using ppapi::ArrayBufferVar; | 33 using ppapi::ArrayBufferVar; |
| 33 using ppapi::PpapiGlobals; | 34 using ppapi::PpapiGlobals; |
| 34 using ppapi::StringVar; | 35 using ppapi::StringVar; |
| 35 using ppapi::thunk::PPB_WebSocket_API; | 36 using ppapi::thunk::PPB_WebSocket_API; |
| 36 using ppapi::TrackedCallback; | 37 using ppapi::TrackedCallback; |
| 38 using ppapi::Var; | |
| 37 using ppapi::VarTracker; | 39 using ppapi::VarTracker; |
| 38 using WebKit::WebData; | 40 using WebKit::WebArrayBuffer; |
| 39 using WebKit::WebDocument; | 41 using WebKit::WebDocument; |
| 40 using WebKit::WebString; | 42 using WebKit::WebString; |
| 41 using WebKit::WebSocket; | 43 using WebKit::WebSocket; |
| 42 using WebKit::WebSocketClient; | 44 using WebKit::WebSocketClient; |
| 43 using WebKit::WebURL; | 45 using WebKit::WebURL; |
| 44 | 46 |
| 45 const uint32_t kMaxReasonSizeInBytes = 123; | 47 const uint32_t kMaxReasonSizeInBytes = 123; |
| 46 const size_t kHybiBaseFramingOverhead = 2; | 48 const size_t kHybiBaseFramingOverhead = 2; |
| 47 const size_t kHybiMaskingKeyLength = 4; | 49 const size_t kHybiMaskingKeyLength = 4; |
| 48 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; | 50 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 68 bool InValidStateToReceive(PP_WebSocketReadyState_Dev state) { | 70 bool InValidStateToReceive(PP_WebSocketReadyState_Dev state) { |
| 69 return state == PP_WEBSOCKETREADYSTATE_OPEN_DEV || | 71 return state == PP_WEBSOCKETREADYSTATE_OPEN_DEV || |
| 70 state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV; | 72 state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV; |
| 71 } | 73 } |
| 72 | 74 |
| 73 } // namespace | 75 } // namespace |
| 74 | 76 |
| 75 namespace webkit { | 77 namespace webkit { |
| 76 namespace ppapi { | 78 namespace ppapi { |
| 77 | 79 |
| 78 // TODO(toyoshim): Default value of binary_type_ must be | |
| 79 // PP_WEBSOCKETBINARYTYPE_BLOB_DEV after supporting Blob. | |
| 80 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) | 80 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) |
| 81 : Resource(instance), | 81 : Resource(instance), |
| 82 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), | 82 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), |
| 83 binary_type_(PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV), | 83 binary_type_(WebSocket::BinaryTypeBlob), |
| 84 error_was_received_(false), | 84 error_was_received_(false), |
| 85 receive_callback_var_(NULL), | 85 receive_callback_var_(NULL), |
| 86 wait_for_receive_(false), | 86 wait_for_receive_(false), |
| 87 close_code_(0), | 87 close_code_(0), |
| 88 close_was_clean_(PP_FALSE), | 88 close_was_clean_(PP_FALSE), |
| 89 empty_string_(new StringVar("", 0)), | 89 empty_string_(new StringVar("", 0)), |
| 90 buffered_amount_(0), | 90 buffered_amount_(0), |
| 91 buffered_amount_after_close_(0) { | 91 buffered_amount_after_close_(0) { |
| 92 } | 92 } |
| 93 | 93 |
| 94 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { | 94 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { |
| 95 if (websocket_.get()) | 95 if (websocket_.get()) |
| 96 websocket_->disconnect(); | 96 websocket_->disconnect(); |
| 97 | |
| 98 // Clean up received and unread messages | |
| 99 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); | |
| 100 while (!received_messages_.empty()) { | |
| 101 PP_Var var = received_messages_.front(); | |
| 102 received_messages_.pop(); | |
| 103 var_tracker->ReleaseVar(var); | |
| 104 } | |
| 105 } | 97 } |
| 106 | 98 |
| 107 // static | 99 // static |
| 108 PP_Resource PPB_WebSocket_Impl::Create(PP_Instance instance) { | 100 PP_Resource PPB_WebSocket_Impl::Create(PP_Instance instance) { |
| 109 scoped_refptr<PPB_WebSocket_Impl> ws(new PPB_WebSocket_Impl(instance)); | 101 scoped_refptr<PPB_WebSocket_Impl> ws(new PPB_WebSocket_Impl(instance)); |
| 110 return ws->GetReference(); | 102 return ws->GetReference(); |
| 111 } | 103 } |
| 112 | 104 |
| 113 PPB_WebSocket_API* PPB_WebSocket_Impl::AsPPB_WebSocket_API() { | 105 PPB_WebSocket_API* PPB_WebSocket_Impl::AsPPB_WebSocket_API() { |
| 114 return this; | 106 return this; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 if (!callback.func) | 188 if (!callback.func) |
| 197 return PP_ERROR_BLOCKS_MAIN_THREAD; | 189 return PP_ERROR_BLOCKS_MAIN_THREAD; |
| 198 | 190 |
| 199 // Create WebKit::WebSocket object and connect. | 191 // Create WebKit::WebSocket object and connect. |
| 200 WebDocument document = plugin_instance->container()->element().document(); | 192 WebDocument document = plugin_instance->container()->element().document(); |
| 201 websocket_.reset(WebSocket::create(document, this)); | 193 websocket_.reset(WebSocket::create(document, this)); |
| 202 DCHECK(websocket_.get()); | 194 DCHECK(websocket_.get()); |
| 203 if (!websocket_.get()) | 195 if (!websocket_.get()) |
| 204 return PP_ERROR_NOTSUPPORTED; | 196 return PP_ERROR_NOTSUPPORTED; |
| 205 | 197 |
| 198 // Set receiving binary object type. | |
| 199 websocket_->setBinaryType(binary_type_); | |
| 200 | |
| 206 websocket_->connect(web_url, web_protocols); | 201 websocket_->connect(web_url, web_protocols); |
| 207 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV; | 202 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV; |
| 208 | 203 |
| 209 // Install callback. | 204 // Install callback. |
| 210 connect_callback_ = new TrackedCallback(this, callback); | 205 connect_callback_ = new TrackedCallback(this, callback); |
| 211 | 206 |
| 212 return PP_OK_COMPLETIONPENDING; | 207 return PP_OK_COMPLETIONPENDING; |
| 213 } | 208 } |
| 214 | 209 |
| 215 int32_t PPB_WebSocket_Impl::Close(uint16_t code, | 210 int32_t PPB_WebSocket_Impl::Close(uint16_t code, |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 // Send the message. | 345 // Send the message. |
| 351 if (message.type == PP_VARTYPE_STRING) { | 346 if (message.type == PP_VARTYPE_STRING) { |
| 352 // Convert message to WebString. | 347 // Convert message to WebString. |
| 353 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | 348 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); |
| 354 if (!message_string) | 349 if (!message_string) |
| 355 return PP_ERROR_BADARGUMENT; | 350 return PP_ERROR_BADARGUMENT; |
| 356 WebString web_message = WebString::fromUTF8(message_string->value()); | 351 WebString web_message = WebString::fromUTF8(message_string->value()); |
| 357 if (!websocket_->sendText(web_message)) | 352 if (!websocket_->sendText(web_message)) |
| 358 return PP_ERROR_BADARGUMENT; | 353 return PP_ERROR_BADARGUMENT; |
| 359 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { | 354 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { |
| 360 // Convert message to WebData. | 355 // Convert message to WebArrayBuffer. |
| 361 // TODO(toyoshim): Must add a WebKit interface which handles WebArrayBuffer | 356 scoped_refptr<HostArrayBufferVar> host_message = |
| 362 // directly. | 357 static_cast<HostArrayBufferVar*>(ArrayBufferVar::FromPPVar(message)); |
| 363 scoped_refptr<ArrayBufferVar> message_array_buffer = | 358 if (!host_message) |
| 364 ArrayBufferVar::FromPPVar(message); | |
| 365 if (!message_array_buffer) | |
| 366 return PP_ERROR_BADARGUMENT; | 359 return PP_ERROR_BADARGUMENT; |
| 367 WebData web_message = WebData( | 360 WebArrayBuffer& web_message = host_message->webkit_buffer(); |
| 368 static_cast<const char*>(message_array_buffer->Map()), | 361 if (!websocket_->sendArrayBuffer(web_message)) |
| 369 static_cast<size_t>(message_array_buffer->ByteLength())); | |
| 370 if (!websocket_->sendBinary(web_message)) | |
| 371 return PP_ERROR_BADARGUMENT; | 362 return PP_ERROR_BADARGUMENT; |
| 372 } else { | 363 } else { |
| 373 // TODO(toyoshim): Support Blob. | 364 // TODO(toyoshim): Support Blob. |
| 374 return PP_ERROR_NOTSUPPORTED; | 365 return PP_ERROR_NOTSUPPORTED; |
| 375 } | 366 } |
| 376 | 367 |
| 377 return PP_OK; | 368 return PP_OK; |
| 378 } | 369 } |
| 379 | 370 |
| 380 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { | 371 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 } | 408 } |
| 418 | 409 |
| 419 PP_Var PPB_WebSocket_Impl::GetURL() { | 410 PP_Var PPB_WebSocket_Impl::GetURL() { |
| 420 if (!url_) | 411 if (!url_) |
| 421 return empty_string_->GetPPVar(); | 412 return empty_string_->GetPPVar(); |
| 422 return url_->GetPPVar(); | 413 return url_->GetPPVar(); |
| 423 } | 414 } |
| 424 | 415 |
| 425 PP_Bool PPB_WebSocket_Impl::SetBinaryType( | 416 PP_Bool PPB_WebSocket_Impl::SetBinaryType( |
| 426 PP_WebSocketBinaryType_Dev binary_type) { | 417 PP_WebSocketBinaryType_Dev binary_type) { |
| 427 // TODO(toyoshim): Use WebKit new API to set the receiving binary type. | 418 switch (binary_type) { |
| 428 return PP_FALSE; | 419 case PP_WEBSOCKETBINARYTYPE_BLOB_DEV: |
| 420 binary_type_ = WebSocket::BinaryTypeBlob; | |
| 421 break; | |
| 422 case PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV: | |
| 423 binary_type_ = WebSocket::BinaryTypeArrayBuffer; | |
| 424 break; | |
| 425 default: | |
| 426 return PP_FALSE; | |
| 427 } | |
| 428 if (!websocket_.get()) | |
| 429 return PP_FALSE; | |
| 430 websocket_->setBinaryType(binary_type_); | |
| 431 return PP_TRUE; | |
| 429 } | 432 } |
| 430 | 433 |
| 431 PP_WebSocketBinaryType_Dev PPB_WebSocket_Impl::GetBinaryType() { | 434 PP_WebSocketBinaryType_Dev PPB_WebSocket_Impl::GetBinaryType() { |
| 432 return binary_type_; | 435 switch (binary_type_) { |
| 436 case WebSocket::BinaryTypeBlob: | |
| 437 return PP_WEBSOCKETBINARYTYPE_BLOB_DEV; | |
| 438 case WebSocket::BinaryTypeArrayBuffer: | |
| 439 return PP_WEBSOCKETBINARYTYPE_ARRAYBUFFER_DEV; | |
| 440 default: | |
| 441 NOTREACHED(); | |
| 442 return PP_WEBSOCKETBINARYTYPE_INVALID; | |
| 443 } | |
| 433 } | 444 } |
| 434 | 445 |
| 435 void PPB_WebSocket_Impl::didConnect() { | 446 void PPB_WebSocket_Impl::didConnect() { |
| 436 DCHECK_EQ(PP_WEBSOCKETREADYSTATE_CONNECTING_DEV, state_); | 447 DCHECK_EQ(PP_WEBSOCKETREADYSTATE_CONNECTING_DEV, state_); |
| 437 state_ = PP_WEBSOCKETREADYSTATE_OPEN_DEV; | 448 state_ = PP_WEBSOCKETREADYSTATE_OPEN_DEV; |
| 438 TrackedCallback::ClearAndRun(&connect_callback_, PP_OK); | 449 TrackedCallback::ClearAndRun(&connect_callback_, PP_OK); |
| 439 } | 450 } |
| 440 | 451 |
| 441 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) { | 452 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) { |
| 442 // Dispose packets after receiving an error or in invalid state. | 453 // Dispose packets after receiving an error or in invalid state. |
| 443 if (error_was_received_ || !InValidStateToReceive(state_)) | 454 if (error_was_received_ || !InValidStateToReceive(state_)) |
| 444 return; | 455 return; |
| 445 | 456 |
| 446 // Append received data to queue. | 457 // Append received data to queue. |
| 447 std::string string = message.utf8(); | 458 std::string string = message.utf8(); |
| 448 PP_Var var = StringVar::StringToPPVar(string); | 459 received_messages_.push(new scoped_refptr<Var>(new StringVar(string))); |
|
dmichael (off chromium)
2012/01/17 22:14:28
You don't want to "new" the scoped_refptr; I think
Takashi Toyoshima
2012/01/18 12:10:43
This time, I misunderstand std::queue using with C
dmichael (off chromium)
2012/01/18 16:20:47
Yep!
| |
| 449 received_messages_.push(var); | |
| 450 | 460 |
| 451 if (!wait_for_receive_) | 461 if (!wait_for_receive_) |
| 452 return; | 462 return; |
| 453 | 463 |
| 454 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); | 464 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); |
| 455 } | 465 } |
| 456 | 466 |
| 457 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { | 467 void PPB_WebSocket_Impl::didReceiveArrayBuffer( |
| 468 const WebArrayBuffer& binaryData) { | |
| 458 // Dispose packets after receiving an error or in invalid state. | 469 // Dispose packets after receiving an error or in invalid state. |
| 459 if (error_was_received_ || !InValidStateToReceive(state_)) | 470 if (error_was_received_ || !InValidStateToReceive(state_)) |
| 460 return; | 471 return; |
| 461 | 472 |
| 462 // Append received data to queue. | 473 // Append received data to queue. |
| 463 PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 474 received_messages_.push( |
| 464 binaryData.size()); | 475 new scoped_refptr<Var>(new HostArrayBufferVar(binaryData))); |
|
dmichael (off chromium)
2012/01/17 22:14:28
Ditto
Takashi Toyoshima
2012/01/18 12:10:43
Done.
| |
| 465 scoped_refptr<ArrayBufferVar> arraybuffer = ArrayBufferVar::FromPPVar(var); | |
| 466 void* data = arraybuffer->Map(); | |
| 467 memcpy(data, binaryData.data(), binaryData.size()); | |
| 468 received_messages_.push(var); | |
| 469 | 476 |
| 470 if (!wait_for_receive_) | 477 if (!wait_for_receive_) |
| 471 return; | 478 return; |
| 472 | 479 |
| 473 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); | 480 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); |
| 474 } | 481 } |
| 475 | 482 |
| 476 void PPB_WebSocket_Impl::didReceiveMessageError() { | 483 void PPB_WebSocket_Impl::didReceiveMessageError() { |
| 477 // Ignore error notification in invalid state. | 484 // Ignore error notification in invalid state. |
| 478 if (!InValidStateToReceive(state_)) | 485 if (!InValidStateToReceive(state_)) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 | 548 |
| 542 // Disconnect. | 549 // Disconnect. |
| 543 if (websocket_.get()) | 550 if (websocket_.get()) |
| 544 websocket_->disconnect(); | 551 websocket_->disconnect(); |
| 545 } | 552 } |
| 546 | 553 |
| 547 int32_t PPB_WebSocket_Impl::DoReceive() { | 554 int32_t PPB_WebSocket_Impl::DoReceive() { |
| 548 if (!receive_callback_var_) | 555 if (!receive_callback_var_) |
| 549 return PP_OK; | 556 return PP_OK; |
| 550 | 557 |
| 551 *receive_callback_var_ = received_messages_.front(); | 558 *receive_callback_var_ = (*received_messages_.front())->GetPPVar(); |
| 552 received_messages_.pop(); | 559 received_messages_.pop(); |
| 553 receive_callback_var_ = NULL; | 560 receive_callback_var_ = NULL; |
| 554 wait_for_receive_ = false; | 561 wait_for_receive_ = false; |
| 555 return PP_OK; | 562 return PP_OK; |
| 556 } | 563 } |
| 557 | 564 |
| 558 } // namespace ppapi | 565 } // namespace ppapi |
| 559 } // namespace webkit | 566 } // namespace webkit |
| OLD | NEW |