Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ppapi/proxy/websocket_resource.h" | |
| 6 | |
| 7 #include <set> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "ppapi/c/pp_errors.h" | |
| 11 #include "ppapi/proxy/ppapi_messages.h" | |
| 12 #include "ppapi/shared_impl/ppapi_globals.h" | |
| 13 #include "ppapi/shared_impl/var.h" | |
| 14 #include "ppapi/shared_impl/var_tracker.h" | |
| 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSocket.h" | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 const uint32_t kMaxReasonSizeInBytes = 123; | |
| 20 const size_t kBaseFramingOverhead = 2; | |
| 21 const size_t kMaskingKeyLength = 4; | |
| 22 const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; | |
| 23 const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000; | |
| 24 | |
| 25 uint64_t SaturateAdd(uint64_t a, uint64_t b) { | |
| 26 if (kuint64max - a < b) | |
| 27 return kuint64max; | |
| 28 return a + b; | |
| 29 } | |
| 30 | |
| 31 uint64_t GetFrameSize(uint64_t payload_size) { | |
| 32 uint64_t overhead = kBaseFramingOverhead + kMaskingKeyLength; | |
| 33 if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) | |
| 34 overhead += 8; | |
| 35 else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) | |
| 36 overhead += 2; | |
| 37 return SaturateAdd(payload_size, overhead); | |
| 38 } | |
| 39 | |
| 40 bool InValidStateToReceive(PP_WebSocketReadyState state) { | |
| 41 return state == PP_WEBSOCKETREADYSTATE_OPEN || | |
| 42 state == PP_WEBSOCKETREADYSTATE_CLOSING; | |
| 43 } | |
| 44 | |
| 45 } // namespace | |
| 46 | |
| 47 | |
| 48 namespace ppapi { | |
| 49 namespace proxy { | |
| 50 | |
| 51 WebSocketResource::WebSocketResource(Connection connection, | |
| 52 PP_Instance instance) | |
| 53 : PluginResource(connection, instance), | |
| 54 connect_request_id_(0), | |
| 55 close_request_id_(0), | |
| 56 state_(PP_WEBSOCKETREADYSTATE_INVALID), | |
| 57 error_was_received_(false), | |
| 58 receive_callback_var_(NULL), | |
| 59 empty_string_(new StringVar("", 0)), | |
| 60 close_code_(0), | |
| 61 close_reason_(NULL), | |
| 62 close_was_clean_(PP_FALSE), | |
| 63 extensions_(NULL), | |
| 64 protocol_(NULL), | |
| 65 url_(NULL), | |
| 66 buffered_amount_(0), | |
| 67 buffered_amount_after_close_(0) { | |
| 68 } | |
| 69 | |
| 70 WebSocketResource::~WebSocketResource() { | |
| 71 } | |
| 72 | |
| 73 thunk::PPB_WebSocket_API* WebSocketResource::AsPPB_WebSocket_API() { | |
| 74 return this; | |
| 75 } | |
| 76 | |
| 77 int32_t WebSocketResource::Connect( | |
| 78 PP_Var url, | |
|
brettw
2012/10/03 04:54:02
Can you make this (in the _api as well) a const re
Takashi Toyoshima
2012/10/03 11:42:20
I think we have not used const ref for PP_Var usua
brettw
2012/10/03 20:30:24
We shouldn't change the C bindings, which are the
Takashi Toyoshima
2012/10/05 07:35:01
Thank you.
Now I understand the reason of PP_Var c
| |
| 79 const PP_Var protocols[], | |
| 80 uint32_t protocol_count, | |
| 81 scoped_refptr<TrackedCallback> callback) { | |
| 82 if (TrackedCallback::IsPending(connect_callback_)) | |
| 83 return PP_ERROR_INPROGRESS; | |
| 84 | |
| 85 // Connect() can be called at most once. | |
| 86 if (state_ != PP_WEBSOCKETREADYSTATE_INVALID) | |
| 87 return PP_ERROR_INPROGRESS; | |
| 88 state_ = PP_WEBSOCKETREADYSTATE_CLOSED; | |
| 89 | |
| 90 // Get the URL. | |
| 91 scoped_refptr<StringVar> url_string = StringVar::FromPPVar(url); | |
| 92 if (!url_string) | |
| 93 return PP_ERROR_BADARGUMENT; | |
| 94 | |
| 95 // Validate protocols. | |
| 96 std::string protocol_string; | |
| 97 std::set<std::string> protocol_set; | |
| 98 for (uint32_t i = 0; i < protocol_count; i++) { | |
| 99 scoped_refptr<StringVar> protocol(StringVar::FromPPVar(protocols[i])); | |
| 100 | |
| 101 // Check invalid and empty entries. | |
| 102 if (!protocol || !protocol->value().length()) | |
| 103 return PP_ERROR_BADARGUMENT; | |
| 104 | |
| 105 // Check duplicated protocol entries. | |
| 106 if (protocol_set.find(protocol->value()) != protocol_set.end()) | |
| 107 return PP_ERROR_BADARGUMENT; | |
| 108 protocol_set.insert(protocol->value()); | |
| 109 | |
| 110 // Check containing characters. | |
| 111 for (std::string::const_iterator it = protocol->value().begin(); | |
| 112 it != protocol->value().end(); | |
| 113 ++it) { | |
| 114 uint8_t character = *it; | |
| 115 // WebSocket specification says "(Subprotocol string must consist of) | |
| 116 // characters in the range U+0021 to U+007E not including separator | |
| 117 // characters as defined in [RFC2616]." | |
| 118 const uint8_t minimumProtocolCharacter = '!'; // U+0021. | |
|
brettw
2012/10/03 04:54:02
To what extent is this checking security sensitive
Takashi Toyoshima
2012/10/03 11:46:28
Firstly, I think this check is safe to run in NaCl
| |
| 119 const uint8_t maximumProtocolCharacter = '~'; // U+007E. | |
| 120 if (character < minimumProtocolCharacter || | |
| 121 character > maximumProtocolCharacter || | |
| 122 character == '"' || character == '(' || character == ')' || | |
| 123 character == ',' || character == '/' || | |
| 124 (character >= ':' && character <= '@') || // U+003A - U+0040 | |
| 125 (character >= '[' && character <= ']') || // U+005B - u+005D | |
| 126 character == '{' || character == '}') | |
| 127 return PP_ERROR_BADARGUMENT; | |
| 128 } | |
| 129 // Join protocols with the comma separator. | |
| 130 if (i != 0) | |
| 131 protocol_string.append(","); | |
| 132 protocol_string.append(protocol->value()); | |
| 133 } | |
| 134 | |
| 135 // Install callback. | |
| 136 connect_callback_ = callback; | |
| 137 | |
| 138 // Create remote host in the renderer, then request to check the URL and | |
| 139 // establish the connection. | |
| 140 state_ = PP_WEBSOCKETREADYSTATE_CONNECTING; | |
| 141 SendCreateToRenderer(PpapiHostMsg_WebSocket_Create()); | |
| 142 connect_request_id_ = | |
| 143 CallRenderer(PpapiHostMsg_WebSocket_Connect(url_string->value(), | |
| 144 protocol_string)); | |
| 145 | |
| 146 return PP_OK_COMPLETIONPENDING; | |
| 147 } | |
| 148 | |
| 149 int32_t WebSocketResource::Close(uint16_t code, | |
| 150 PP_Var reason, | |
| 151 scoped_refptr<TrackedCallback> callback) { | |
| 152 if (TrackedCallback::IsPending(close_callback_)) | |
| 153 return PP_ERROR_INPROGRESS; | |
| 154 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID) | |
| 155 return PP_ERROR_FAILED; | |
| 156 | |
| 157 // Validate |code| and |reason|. | |
| 158 scoped_refptr<StringVar> reason_string_var; | |
| 159 std::string reason_string; | |
| 160 WebKit::WebSocket::CloseEventCode event_code = | |
| 161 static_cast<WebKit::WebSocket::CloseEventCode>(code); | |
| 162 if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) { | |
| 163 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are | |
| 164 // assigned to different values. A conversion is needed if | |
| 165 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified. | |
| 166 event_code = WebKit::WebSocket::CloseEventCodeNotSpecified; | |
| 167 } else { | |
| 168 if (!(code == PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE || | |
| 169 (PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN <= code && | |
| 170 code <= PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX))) | |
| 171 // RFC 6455 limits applications to use reserved connection close code in | |
| 172 // section 7.4.2.. The WebSocket API (http://www.w3.org/TR/websockets/) | |
| 173 // defines this out of range error as InvalidAccessError in JavaScript. | |
| 174 return PP_ERROR_NOACCESS; | |
| 175 | |
| 176 // |reason| must be ignored if it is PP_VARTYPE_UNDEFINED or |code| is | |
| 177 // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED. | |
| 178 if (reason.type != PP_VARTYPE_UNDEFINED) { | |
| 179 // Validate |reason|. | |
| 180 reason_string_var = StringVar::FromPPVar(reason); | |
| 181 if (!reason_string_var || | |
| 182 reason_string_var->value().size() > kMaxReasonSizeInBytes) | |
| 183 return PP_ERROR_BADARGUMENT; | |
| 184 reason_string = reason_string_var->value(); | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 // Check state. | |
| 189 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING) | |
| 190 return PP_ERROR_INPROGRESS; | |
| 191 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED) | |
| 192 return PP_OK; | |
| 193 | |
| 194 // Install |callback|. | |
| 195 close_callback_ = callback; | |
| 196 | |
| 197 // Abort ongoing connect. | |
| 198 if (connect_callback_) { | |
| 199 state_ = PP_WEBSOCKETREADYSTATE_CLOSING; | |
| 200 // Need to do a "Post" to avoid reentering the plugin. | |
| 201 connect_callback_->PostAbort(); | |
| 202 connect_callback_ = NULL; | |
| 203 CallRenderer(PpapiHostMsg_WebSocket_Fail( | |
| 204 "WebSocket was closed before the connection was established.")); | |
| 205 return PP_OK_COMPLETIONPENDING; | |
| 206 } | |
| 207 | |
| 208 // Abort ongoing receive. | |
| 209 if (receive_callback_) { | |
| 210 receive_callback_var_ = NULL; | |
| 211 // Need to do a "Post" to avoid reentering the plugin. | |
| 212 receive_callback_->PostAbort(); | |
| 213 receive_callback_ = NULL; | |
| 214 } | |
| 215 | |
| 216 // Close connection. | |
| 217 state_ = PP_WEBSOCKETREADYSTATE_CLOSING; | |
| 218 close_request_id_ = | |
| 219 CallRenderer(PpapiHostMsg_WebSocket_Close((int32_t)event_code, | |
|
brettw
2012/10/03 04:54:02
Nit: use C++ casts.
Takashi Toyoshima
2012/10/03 11:42:20
Done.
| |
| 220 reason_string)); | |
| 221 return PP_OK_COMPLETIONPENDING; | |
| 222 } | |
| 223 | |
| 224 int32_t WebSocketResource::ReceiveMessage( | |
| 225 PP_Var* message, | |
| 226 scoped_refptr<TrackedCallback> callback) { | |
| 227 if (TrackedCallback::IsPending(receive_callback_)) | |
| 228 return PP_ERROR_INPROGRESS; | |
| 229 | |
| 230 // Check state. | |
| 231 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID || | |
| 232 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING) | |
| 233 return PP_ERROR_BADARGUMENT; | |
| 234 | |
| 235 // Just return received message if any received message is queued. | |
| 236 if (!received_messages_.empty()) { | |
| 237 receive_callback_var_ = message; | |
| 238 return DoReceive(); | |
| 239 } | |
| 240 | |
| 241 // Check state again. In CLOSED state, no more messages will be received. | |
| 242 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED) | |
| 243 return PP_ERROR_BADARGUMENT; | |
| 244 | |
| 245 // Returns PP_ERROR_FAILED after an error is received and received messages | |
| 246 // is exhausted. | |
| 247 if (error_was_received_) | |
| 248 return PP_ERROR_FAILED; | |
| 249 | |
| 250 // Or retain |message| as buffer to store and install |callback|. | |
| 251 receive_callback_var_ = message; | |
| 252 receive_callback_ = callback; | |
| 253 | |
| 254 return PP_OK_COMPLETIONPENDING; | |
| 255 } | |
| 256 | |
| 257 int32_t WebSocketResource::SendMessage(PP_Var message) { | |
| 258 // Check state. | |
| 259 if (state_ == PP_WEBSOCKETREADYSTATE_INVALID || | |
| 260 state_ == PP_WEBSOCKETREADYSTATE_CONNECTING) | |
| 261 return PP_ERROR_BADARGUMENT; | |
| 262 | |
| 263 if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING || | |
| 264 state_ == PP_WEBSOCKETREADYSTATE_CLOSED) { | |
| 265 // Handle buffered_amount_after_close_. | |
| 266 uint64_t payload_size = 0; | |
| 267 if (message.type == PP_VARTYPE_STRING) { | |
| 268 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | |
| 269 if (message_string) | |
| 270 payload_size += message_string->value().length(); | |
| 271 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { | |
| 272 scoped_refptr<ArrayBufferVar> message_array_buffer = | |
| 273 ArrayBufferVar::FromPPVar(message); | |
| 274 if (message_array_buffer) | |
| 275 payload_size += message_array_buffer->ByteLength(); | |
| 276 } else { | |
| 277 // TODO(toyoshim): Support Blob. | |
| 278 return PP_ERROR_NOTSUPPORTED; | |
| 279 } | |
| 280 | |
| 281 buffered_amount_after_close_ = | |
| 282 SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); | |
| 283 | |
| 284 return PP_ERROR_FAILED; | |
| 285 } | |
| 286 | |
| 287 // Send the message. | |
| 288 // TODO(toyoshim): Check if ppapi::proxy::SerializedVar can reduce copy. | |
|
brettw
2012/10/03 04:54:02
Nope, doing this won't save a copy, so you can jus
Takashi Toyoshima
2012/10/03 11:42:20
Thanks!
| |
| 289 if (message.type == PP_VARTYPE_STRING) { | |
| 290 // Convert message to std::string, then send it. | |
| 291 scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); | |
| 292 if (!message_string) | |
| 293 return PP_ERROR_BADARGUMENT; | |
| 294 CallRenderer(PpapiHostMsg_WebSocket_SendText(message_string->value())); | |
| 295 } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { | |
| 296 // Convert message to std::vector<uint8_t>, then send it. | |
| 297 scoped_refptr<ArrayBufferVar> message_arraybuffer = | |
| 298 ArrayBufferVar::FromPPVar(message); | |
| 299 if (!message_arraybuffer) | |
| 300 return PP_ERROR_BADARGUMENT; | |
| 301 uint8_t* message_data = static_cast<uint8_t*>(message_arraybuffer->Map()); | |
| 302 uint32 message_length = message_arraybuffer->ByteLength(); | |
| 303 std::vector<uint8_t> message_vector(message_data, | |
| 304 message_data + message_length); | |
| 305 CallRenderer(PpapiHostMsg_WebSocket_SendBinary(message_vector)); | |
| 306 } else { | |
| 307 // TODO(toyoshim): Support Blob. | |
| 308 return PP_ERROR_NOTSUPPORTED; | |
| 309 } | |
| 310 return PP_OK; | |
| 311 } | |
| 312 | |
| 313 uint64_t WebSocketResource::GetBufferedAmount() { | |
| 314 return SaturateAdd(buffered_amount_, buffered_amount_after_close_); | |
| 315 } | |
| 316 | |
| 317 uint16_t WebSocketResource::GetCloseCode() { | |
| 318 return close_code_; | |
| 319 } | |
| 320 | |
| 321 PP_Var WebSocketResource::GetCloseReason() { | |
| 322 if (!close_reason_) | |
| 323 return empty_string_->GetPPVar(); | |
| 324 return close_reason_->GetPPVar(); | |
| 325 } | |
| 326 | |
| 327 PP_Bool WebSocketResource::GetCloseWasClean() { | |
| 328 return close_was_clean_; | |
| 329 } | |
| 330 | |
| 331 PP_Var WebSocketResource::GetExtensions() { | |
| 332 return StringVar::StringToPPVar(""); | |
|
brettw
2012/10/03 04:54:02
Can you use std::string() instead of ""? It's more
Takashi Toyoshima
2012/10/03 11:42:20
Done.
| |
| 333 } | |
| 334 | |
| 335 PP_Var WebSocketResource::GetProtocol() { | |
| 336 if (!protocol_) | |
| 337 return empty_string_->GetPPVar(); | |
| 338 return protocol_->GetPPVar(); | |
| 339 } | |
| 340 | |
| 341 PP_WebSocketReadyState WebSocketResource::GetReadyState() { | |
| 342 return state_; | |
| 343 } | |
| 344 | |
| 345 PP_Var WebSocketResource::GetURL() { | |
| 346 if (!url_) | |
| 347 return empty_string_->GetPPVar(); | |
| 348 return url_->GetPPVar(); | |
| 349 } | |
| 350 | |
| 351 void WebSocketResource::OnReplyReceived( | |
| 352 const ResourceMessageReplyParams& params, | |
| 353 const IPC::Message& msg) { | |
| 354 // TODO(toyoshim): DISPATCH_RESOURCE_REPLY will be replaced with other | |
| 355 // mechanisms. WebSocket dispatches IPC messages manually for now and must be | |
| 356 // replaced with the new one in the future. | |
| 357 int32_t sequence = params.sequence(); | |
| 358 if (!sequence) { | |
| 359 // Handle unsolicited IPCs. | |
| 360 switch (msg.type()) { | |
| 361 case PpapiPluginMsg_WebSocket_ReceiveTextReply::ID: { | |
| 362 PpapiPluginMsg_WebSocket_ReceiveTextReply::Schema::Param p; | |
| 363 if (PpapiPluginMsg_WebSocket_ReceiveTextReply::Read(&msg, &p)) | |
| 364 OnPluginMsgReceiveTextReply(params, p.a); | |
| 365 else | |
| 366 NOTREACHED(); | |
| 367 break; } | |
|
brettw
2012/10/03 04:54:02
I've usually seen the closing } on the next line.
Takashi Toyoshima
2012/10/03 11:42:20
Done.
| |
| 368 case PpapiPluginMsg_WebSocket_ReceiveBinaryReply::ID: { | |
| 369 PpapiPluginMsg_WebSocket_ReceiveBinaryReply::Schema::Param p; | |
| 370 if (PpapiPluginMsg_WebSocket_ReceiveBinaryReply::Read(&msg, &p)) | |
| 371 OnPluginMsgReceiveBinaryReply(params, p.a); | |
| 372 else | |
| 373 NOTREACHED(); | |
| 374 break; } | |
| 375 case PpapiPluginMsg_WebSocket_ErrorReply::ID: { | |
| 376 OnPluginMsgErrorReply(params); | |
| 377 break; } | |
| 378 case PpapiPluginMsg_WebSocket_BufferedAmountReply::ID: { | |
| 379 PpapiPluginMsg_WebSocket_BufferedAmountReply::Schema::Param p; | |
| 380 if (PpapiPluginMsg_WebSocket_BufferedAmountReply::Read(&msg, &p)) | |
| 381 OnPluginMsgBufferedAmountReply(params, p.a); | |
| 382 else | |
| 383 NOTREACHED(); | |
| 384 break; } | |
| 385 case PpapiPluginMsg_WebSocket_StateReply::ID: { | |
| 386 PpapiPluginMsg_WebSocket_StateReply::Schema::Param p; | |
| 387 if (PpapiPluginMsg_WebSocket_StateReply::Read(&msg, &p)) | |
| 388 OnPluginMsgStateReply(params, p.a); | |
| 389 else | |
| 390 NOTREACHED(); | |
| 391 break; } | |
| 392 case PpapiPluginMsg_WebSocket_ClosedReply::ID: { | |
| 393 PpapiPluginMsg_WebSocket_ClosedReply::Schema::Param p; | |
| 394 if (PpapiPluginMsg_WebSocket_ClosedReply::Read(&msg, &p)) | |
| 395 OnPluginMsgClosedReply(params, p.a, p.b, p.c, p.d); | |
| 396 else | |
| 397 NOTREACHED(); | |
| 398 break; } | |
| 399 default: | |
| 400 NOTREACHED(); | |
| 401 } | |
| 402 } else if (sequence == connect_request_id_) { | |
| 403 PpapiPluginMsg_WebSocket_ConnectReply::Schema::Param p; | |
| 404 if (PpapiPluginMsg_WebSocket_ConnectReply::Read(&msg, &p)) | |
| 405 OnPluginMsgConnectReply(params, p.a, p.b); | |
| 406 else // On error use default params and run the callback. | |
| 407 OnPluginMsgConnectReply(params, std::string(), std::string()); | |
| 408 } else if (sequence == close_request_id_) { | |
| 409 PpapiPluginMsg_WebSocket_CloseReply::Schema::Param p; | |
| 410 if (PpapiPluginMsg_WebSocket_CloseReply::Read(&msg, &p)) | |
| 411 OnPluginMsgCloseReply(params, p.a, p.b, p.c, p.d); | |
| 412 else // On error use default params and run the callback. | |
| 413 OnPluginMsgCloseReply(params, 0, false, 0, std::string()); | |
| 414 } else { | |
| 415 NOTREACHED(); | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 void WebSocketResource::OnPluginMsgConnectReply( | |
| 420 const ResourceMessageReplyParams& params, | |
| 421 const std::string& url, | |
| 422 const std::string& protocol) { | |
| 423 if (!TrackedCallback::IsPending(connect_callback_)) | |
| 424 return; | |
| 425 | |
| 426 int32_t result = params.result(); | |
| 427 if (result == PP_OK) { | |
| 428 state_ = PP_WEBSOCKETREADYSTATE_OPEN; | |
| 429 protocol_ = new StringVar(protocol); | |
| 430 } else { | |
| 431 url_ = new StringVar(url); | |
| 432 } | |
| 433 if (result != PP_OK_COMPLETIONPENDING) | |
| 434 TrackedCallback::ClearAndRun(&connect_callback_, params.result()); | |
| 435 } | |
| 436 | |
| 437 void WebSocketResource::OnPluginMsgCloseReply( | |
| 438 const ResourceMessageReplyParams& params, | |
| 439 unsigned long buffered_amount, | |
| 440 bool was_clean, | |
| 441 unsigned short code, | |
| 442 const std::string& reason) { | |
| 443 // Set close related properties. | |
| 444 state_ = PP_WEBSOCKETREADYSTATE_CLOSED; | |
| 445 buffered_amount_ = buffered_amount; | |
| 446 close_was_clean_ = PP_FromBool(was_clean); | |
| 447 close_code_ = code; | |
| 448 close_reason_ = new StringVar(reason); | |
| 449 | |
| 450 bool post = false; | |
| 451 if (TrackedCallback::IsPending(connect_callback_)) { | |
| 452 connect_callback_->PostRun(PP_ERROR_FAILED); | |
| 453 post = true; | |
| 454 } | |
| 455 | |
| 456 if (TrackedCallback::IsPending(receive_callback_)) { | |
| 457 receive_callback_var_ = NULL; | |
| 458 receive_callback_->PostRun(PP_ERROR_FAILED); | |
| 459 post = true; | |
| 460 } | |
| 461 | |
| 462 if (!TrackedCallback::IsPending(close_callback_)) | |
| 463 return; | |
| 464 | |
| 465 if (post) | |
| 466 close_callback_->PostRun(params.result()); | |
| 467 else | |
| 468 TrackedCallback::ClearAndRun(&close_callback_, params.result()); | |
| 469 } | |
| 470 | |
| 471 void WebSocketResource::OnPluginMsgReceiveTextReply( | |
| 472 const ResourceMessageReplyParams& params, | |
| 473 const std::string& message) { | |
| 474 // Dispose packets after receiving an error or in invalid state. | |
| 475 if (error_was_received_ || !InValidStateToReceive(state_)) | |
| 476 return; | |
| 477 | |
| 478 // Append received data to queue. | |
| 479 received_messages_.push(scoped_refptr<Var>(new StringVar(message))); | |
| 480 | |
| 481 if (!TrackedCallback::IsPending(receive_callback_)) | |
| 482 return; | |
| 483 | |
| 484 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); | |
| 485 } | |
| 486 | |
| 487 void WebSocketResource::OnPluginMsgReceiveBinaryReply( | |
| 488 const ResourceMessageReplyParams& params, | |
| 489 const std::vector<uint8_t>& message) { | |
| 490 // Dispose packets after receiving an error or in invalid state. | |
| 491 if (error_was_received_ || !InValidStateToReceive(state_)) | |
| 492 return; | |
| 493 | |
| 494 // Append received data to queue. | |
| 495 scoped_refptr<Var> message_var(ArrayBufferVar::FromPPVar( | |
| 496 PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( | |
| 497 message.size(), | |
| 498 &message.front()))); | |
| 499 received_messages_.push(message_var); | |
| 500 | |
| 501 if (!TrackedCallback::IsPending(receive_callback_)) | |
| 502 return; | |
| 503 | |
| 504 TrackedCallback::ClearAndRun(&receive_callback_, DoReceive()); | |
| 505 | |
|
brettw
2012/10/03 04:54:02
Nit: blank line
Takashi Toyoshima
2012/10/03 11:42:20
Done.
| |
| 506 } | |
| 507 | |
| 508 void WebSocketResource::OnPluginMsgErrorReply( | |
| 509 const ResourceMessageReplyParams& params) { | |
| 510 } | |
| 511 | |
| 512 void WebSocketResource::OnPluginMsgBufferedAmountReply( | |
| 513 const ResourceMessageReplyParams& params, | |
| 514 unsigned long buffered_amount) { | |
| 515 buffered_amount_ = buffered_amount; | |
| 516 } | |
| 517 | |
| 518 void WebSocketResource::OnPluginMsgStateReply( | |
| 519 const ResourceMessageReplyParams& params, | |
| 520 int32_t state) { | |
| 521 state_ = static_cast<PP_WebSocketReadyState>(state); | |
| 522 } | |
| 523 | |
| 524 void WebSocketResource::OnPluginMsgClosedReply( | |
| 525 const ResourceMessageReplyParams& params, | |
| 526 unsigned long buffered_amount, | |
| 527 bool was_clean, | |
| 528 unsigned short code, | |
| 529 const std::string& reason) { | |
| 530 OnPluginMsgCloseReply(params, buffered_amount, was_clean, code, reason); | |
| 531 } | |
| 532 | |
| 533 int32_t WebSocketResource::DoReceive() { | |
| 534 if (!receive_callback_var_) | |
| 535 return PP_OK; | |
| 536 | |
| 537 *receive_callback_var_ = received_messages_.front()->GetPPVar(); | |
| 538 received_messages_.pop(); | |
| 539 receive_callback_var_ = NULL; | |
| 540 return PP_OK; | |
| 541 } | |
| 542 | |
| 543 } // namespace proxy | |
| 544 } // namespace ppapi | |
| OLD | NEW |