OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/pp_completion_callback.h" | 15 #include "ppapi/c/pp_completion_callback.h" |
15 #include "ppapi/c/pp_errors.h" | 16 #include "ppapi/c/pp_errors.h" |
16 #include "ppapi/c/pp_var.h" | 17 #include "ppapi/c/pp_var.h" |
17 #include "ppapi/c/ppb_var.h" | 18 #include "ppapi/c/ppb_var.h" |
18 #include "ppapi/shared_impl/var.h" | 19 #include "ppapi/shared_impl/var.h" |
19 #include "ppapi/shared_impl/var_tracker.h" | 20 #include "ppapi/shared_impl/var_tracker.h" |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebData.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebData.h" |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" | 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" |
27 #include "webkit/plugins/ppapi/host_globals.h" | 28 #include "webkit/plugins/ppapi/host_globals.h" |
28 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 29 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
29 #include "webkit/plugins/ppapi/resource_helper.h" | 30 #include "webkit/plugins/ppapi/resource_helper.h" |
30 | 31 |
| 32 using ppapi::ArrayBufferVar; |
31 using ppapi::PpapiGlobals; | 33 using ppapi::PpapiGlobals; |
32 using ppapi::StringVar; | 34 using ppapi::StringVar; |
33 using ppapi::thunk::PPB_WebSocket_API; | 35 using ppapi::thunk::PPB_WebSocket_API; |
34 using ppapi::VarTracker; | 36 using ppapi::VarTracker; |
35 using WebKit::WebData; | 37 using WebKit::WebData; |
36 using WebKit::WebDocument; | 38 using WebKit::WebDocument; |
37 using WebKit::WebString; | 39 using WebKit::WebString; |
38 using WebKit::WebSocket; | 40 using WebKit::WebSocket; |
39 using WebKit::WebSocketClient; | 41 using WebKit::WebSocketClient; |
40 using WebKit::WebURL; | 42 using WebKit::WebURL; |
41 | 43 |
42 const uint32_t kMaxReasonSizeInBytes = 123; | 44 const uint32_t kMaxReasonSizeInBytes = 123; |
43 const size_t kHybiBaseFramingOverhead = 2; | 45 const size_t kHybiBaseFramingOverhead = 2; |
44 const size_t kHybiMaskingKeyLength = 4; | 46 const size_t kHybiMaskingKeyLength = 4; |
45 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; | 47 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; |
46 const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000; | 48 const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000; |
47 | 49 |
48 namespace { | 50 namespace { |
49 | 51 |
50 uint64_t SaturateAdd(uint64_t a, uint64_t b) { | 52 uint64_t SaturateAdd(uint64_t a, uint64_t b) { |
51 if (kuint64max - a < b) | 53 if (kuint64max - a < b) |
52 return kuint64max; | 54 return kuint64max; |
53 return a + b; | 55 return a + b; |
54 } | 56 } |
55 | 57 |
56 uint64_t GetFrameSize(uint64_t payload_size) { | 58 uint64_t GetFrameSize(uint64_t payload_size) { |
57 if (!payload_size) | |
58 return 0; | |
59 | |
60 uint64_t overhead = kHybiBaseFramingOverhead + kHybiMaskingKeyLength; | 59 uint64_t overhead = kHybiBaseFramingOverhead + kHybiMaskingKeyLength; |
61 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) | 60 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) |
62 overhead += 8; | 61 overhead += 8; |
63 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) | 62 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) |
64 overhead += 2; | 63 overhead += 2; |
65 return SaturateAdd(payload_size, overhead); | 64 return SaturateAdd(payload_size, overhead); |
66 } | 65 } |
67 | 66 |
68 bool InValidStateToReceive(PP_WebSocketReadyState_Dev state) { | 67 bool InValidStateToReceive(PP_WebSocketReadyState_Dev state) { |
69 return state == PP_WEBSOCKETREADYSTATE_OPEN_DEV || | 68 return state == PP_WEBSOCKETREADYSTATE_OPEN_DEV || |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 } | 276 } |
278 | 277 |
279 int32_t PPB_WebSocket_Impl::ReceiveMessage(PP_Var* message, | 278 int32_t PPB_WebSocket_Impl::ReceiveMessage(PP_Var* message, |
280 PP_CompletionCallback callback) { | 279 PP_CompletionCallback callback) { |
281 // Check state. | 280 // Check state. |
282 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || | 281 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID_DEV || |
283 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) | 282 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) |
284 return PP_ERROR_BADARGUMENT; | 283 return PP_ERROR_BADARGUMENT; |
285 | 284 |
286 // Just return received message if any received message is queued. | 285 // Just return received message if any received message is queued. |
287 if (!received_messages_.empty()) | 286 if (!received_messages_.empty()) { |
| 287 receive_callback_var_ = message; |
288 return DoReceive(); | 288 return DoReceive(); |
| 289 } |
289 | 290 |
290 // Check state again. In CLOSED state, no more messages will be received. | 291 // Check state again. In CLOSED state, no more messages will be received. |
291 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) | 292 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) |
292 return PP_ERROR_BADARGUMENT; | 293 return PP_ERROR_BADARGUMENT; |
293 | 294 |
294 // Returns PP_ERROR_FAILED after an error is received and received messages | 295 // Returns PP_ERROR_FAILED after an error is received and received messages |
295 // is exhausted. | 296 // is exhausted. |
296 if (error_was_received_) | 297 if (error_was_received_) |
297 return PP_ERROR_FAILED; | 298 return PP_ERROR_FAILED; |
298 | 299 |
(...skipping 20 matching lines...) Expand all Loading... |
319 return PP_ERROR_BADARGUMENT; | 320 return PP_ERROR_BADARGUMENT; |
320 | 321 |
321 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || | 322 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || |
322 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { | 323 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { |
323 // Handle buffered_amount_after_close_. | 324 // Handle buffered_amount_after_close_. |
324 uint64_t payload_size = 0; | 325 uint64_t payload_size = 0; |
325 if (message.type == PP_VARTYPE_STRING) { | 326 if (message.type == PP_VARTYPE_STRING) { |
326 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | 327 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); |
327 if (message_string) | 328 if (message_string) |
328 payload_size += message_string->value().length(); | 329 payload_size += message_string->value().length(); |
| 330 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { |
| 331 scoped_refptr<ArrayBufferVar> message_array_buffer = |
| 332 ArrayBufferVar::FromPPVar(message); |
| 333 if (message_array_buffer) |
| 334 payload_size += message_array_buffer->ByteLength(); |
| 335 } else { |
| 336 // TODO(toyoshim): Support Blob. |
| 337 return PP_ERROR_NOTSUPPORTED; |
329 } | 338 } |
330 // TODO(toyoshim): Support binary data. | |
331 | 339 |
332 buffered_amount_after_close_ = | 340 buffered_amount_after_close_ = |
333 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); | 341 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); |
334 | 342 |
335 return PP_ERROR_FAILED; | 343 return PP_ERROR_FAILED; |
336 } | 344 } |
337 | 345 |
338 if (message.type != PP_VARTYPE_STRING) { | 346 // Send the message. |
339 // TODO(toyoshim): Support binary data. | 347 if (message.type == PP_VARTYPE_STRING) { |
| 348 // Convert message to WebString. |
| 349 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); |
| 350 if (!message_string) |
| 351 return PP_ERROR_BADARGUMENT; |
| 352 WebString web_message = WebString::fromUTF8(message_string->value()); |
| 353 if (!websocket_->sendText(web_message)) |
| 354 return PP_ERROR_BADARGUMENT; |
| 355 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { |
| 356 // Convert message to WebData. |
| 357 // TODO(toyoshim): Must add a WebKit interface which handles WebArrayBuffer |
| 358 // directly. |
| 359 scoped_refptr<ArrayBufferVar> message_array_buffer = |
| 360 ArrayBufferVar::FromPPVar(message); |
| 361 if (!message_array_buffer) |
| 362 return PP_ERROR_BADARGUMENT; |
| 363 WebData web_message = WebData( |
| 364 static_cast<const char*>(message_array_buffer->Map()), |
| 365 static_cast<size_t>(message_array_buffer->ByteLength())); |
| 366 if (!websocket_->sendBinary(web_message)) |
| 367 return PP_ERROR_BADARGUMENT; |
| 368 } else { |
| 369 // TODO(toyoshim): Support Blob. |
340 return PP_ERROR_NOTSUPPORTED; | 370 return PP_ERROR_NOTSUPPORTED; |
341 } | 371 } |
342 | 372 |
343 // Convert message to WebString. | |
344 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | |
345 if (!message_string) | |
346 return PP_ERROR_BADARGUMENT; | |
347 WebString web_message = WebString::fromUTF8(message_string->value()); | |
348 if (!websocket_->sendText(web_message)) | |
349 return PP_ERROR_BADARGUMENT; | |
350 | |
351 return PP_OK; | 373 return PP_OK; |
352 } | 374 } |
353 | 375 |
354 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { | 376 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { |
355 return SaturateAdd(buffered_amount_, buffered_amount_after_close_); | 377 return SaturateAdd(buffered_amount_, buffered_amount_after_close_); |
356 } | 378 } |
357 | 379 |
358 uint16_t PPB_WebSocket_Impl::GetCloseCode() { | 380 uint16_t PPB_WebSocket_Impl::GetCloseCode() { |
359 return close_code_; | 381 return close_code_; |
360 } | 382 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 return; | 438 return; |
417 | 439 |
418 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive()); | 440 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive()); |
419 } | 441 } |
420 | 442 |
421 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { | 443 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { |
422 // Dispose packets after receiving an error or in invalid state. | 444 // Dispose packets after receiving an error or in invalid state. |
423 if (error_was_received_ || !InValidStateToReceive(state_)) | 445 if (error_was_received_ || !InValidStateToReceive(state_)) |
424 return; | 446 return; |
425 | 447 |
426 // TODO(toyoshim): Support to receive binary data. | 448 // Append received data to queue. |
427 DLOG(INFO) << "didReceiveBinaryData is not implemented yet."; | 449 PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
| 450 binaryData.size()); |
| 451 scoped_refptr<ArrayBufferVar> arraybuffer = ArrayBufferVar::FromPPVar(var); |
| 452 void* data = arraybuffer->Map(); |
| 453 memcpy(data, binaryData.data(), binaryData.size()); |
| 454 received_messages_.push(var); |
| 455 |
| 456 if (!wait_for_receive_) |
| 457 return; |
| 458 |
| 459 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive()); |
428 } | 460 } |
429 | 461 |
430 void PPB_WebSocket_Impl::didReceiveMessageError() { | 462 void PPB_WebSocket_Impl::didReceiveMessageError() { |
431 // Ignore error notification in invalid state. | 463 // Ignore error notification in invalid state. |
432 if (!InValidStateToReceive(state_)) | 464 if (!InValidStateToReceive(state_)) |
433 return; | 465 return; |
434 | 466 |
435 // Records the error, then stops receiving any frames after this error. | 467 // Records the error, then stops receiving any frames after this error. |
436 // The error will be notified after all queued messages are read via | 468 // The error will be notified after all queued messages are read via |
437 // ReceiveMessage(). | 469 // ReceiveMessage(). |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 | 536 |
505 *receive_callback_var_ = received_messages_.front(); | 537 *receive_callback_var_ = received_messages_.front(); |
506 received_messages_.pop(); | 538 received_messages_.pop(); |
507 receive_callback_var_ = NULL; | 539 receive_callback_var_ = NULL; |
508 wait_for_receive_ = false; | 540 wait_for_receive_ = false; |
509 return PP_OK; | 541 return PP_OK; |
510 } | 542 } |
511 | 543 |
512 } // namespace ppapi | 544 } // namespace ppapi |
513 } // namespace webkit | 545 } // namespace webkit |
OLD | NEW |