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 |