| 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 |