15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/websocket_resource.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/dispatch_reply_message.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var_tracker.h" 187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebSocket.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32_t kMaxReasonSizeInBytes = 123; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kBaseFramingOverhead = 2; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaskingKeyLength = 4; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMinimumPayloadSizeWithTwoByteExtendedPayloadLength = 126; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMinimumPayloadSizeWithEightByteExtendedPayloadLength = 0x10000; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint64_t SaturateAdd(uint64_t a, uint64_t b) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kuint64max - a < b) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kuint64max; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a + b; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint64_t GetFrameSize(uint64_t payload_size) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t overhead = kBaseFramingOverhead + kMaskingKeyLength; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (payload_size > kMinimumPayloadSizeWithEightByteExtendedPayloadLength) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overhead += 8; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (payload_size > kMinimumPayloadSizeWithTwoByteExtendedPayloadLength) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overhead += 2; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SaturateAdd(payload_size, overhead); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InValidStateToReceive(PP_WebSocketReadyState state) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state == PP_WEBSOCKETREADYSTATE_OPEN || 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state == PP_WEBSOCKETREADYSTATE_CLOSING; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebSocketResource::WebSocketResource(Connection connection, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Instance instance) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : PluginResource(connection, instance), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_(PP_WEBSOCKETREADYSTATE_INVALID), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_was_received_(false), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_(NULL), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) empty_string_(new StringVar(std::string())), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_code_(0), 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_reason_(NULL), 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_was_clean_(PP_FALSE), 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions_(NULL), 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_(NULL), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_(NULL), 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_amount_(0), 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_amount_after_close_(0) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebSocketResource::~WebSocketResource() { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)thunk::PPB_WebSocket_API* WebSocketResource::AsPPB_WebSocket_API() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebSocketResource::Connect( 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PP_Var& url, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PP_Var protocols[], 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t protocol_count, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(connect_callback_)) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_INPROGRESS; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connect() can be called at most once. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ != PP_WEBSOCKETREADYSTATE_INVALID) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_INPROGRESS; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PP_WEBSOCKETREADYSTATE_CLOSED; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the URL. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = StringVar::FromPPVar(url); 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!url_.get()) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the protocols. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> protocol_set; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> protocol_strings; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_strings.reserve(protocol_count); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32_t i = 0; i < protocol_count; ++i) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<StringVar> protocol(StringVar::FromPPVar(protocols[i])); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check invalid and empty entries. 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!protocol.get() || !protocol->value().length()) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check duplicated protocol entries. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (protocol_set.find(protocol->value()) != protocol_set.end()) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_set.insert(protocol->value()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_strings.push_back(protocol->value()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install callback. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_ = callback; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create remote host in the renderer, then request to check the URL and 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // establish the connection. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PP_WEBSOCKETREADYSTATE_CONNECTING; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendCreate(RENDERER, PpapiHostMsg_WebSocket_Create()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiHostMsg_WebSocket_Connect msg(url_->value(), protocol_strings); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Call<PpapiPluginMsg_WebSocket_ConnectReply>(RENDERER, msg, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&WebSocketResource::OnPluginMsgConnectReply, this)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebSocketResource::Close(uint16_t code, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PP_Var& reason, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(close_callback_)) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_INPROGRESS; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_INVALID) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_FAILED; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate |code| and |reason|. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<StringVar> reason_string_var; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string reason_string; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebKit::WebSocket::CloseEventCode event_code = 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<WebKit::WebSocket::CloseEventCode>(code); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // assigned to different values. A conversion is needed if 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_code = WebKit::WebSocket::CloseEventCodeNotSpecified; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(code == PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE || 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (PP_WEBSOCKETSTATUSCODE_USER_REGISTERED_MIN <= code && 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) code <= PP_WEBSOCKETSTATUSCODE_USER_PRIVATE_MAX))) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RFC 6455 limits applications to use reserved connection close code in 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // section 7.4.2.. The WebSocket API (http://www.w3.org/TR/websockets/) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // defines this out of range error as InvalidAccessError in JavaScript. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_NOACCESS; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |reason| must be ignored if it is PP_VARTYPE_UNDEFINED or |code| is 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reason.type != PP_VARTYPE_UNDEFINED) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate |reason|. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason_string_var = StringVar::FromPPVar(reason); 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!reason_string_var.get() || 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason_string_var->value().size() > kMaxReasonSizeInBytes) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason_string = reason_string_var->value(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check state. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_INPROGRESS; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install |callback|. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_callback_ = callback; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Abort ongoing connect. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(connect_callback_)) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PP_WEBSOCKETREADYSTATE_CLOSING; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to do a "Post" to avoid reentering the plugin. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_->PostAbort(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_ = NULL; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Post(RENDERER, PpapiHostMsg_WebSocket_Fail( 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WebSocket was closed before the connection was established.")); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Abort ongoing receive. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(receive_callback_)) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_ = NULL; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to do a "Post" to avoid reentering the plugin. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_->PostAbort(); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_ = NULL; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close connection. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PP_WEBSOCKETREADYSTATE_CLOSING; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiHostMsg_WebSocket_Close msg(static_cast<int32_t>(event_code), 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason_string); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Call<PpapiPluginMsg_WebSocket_CloseReply>(RENDERER, msg, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&WebSocketResource::OnPluginMsgCloseReply, this)); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebSocketResource::ReceiveMessage( 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Var* message, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<TrackedCallback> callback) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(receive_callback_)) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_INPROGRESS; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check state. 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_INVALID || 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ == PP_WEBSOCKETREADYSTATE_CONNECTING) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just return received message if any received message is queued. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!received_messages_.empty()) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_ = message; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoReceive(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check state again. In CLOSED state, no more messages will be received. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_CLOSED) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns PP_ERROR_FAILED after an error is received and received messages 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is exhausted. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_was_received_) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_FAILED; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Or retain |message| as buffer to store and install |callback|. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_ = message; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_ = callback; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK_COMPLETIONPENDING; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebSocketResource::SendMessage(const PP_Var& message) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check state. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_INVALID || 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ == PP_WEBSOCKETREADYSTATE_CONNECTING) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == PP_WEBSOCKETREADYSTATE_CLOSING || 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ == PP_WEBSOCKETREADYSTATE_CLOSED) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle buffered_amount_after_close_. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64_t payload_size = 0; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message.type == PP_VARTYPE_STRING) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (message_string.get()) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload_size += message_string->value().length(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ArrayBufferVar> message_array_buffer = 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArrayBufferVar::FromPPVar(message); 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (message_array_buffer.get()) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload_size += message_array_buffer->ByteLength(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(toyoshim): Support Blob. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_NOTSUPPORTED; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_amount_after_close_ = 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaturateAdd(buffered_amount_after_close_, GetFrameSize(payload_size)); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_FAILED; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the message. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message.type == PP_VARTYPE_STRING) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert message to std::string, then send it. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<StringVar> message_string = StringVar::FromPPVar(message); 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!message_string.get()) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Post(RENDERER, PpapiHostMsg_WebSocket_SendText(message_string->value())); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (message.type == PP_VARTYPE_ARRAY_BUFFER) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert message to std::vector<uint8_t>, then send it. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ArrayBufferVar> message_arraybuffer = 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArrayBufferVar::FromPPVar(message); 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!message_arraybuffer.get()) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_BADARGUMENT; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* message_data = static_cast<uint8_t*>(message_arraybuffer->Map()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 message_length = message_arraybuffer->ByteLength(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8_t> message_vector(message_data, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_data + message_length); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Post(RENDERER, PpapiHostMsg_WebSocket_SendBinary(message_vector)); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(toyoshim): Support Blob. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_ERROR_NOTSUPPORTED; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint64_t WebSocketResource::GetBufferedAmount() { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SaturateAdd(buffered_amount_, buffered_amount_after_close_); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint16_t WebSocketResource::GetCloseCode() { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return close_code_; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var WebSocketResource::GetCloseReason() { 302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!close_reason_.get()) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return empty_string_->GetPPVar(); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return close_reason_->GetPPVar(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool WebSocketResource::GetCloseWasClean() { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return close_was_clean_; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var WebSocketResource::GetExtensions() { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StringVar::StringToPPVar(std::string()); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var WebSocketResource::GetProtocol() { 316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!protocol_.get()) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return empty_string_->GetPPVar(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return protocol_->GetPPVar(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_WebSocketReadyState WebSocketResource::GetReadyState() { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state_; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var WebSocketResource::GetURL() { 326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!url_.get()) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return empty_string_->GetPPVar(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url_->GetPPVar(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnReplyReceived( 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPC::Message& msg) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params.sequence()) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PluginResource::OnReplyReceived(params, msg); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(WebSocketResource, msg) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ReceiveTextReply, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgReceiveTextReply) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ReceiveBinaryReply, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgReceiveBinaryReply) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_0( 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ErrorReply, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgErrorReply) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_BufferedAmountReply, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgBufferedAmountReply) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_StateReply, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgStateReply) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ClosedReply, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgClosedReply) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED()) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgConnectReply( 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& protocol) { 366558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!TrackedCallback::IsPending(connect_callback_) || 367558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch TrackedCallback::IsScheduledToRun(connect_callback_)) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 369558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32_t result = params.result(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == PP_OK) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PP_WEBSOCKETREADYSTATE_OPEN; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol_ = new StringVar(protocol); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = new StringVar(url); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_callback_->Run(params.result()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgCloseReply( 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long buffered_amount, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_clean, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned short code, 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& reason) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set close related properties. 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = PP_WEBSOCKETREADYSTATE_CLOSED; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_amount_ = buffered_amount; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_was_clean_ = PP_FromBool(was_clean); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_code_ = code; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_reason_ = new StringVar(reason); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(receive_callback_)) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_ = NULL; 395558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!TrackedCallback::IsScheduledToRun(receive_callback_)) 396558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch receive_callback_->PostRun(PP_ERROR_FAILED); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_ = NULL; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TrackedCallback::IsPending(close_callback_)) { 401558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!TrackedCallback::IsScheduledToRun(close_callback_)) 402558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch close_callback_->PostRun(params.result()); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_callback_ = NULL; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgReceiveTextReply( 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& message) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dispose packets after receiving an error or in invalid state. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_was_received_ || !InValidStateToReceive(state_)) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append received data to queue. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_messages_.push(scoped_refptr<Var>(new StringVar(message))); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 417558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!TrackedCallback::IsPending(receive_callback_) || 418558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch TrackedCallback::IsScheduledToRun(receive_callback_)) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 420558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_->Run(DoReceive()); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgReceiveBinaryReply( 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8_t>& message) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dispose packets after receiving an error or in invalid state. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_was_received_ || !InValidStateToReceive(state_)) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append received data to queue. 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<Var> message_var( 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferVar( 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message.size(), 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &message.front())); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_messages_.push(message_var); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 439558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!TrackedCallback::IsPending(receive_callback_) || 440558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch TrackedCallback::IsScheduledToRun(receive_callback_)) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 442558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_->Run(DoReceive()); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgErrorReply( 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_was_received_ = true; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 451558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!TrackedCallback::IsPending(receive_callback_) || 452558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch TrackedCallback::IsScheduledToRun(receive_callback_)) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 454558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No more text or binary messages will be received. If there is ongoing 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ReceiveMessage(), we must invoke the callback with error code here. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_ = NULL; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_->Run(PP_ERROR_FAILED); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgBufferedAmountReply( 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long buffered_amount) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_amount_ = buffered_amount; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgStateReply( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32_t state) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = static_cast<PP_WebSocketReadyState>(state); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebSocketResource::OnPluginMsgClosedReply( 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResourceMessageReplyParams& params, 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long buffered_amount, 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_clean, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned short code, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& reason) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnPluginMsgCloseReply(params, buffered_amount, was_clean, code, reason); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebSocketResource::DoReceive() { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!receive_callback_var_) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *receive_callback_var_ = received_messages_.front()->GetPPVar(); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_messages_.pop(); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) receive_callback_var_ = NULL; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_OK; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace proxy 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ppapi 495