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" |
(...skipping 15 matching lines...) Expand all Loading... |
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_globals.h" | 28 #include "webkit/plugins/ppapi/host_globals.h" |
29 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 29 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
30 #include "webkit/plugins/ppapi/resource_helper.h" | 30 #include "webkit/plugins/ppapi/resource_helper.h" |
31 | 31 |
32 using ppapi::ArrayBufferVar; | 32 using ppapi::ArrayBufferVar; |
33 using ppapi::PpapiGlobals; | 33 using ppapi::PpapiGlobals; |
34 using ppapi::StringVar; | 34 using ppapi::StringVar; |
35 using ppapi::thunk::PPB_WebSocket_API; | 35 using ppapi::thunk::PPB_WebSocket_API; |
| 36 using ppapi::TrackedCallback; |
36 using ppapi::VarTracker; | 37 using ppapi::VarTracker; |
37 using WebKit::WebData; | 38 using WebKit::WebData; |
38 using WebKit::WebDocument; | 39 using WebKit::WebDocument; |
39 using WebKit::WebString; | 40 using WebKit::WebString; |
40 using WebKit::WebSocket; | 41 using WebKit::WebSocket; |
41 using WebKit::WebSocketClient; | 42 using WebKit::WebSocketClient; |
42 using WebKit::WebURL; | 43 using WebKit::WebURL; |
43 | 44 |
44 const uint32_t kMaxReasonSizeInBytes = 123; | 45 const uint32_t kMaxReasonSizeInBytes = 123; |
45 const size_t kHybiBaseFramingOverhead = 2; | 46 const size_t kHybiBaseFramingOverhead = 2; |
(...skipping 29 matching lines...) Expand all Loading... |
75 namespace ppapi { | 76 namespace ppapi { |
76 | 77 |
77 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) | 78 PPB_WebSocket_Impl::PPB_WebSocket_Impl(PP_Instance instance) |
78 : Resource(instance), | 79 : Resource(instance), |
79 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), | 80 state_(PP_WEBSOCKETREADYSTATE_INVALID_DEV), |
80 error_was_received_(false), | 81 error_was_received_(false), |
81 receive_callback_var_(NULL), | 82 receive_callback_var_(NULL), |
82 wait_for_receive_(false), | 83 wait_for_receive_(false), |
83 close_code_(0), | 84 close_code_(0), |
84 close_was_clean_(PP_FALSE), | 85 close_was_clean_(PP_FALSE), |
| 86 empty_string_(new StringVar("", 0)), |
85 buffered_amount_(0), | 87 buffered_amount_(0), |
86 buffered_amount_after_close_(0) { | 88 buffered_amount_after_close_(0) { |
87 connect_callback_.func = NULL; | |
88 connect_callback_.user_data = NULL; | |
89 receive_callback_.func = NULL; | |
90 receive_callback_.user_data = NULL; | |
91 close_callback_.func = NULL; | |
92 close_callback_.user_data = NULL; | |
93 empty_string_ = new StringVar("", 0); | |
94 } | 89 } |
95 | 90 |
96 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { | 91 PPB_WebSocket_Impl::~PPB_WebSocket_Impl() { |
97 if (websocket_.get()) | 92 if (websocket_.get()) |
98 websocket_->disconnect(); | 93 websocket_->disconnect(); |
99 | 94 |
100 // Clean up received and unread messages | 95 // Clean up received and unread messages |
101 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); | 96 VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker(); |
102 while (!received_messages_.empty()) { | 97 while (!received_messages_.empty()) { |
103 PP_Var var = received_messages_.front(); | 98 PP_Var var = received_messages_.front(); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 WebDocument document = plugin_instance->container()->element().document(); | 197 WebDocument document = plugin_instance->container()->element().document(); |
203 websocket_.reset(WebSocket::create(document, this)); | 198 websocket_.reset(WebSocket::create(document, this)); |
204 DCHECK(websocket_.get()); | 199 DCHECK(websocket_.get()); |
205 if (!websocket_.get()) | 200 if (!websocket_.get()) |
206 return PP_ERROR_NOTSUPPORTED; | 201 return PP_ERROR_NOTSUPPORTED; |
207 | 202 |
208 websocket_->connect(web_url, web_protocols); | 203 websocket_->connect(web_url, web_protocols); |
209 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV; | 204 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING_DEV; |
210 | 205 |
211 // Install callback. | 206 // Install callback. |
212 connect_callback_ = callback; | 207 connect_callback_ = new TrackedCallback(this, callback); |
213 | 208 |
214 return PP_OK_COMPLETIONPENDING; | 209 return PP_OK_COMPLETIONPENDING; |
215 } | 210 } |
216 | 211 |
217 int32_t PPB_WebSocket_Impl::Close(uint16_t code, | 212 int32_t PPB_WebSocket_Impl::Close(uint16_t code, |
218 PP_Var reason, | 213 PP_Var reason, |
219 PP_CompletionCallback callback) { | 214 PP_CompletionCallback callback) { |
220 // Check mandarory interfaces. | 215 // Check mandarory interfaces. |
221 if (!websocket_.get()) | 216 if (!websocket_.get()) |
222 return PP_ERROR_FAILED; | 217 return PP_ERROR_FAILED; |
(...skipping 20 matching lines...) Expand all Loading... |
243 // Check state. | 238 // Check state. |
244 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || | 239 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING_DEV || |
245 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) | 240 state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) |
246 return PP_ERROR_INPROGRESS; | 241 return PP_ERROR_INPROGRESS; |
247 | 242 |
248 // Validate |callback| (Doesn't support blocking callback) | 243 // Validate |callback| (Doesn't support blocking callback) |
249 if (!callback.func) | 244 if (!callback.func) |
250 return PP_ERROR_BLOCKS_MAIN_THREAD; | 245 return PP_ERROR_BLOCKS_MAIN_THREAD; |
251 | 246 |
252 // Install |callback|. | 247 // Install |callback|. |
253 close_callback_ = callback; | 248 close_callback_ = new TrackedCallback(this, callback); |
254 | 249 |
255 // Abort ongoing connect. | 250 // Abort ongoing connect. |
256 if (state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) { | 251 if (state_ == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) { |
257 state_ = PP_WEBSOCKETREADYSTATE_CLOSING_DEV; | 252 state_ = PP_WEBSOCKETREADYSTATE_CLOSING_DEV; |
258 PP_RunAndClearCompletionCallback(&connect_callback_, PP_ERROR_ABORTED); | 253 // Need to do a "Post" to avoid reentering the plugin. |
| 254 connect_callback_->PostAbort(); |
| 255 connect_callback_ = NULL; |
259 websocket_->fail( | 256 websocket_->fail( |
260 "WebSocket was closed before the connection was established."); | 257 "WebSocket was closed before the connection was established."); |
261 return PP_OK_COMPLETIONPENDING; | 258 return PP_OK_COMPLETIONPENDING; |
262 } | 259 } |
263 | 260 |
264 // Abort ongoing receive. | 261 // Abort ongoing receive. |
265 if (wait_for_receive_) { | 262 if (wait_for_receive_) { |
266 wait_for_receive_ = false; | 263 wait_for_receive_ = false; |
267 receive_callback_var_ = NULL; | 264 receive_callback_var_ = NULL; |
268 PP_RunAndClearCompletionCallback(&receive_callback_, PP_ERROR_ABORTED); | 265 |
| 266 // Need to do a "Post" to avoid reentering the plugin. |
| 267 receive_callback_->PostAbort(); |
| 268 receive_callback_ = NULL; |
269 } | 269 } |
270 | 270 |
271 // Close connection. | 271 // Close connection. |
272 state_ = PP_WEBSOCKETREADYSTATE_CLOSING_DEV; | 272 state_ = PP_WEBSOCKETREADYSTATE_CLOSING_DEV; |
273 WebString web_reason = WebString::fromUTF8(reason_string->value()); | 273 WebString web_reason = WebString::fromUTF8(reason_string->value()); |
274 websocket_->close(code, web_reason); | 274 websocket_->close(code, web_reason); |
275 | 275 |
276 return PP_OK_COMPLETIONPENDING; | 276 return PP_OK_COMPLETIONPENDING; |
277 } | 277 } |
278 | 278 |
(...skipping 19 matching lines...) Expand all Loading... |
298 if (error_was_received_) | 298 if (error_was_received_) |
299 return PP_ERROR_FAILED; | 299 return PP_ERROR_FAILED; |
300 | 300 |
301 // Validate |callback| (Doesn't support blocking callback) | 301 // Validate |callback| (Doesn't support blocking callback) |
302 if (!callback.func) | 302 if (!callback.func) |
303 return PP_ERROR_BLOCKS_MAIN_THREAD; | 303 return PP_ERROR_BLOCKS_MAIN_THREAD; |
304 | 304 |
305 // Or retain |message| as buffer to store and install |callback|. | 305 // Or retain |message| as buffer to store and install |callback|. |
306 wait_for_receive_ = true; | 306 wait_for_receive_ = true; |
307 receive_callback_var_ = message; | 307 receive_callback_var_ = message; |
308 receive_callback_ = callback; | 308 receive_callback_ = new TrackedCallback(this, callback); |
309 | 309 |
310 return PP_OK_COMPLETIONPENDING; | 310 return PP_OK_COMPLETIONPENDING; |
311 } | 311 } |
312 | 312 |
313 int32_t PPB_WebSocket_Impl::SendMessage(PP_Var message) { | 313 int32_t PPB_WebSocket_Impl::SendMessage(PP_Var message) { |
314 // Check mandatory interfaces. | 314 // Check mandatory interfaces. |
315 if (!websocket_.get()) | 315 if (!websocket_.get()) |
316 return PP_ERROR_FAILED; | 316 return PP_ERROR_FAILED; |
317 | 317 |
318 // Check state. | 318 // Check state. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 | 415 |
416 PP_Var PPB_WebSocket_Impl::GetURL() { | 416 PP_Var PPB_WebSocket_Impl::GetURL() { |
417 if (!url_) | 417 if (!url_) |
418 return empty_string_->GetPPVar(); | 418 return empty_string_->GetPPVar(); |
419 return url_->GetPPVar(); | 419 return url_->GetPPVar(); |
420 } | 420 } |
421 | 421 |
422 void PPB_WebSocket_Impl::didConnect() { | 422 void PPB_WebSocket_Impl::didConnect() { |
423 DCHECK_EQ(PP_WEBSOCKETREADYSTATE_CONNECTING_DEV, state_); | 423 DCHECK_EQ(PP_WEBSOCKETREADYSTATE_CONNECTING_DEV, state_); |
424 state_ = PP_WEBSOCKETREADYSTATE_OPEN_DEV; | 424 state_ = PP_WEBSOCKETREADYSTATE_OPEN_DEV; |
425 PP_RunAndClearCompletionCallback(&connect_callback_, PP_OK); | 425 TrackedCallback::ClearAndRun(&connect_callback_, PP_OK); |
426 } | 426 } |
427 | 427 |
428 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) { | 428 void PPB_WebSocket_Impl::didReceiveMessage(const WebString& message) { |
429 // Dispose packets after receiving an error or in invalid state. | 429 // Dispose packets after receiving an error or in invalid state. |
430 if (error_was_received_ || !InValidStateToReceive(state_)) | 430 if (error_was_received_ || !InValidStateToReceive(state_)) |
431 return; | 431 return; |
432 | 432 |
433 // Append received data to queue. | 433 // Append received data to queue. |
434 std::string string = message.utf8(); | 434 std::string string = message.utf8(); |
435 PP_Var var = StringVar::StringToPPVar(string); | 435 PP_Var var = StringVar::StringToPPVar(string); |
436 received_messages_.push(var); | 436 received_messages_.push(var); |
437 | 437 |
438 if (!wait_for_receive_) | 438 if (!wait_for_receive_) |
439 return; | 439 return; |
440 | 440 |
441 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive()); | 441 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); |
442 } | 442 } |
443 | 443 |
444 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { | 444 void PPB_WebSocket_Impl::didReceiveBinaryData(const WebData& binaryData) { |
445 // Dispose packets after receiving an error or in invalid state. | 445 // Dispose packets after receiving an error or in invalid state. |
446 if (error_was_received_ || !InValidStateToReceive(state_)) | 446 if (error_was_received_ || !InValidStateToReceive(state_)) |
447 return; | 447 return; |
448 | 448 |
449 // Append received data to queue. | 449 // Append received data to queue. |
450 PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | 450 PP_Var var = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( |
451 binaryData.size()); | 451 binaryData.size()); |
452 scoped_refptr<ArrayBufferVar> arraybuffer = ArrayBufferVar::FromPPVar(var); | 452 scoped_refptr<ArrayBufferVar> arraybuffer = ArrayBufferVar::FromPPVar(var); |
453 void* data = arraybuffer->Map(); | 453 void* data = arraybuffer->Map(); |
454 memcpy(data, binaryData.data(), binaryData.size()); | 454 memcpy(data, binaryData.data(), binaryData.size()); |
455 received_messages_.push(var); | 455 received_messages_.push(var); |
456 | 456 |
457 if (!wait_for_receive_) | 457 if (!wait_for_receive_) |
458 return; | 458 return; |
459 | 459 |
460 PP_RunAndClearCompletionCallback(&receive_callback_, DoReceive()); | 460 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); |
461 } | 461 } |
462 | 462 |
463 void PPB_WebSocket_Impl::didReceiveMessageError() { | 463 void PPB_WebSocket_Impl::didReceiveMessageError() { |
464 // Ignore error notification in invalid state. | 464 // Ignore error notification in invalid state. |
465 if (!InValidStateToReceive(state_)) | 465 if (!InValidStateToReceive(state_)) |
466 return; | 466 return; |
467 | 467 |
468 // Records the error, then stops receiving any frames after this error. | 468 // Records the error, then stops receiving any frames after this error. |
469 // The error will be notified after all queued messages are read via | 469 // The error will be notified after all queued messages are read via |
470 // ReceiveMessage(). | 470 // ReceiveMessage(). |
471 error_was_received_ = true; | 471 error_was_received_ = true; |
472 if (!wait_for_receive_) | 472 if (!wait_for_receive_) |
473 return; | 473 return; |
474 | 474 |
475 // But, if no messages are queued and ReceiveMessage() is now on going. | 475 // But, if no messages are queued and ReceiveMessage() is now on going. |
476 // We must invoke the callback with error code here. | 476 // We must invoke the callback with error code here. |
477 wait_for_receive_ = false; | 477 wait_for_receive_ = false; |
478 receive_callback_var_ = NULL; | 478 receive_callback_var_ = NULL; |
479 PP_RunAndClearCompletionCallback(&receive_callback_, PP_ERROR_FAILED); | 479 TrackedCallback::ClearAndRun(&receive_callback_, PP_ERROR_FAILED); |
480 } | 480 } |
481 | 481 |
482 void PPB_WebSocket_Impl::didUpdateBufferedAmount( | 482 void PPB_WebSocket_Impl::didUpdateBufferedAmount( |
483 unsigned long buffered_amount) { | 483 unsigned long buffered_amount) { |
484 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) | 484 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED_DEV) |
485 return; | 485 return; |
486 buffered_amount_ = buffered_amount; | 486 buffered_amount_ = buffered_amount; |
487 } | 487 } |
488 | 488 |
489 void PPB_WebSocket_Impl::didStartClosingHandshake() { | 489 void PPB_WebSocket_Impl::didStartClosingHandshake() { |
(...skipping 18 matching lines...) Expand all Loading... |
508 | 508 |
509 // Update buffered_amount_. | 509 // Update buffered_amount_. |
510 buffered_amount_ = unhandled_buffered_amount; | 510 buffered_amount_ = unhandled_buffered_amount; |
511 | 511 |
512 // Handle state transition and invoking callback. | 512 // Handle state transition and invoking callback. |
513 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_); | 513 DCHECK_NE(PP_WEBSOCKETREADYSTATE_CLOSED_DEV, state_); |
514 PP_WebSocketReadyState_Dev state = state_; | 514 PP_WebSocketReadyState_Dev state = state_; |
515 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV; | 515 state_ = PP_WEBSOCKETREADYSTATE_CLOSED_DEV; |
516 | 516 |
517 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) | 517 if (state == PP_WEBSOCKETREADYSTATE_CONNECTING_DEV) |
518 PP_RunAndClearCompletionCallback(&connect_callback_, PP_ERROR_FAILED); | 518 TrackedCallback::ClearAndRun(&connect_callback_, PP_ERROR_FAILED); |
519 | 519 |
520 if (wait_for_receive_) { | 520 if (wait_for_receive_) { |
521 wait_for_receive_ = false; | 521 wait_for_receive_ = false; |
522 receive_callback_var_ = NULL; | 522 receive_callback_var_ = NULL; |
523 PP_RunAndClearCompletionCallback(&receive_callback_, PP_ERROR_ABORTED); | 523 TrackedCallback::ClearAndAbort(&receive_callback_); |
524 } | 524 } |
525 | 525 |
526 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV) | 526 if (state == PP_WEBSOCKETREADYSTATE_CLOSING_DEV) |
527 PP_RunAndClearCompletionCallback(&close_callback_, PP_OK); | 527 TrackedCallback::ClearAndRun(&close_callback_, PP_OK); |
528 | 528 |
529 // Disconnect. | 529 // Disconnect. |
530 if (websocket_.get()) | 530 if (websocket_.get()) |
531 websocket_->disconnect(); | 531 websocket_->disconnect(); |
532 } | 532 } |
533 | 533 |
534 int32_t PPB_WebSocket_Impl::DoReceive() { | 534 int32_t PPB_WebSocket_Impl::DoReceive() { |
535 if (!receive_callback_var_) | 535 if (!receive_callback_var_) |
536 return PP_OK; | 536 return PP_OK; |
537 | 537 |
538 *receive_callback_var_ = received_messages_.front(); | 538 *receive_callback_var_ = received_messages_.front(); |
539 received_messages_.pop(); | 539 received_messages_.pop(); |
540 receive_callback_var_ = NULL; | 540 receive_callback_var_ = NULL; |
541 wait_for_receive_ = false; | 541 wait_for_receive_ = false; |
542 return PP_OK; | 542 return PP_OK; |
543 } | 543 } |
544 | 544 |
545 } // namespace ppapi | 545 } // namespace ppapi |
546 } // namespace webkit | 546 } // namespace webkit |
OLD | NEW |