Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: webkit/plugins/ppapi/ppb_websocket_impl.cc

Issue 9026007: WebSocket Pepper API: WebArrayBuffer support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" 26 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" 28 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
29 #include "webkit/plugins/ppapi/host_array_buffer_var.h"
27 #include "webkit/plugins/ppapi/host_globals.h" 30 #include "webkit/plugins/ppapi/host_globals.h"
28 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 31 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
29 #include "webkit/plugins/ppapi/resource_helper.h" 32 #include "webkit/plugins/ppapi/resource_helper.h"
30 33
34 using ppapi::ArrayBufferVar;
31 using ppapi::PpapiGlobals; 35 using ppapi::PpapiGlobals;
32 using ppapi::StringVar; 36 using ppapi::StringVar;
33 using ppapi::thunk::PPB_WebSocket_API; 37 using ppapi::thunk::PPB_WebSocket_API;
34 using ppapi::VarTracker; 38 using ppapi::VarTracker;
39 using WebKit::WebArrayBuffer;
35 using WebKit::WebData; 40 using WebKit::WebData;
36 using WebKit::WebDocument; 41 using WebKit::WebDocument;
37 using WebKit::WebString; 42 using WebKit::WebString;
38 using WebKit::WebSocket; 43 using WebKit::WebSocket;
39 using WebKit::WebSocketClient; 44 using WebKit::WebSocketClient;
40 using WebKit::WebURL; 45 using WebKit::WebURL;
41 46
42 const uint32_t kMaxReasonSizeInBytes = 123; 47 const uint32_t kMaxReasonSizeInBytes = 123;
43 const size_t kHybiBaseFramingOverhead = 2; 48 const size_t kHybiBaseFramingOverhead = 2;
44 const size_t kHybiMaskingKeyLength = 4; 49 const size_t kHybiMaskingKeyLength = 4;
45 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; 50 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126;
46 const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000; 51 const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000;
47 52
48 namespace { 53 namespace {
49 54
50 uint64_t SaturateAdd(uint64_t a, uint64_t b) { 55 uint64_t SaturateAdd(uint64_t a, uint64_t b) {
51 if (kuint64max - a < b) 56 if (kuint64max - a < b)
52 return kuint64max; 57 return kuint64max;
53 return a + b; 58 return a + b;
54 } 59 }
55 60
56 uint64_t GetFrameSize(uint64_t payload_size) { 61 uint64_t GetFrameSize(uint64_t payload_size) {
57 if (!payload_size)
58 return 0;
59
60 uint64_t overhead = kHybiBaseFramingOverhead + kHybiMaskingKeyLength; 62 uint64_t overhead = kHybiBaseFramingOverhead + kHybiMaskingKeyLength;
61 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) 63 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength)
62 overhead += 8; 64 overhead += 8;
63 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) 65 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength)
64 overhead += 2; 66 overhead += 2;
65 return SaturateAdd(payload_size, overhead); 67 return SaturateAdd(payload_size, overhead);
66 } 68 }
67 69
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 ||
(...skipping 20 matching lines...) Expand all
90 receive_callback_.func = NULL; 92 receive_callback_.func = NULL;
91 receive_callback_.user_data = NULL; 93 receive_callback_.user_data = NULL;
92 close_callback_.func = NULL; 94 close_callback_.func = NULL;
93 close_callback_.user_data = NULL; 95 close_callback_.user_data = NULL;
94 empty_string_ = new StringVar("", 0); 96 empty_string_ = new StringVar("", 0);
95 } 97 }
96 98
97 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { 99 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() {
98 if (websocket_.get()) 100 if (websocket_.get())
99 websocket_->disconnect(); 101 websocket_->disconnect();
100
101 // Clean up received and unread messages
102 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
103 while (!received_messages_.empty()) {
104 PP_Var var = received_messages_.front();
105 received_messages_.pop();
106 var_tracker->ReleaseVar(var);
107 }
108 } 102 }
109 103
110 // static 104 // static
111 PP_Resource PPB_WebSocket_Impl::Create(PP_Instance instance) { 105 PP_Resource PPB_WebSocket_Impl::Create(PP_Instance instance) {
112 scoped_refptr<PPB_WebSocket_Impl> ws(new PPB_WebSocket_Impl(instance)); 106 scoped_refptr<PPB_WebSocket_Impl> ws(new PPB_WebSocket_Impl(instance));
113 return ws->GetReference(); 107 return ws->GetReference();
114 } 108 }
115 109
116 PPB_WebSocket_API* PPB_WebSocket_Impl::AsPPB_WebSocket_API() { 110 PPB_WebSocket_API* PPB_WebSocket_Impl::AsPPB_WebSocket_API() {
117 return this; 111 return this;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 if (!callback.func) 193 if (!callback.func)
200 return PP_ERROR_BLOCKS_MAIN_THREAD; 194 return PP_ERROR_BLOCKS_MAIN_THREAD;
201 195
202 // Create WebKit::WebSocket object and connect. 196 // Create WebKit::WebSocket object and connect.
203 WebDocument document = plugin_instance->container()->element().document(); 197 WebDocument document = plugin_instance->container()->element().document();
204 websocket_.reset(WebSocket::create(document, this)); 198 websocket_.reset(WebSocket::create(document, this));
205 DCHECK(websocket_.get()); 199 DCHECK(websocket_.get());
206 if (!websocket_.get()) 200 if (!websocket_.get())
207 return PP_ERROR_NOTSUPPORTED; 201 return PP_ERROR_NOTSUPPORTED;
208 202
203 // TODO(toyoshim): Add an interface to specify binary format types.
204 websocket_->setBinaryType("arraybuffer");
205
209 websocket_->connect(web_url, web_protocols); 206 websocket_->connect(web_url, web_protocols);
210 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV; 207 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV;
211 208
212 // Install callback. 209 // Install callback.
213 connect_callback_ = callback; 210 connect_callback_ = callback;
214 211
215 return PP_OK_COMPLETIONPENDING; 212 return PP_OK_COMPLETIONPENDING;
216 } 213 }
217 214
218 int32_t PPB_WebSocket_Impl::Close(uint16_t code, 215 int32_t PPB_WebSocket_Impl::Close(uint16_t code,
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 return PP_ERROR_BADARGUMENT; 316 return PP_ERROR_BADARGUMENT;
320 317
321 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || 318 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV ||
322 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) { 319 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) {
323 // Handle buffered_amount_after_close_. 320 // Handle buffered_amount_after_close_.
324 uint64_t payload_size = 0; 321 uint64_t payload_size = 0;
325 if (message.type == PP_VARTYPE_STRING) { 322 if (message.type == PP_VARTYPE_STRING) {
326 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); 323 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message);
327 if (message_string) 324 if (message_string)
328 payload_size += message_string->value().length(); 325 payload_size += message_string->value().length();
326 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) {
327 scoped_refptr<ArrayBufferVar> message_array_buffer =
328 ArrayBufferVar::FromPPVar(message);
329 if (message_array_buffer)
330 payload_size += message_array_buffer->ByteLength();
331 } else {
332 // TODO(toyoshim): Support Blob.
333 return PP_ERROR_NOTSUPPORTED;
329 } 334 }
330 // TODO(toyoshim): Support binary data.
331 335
332 buffered_amount_after_close_ = 336 buffered_amount_after_close_ =
333 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); 337 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size));
334 338
335 return PP_ERROR_FAILED; 339 return PP_ERROR_FAILED;
336 } 340 }
337 341
338 if (message.type != PP_VARTYPE_STRING) { 342 // Send the message.
339 // TODO(toyoshim): Support binary data. 343 if (message.type == PP_VARTYPE_STRING) {
344 // Convert message to WebString.
345 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message);
346 if (!message_string)
347 return PP_ERROR_BADARGUMENT;
348 WebString web_message = WebString::fromUTF8(message_string->value());
349 if (!websocket_->sendText(web_message))
350 return PP_ERROR_BADARGUMENT;
351 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) {
352 // Convert message to WebArrayBuffer.
353 scoped_refptr<HostArrayBufferVar> host_message =
354 static_cast<HostArrayBufferVar*>(ArrayBufferVar::FromPPVar(message));
355 if (!host_message)
356 return PP_ERROR_BADARGUMENT;
357 WebArrayBuffer& web_message = host_message->webkit_buffer();
358 if (!websocket_->sendArrayBuffer(web_message))
359 return PP_ERROR_BADARGUMENT;
360 } else {
361 // TODO(toyoshim): Support Blob.
340 return PP_ERROR_NOTSUPPORTED; 362 return PP_ERROR_NOTSUPPORTED;
341 } 363 }
342 364
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; 365 return PP_OK;
352 } 366 }
353 367
354 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() { 368 uint64_t PPB_WebSocket_Impl::GetBufferedAmount() {
355 return SaturateAdd(buffered_amount_, buffered_amount_after_close_); 369 return SaturateAdd(buffered_amount_, buffered_amount_after_close_);
356 } 370 }
357 371
358 uint16_t PPB_WebSocket_Impl::GetCloseCode() { 372 uint16_t PPB_WebSocket_Impl::GetCloseCode() {
359 return close_code_; 373 return close_code_;
360 } 374 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK); 416 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK);
403 } 417 }
404 418
405 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) { 419 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) {
406 // Dispose packets after receiving an error or in invalid state. 420 // Dispose packets after receiving an error or in invalid state.
407 if (error_was_received_ || !InValidStateToReceive(state_)) 421 if (error_was_received_ || !InValidStateToReceive(state_))
408 return; 422 return;
409 423
410 // Append received data to queue. 424 // Append received data to queue.
411 std::string string = message.utf8(); 425 std::string string = message.utf8();
412 PP_Var var = StringVar::StringToPPVar(string); 426 received_messages_.push(new StringVar(string));
413 received_messages_.push(var);
414 427
415 if (!wait_for_receive_) 428 if (!wait_for_receive_)
416 return; 429 return;
417 430
418 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive()); 431 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive());
419 } 432 }
420 433
421 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { 434 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) {
422 // Dispose packets after receiving an error or in invalid state. 435 // Dispose packets after receiving an error or in invalid state.
423 if (error_was_received_ || !InValidStateToReceive(state_)) 436 if (error_was_received_ || !InValidStateToReceive(state_))
424 return; 437 return;
425 438
426 // TODO(toyoshim): Support to receive binary data. 439 // Append received data to queue.
427 DLOG(INFO) << "didReceiveBinaryData is not implemented yet."; 440 scoped_refptr<ArrayBufferVar> var =
441 new HostArrayBufferVar(binaryData.size());
442 void* data = var->Map();
443 memcpy(data, binaryData.data(), binaryData.size());
444 received_messages_.push(var);
445
446 if (!wait_for_receive_)
447 return;
448
449 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive());
450 }
451
452 void PPB_WebSocket_Impl::didReceiveArrayBuffer(
453 const WebArrayBuffer& binaryData) {
454 // Dispose packets after receiving an error or in invalid state.
455 if (error_was_received_ || !InValidStateToReceive(state_))
456 return;
457
458 // Append received data to queue.
459 scoped_refptr<ArrayBufferVar> var = new HostArrayBufferVar(binaryData);
460 received_messages_.push(var);
461
462 if (!wait_for_receive_)
463 return;
464
465 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive());
428 } 466 }
429 467
430 void PPB_WebSocket_Impl::didReceiveMessageError() { 468 void PPB_WebSocket_Impl::didReceiveMessageError() {
431 // Ignore error notification in invalid state. 469 // Ignore error notification in invalid state.
432 if (!InValidStateToReceive(state_)) 470 if (!InValidStateToReceive(state_))
433 return; 471 return;
434 472
435 // Records the error, then stops receiving any frames after this error. 473 // Records the error, then stops receiving any frames after this error.
436 // The error will be notified after all queued messages are read via 474 // The error will be notified after all queued messages are read via
437 // ReceiveMessage(). 475 // ReceiveMessage().
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 533
496 // Disconnect. 534 // Disconnect.
497 if (websocket_.get()) 535 if (websocket_.get())
498 websocket_->disconnect(); 536 websocket_->disconnect();
499 } 537 }
500 538
501 int32_t PPB_WebSocket_Impl::DoReceive() { 539 int32_t PPB_WebSocket_Impl::DoReceive() {
502 if (!receive_callback_var_) 540 if (!receive_callback_var_)
503 return PP_OK; 541 return PP_OK;
504 542
505 *receive_callback_var_ = received_messages_.front(); 543 *receive_callback_var_ = received_messages_.front()->GetPPVar();
506 received_messages_.pop(); 544 received_messages_.pop();
507 receive_callback_var_ = NULL; 545 receive_callback_var_ = NULL;
508 wait_for_receive_ = false; 546 wait_for_receive_ = false;
509 return PP_OK; 547 return PP_OK;
510 } 548 }
511 549
512 } // namespace ppapi 550 } // namespace ppapi
513 } // namespace webkit 551 } // namespace webkit
OLDNEW
« webkit/plugins/ppapi/ppb_websocket_impl.h ('K') | « webkit/plugins/ppapi/ppb_websocket_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698