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 "base/memory/ref_counted.h" 69ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_var.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "ppapi/c/ppb_websocket.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/proxy/locking_resource_releaser.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_proxy_test.h" 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "ppapi/proxy/websocket_resource.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppb_var_shared.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/scoped_pp_resource.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/scoped_pp_var.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/tracked_callback.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/var.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/thunk.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef PluginProxyTest WebSocketResourceTest; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_callback_called; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t g_callback_result; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PPB_Var* ppb_var_ = NULL; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Callback(void* user_data, int32_t result) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_callback_called = true; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_callback_result = result; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_CompletionCallback MakeCallback() { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_callback_called = false; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_callback_result = PP_OK; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PP_MakeCompletionCallback(Callback, NULL); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var MakeStringVar(const std::string& string) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ppb_var_) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ppb_var_ = ppapi::PPB_Var_Shared::GetVarInterface1_1(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ppb_var_->VarFromUtf8(string.c_str(), string.length()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does a test of Connect(). 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WebSocketResourceTest, Connect) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PPB_WebSocket_1_0* websocket_iface = 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thunk::GetPPB_WebSocket_1_0_Thunk(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url("ws://ws.google.com"); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string protocol0("x-foo"); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string protocol1("x-bar"); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Var url_var = MakeStringVar(url); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Var protocols[] = { MakeStringVar(protocol0), MakeStringVar(protocol1) }; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LockingResourceReleaser res(websocket_iface->Create(pp_instance())); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32_t result = websocket_iface->Connect(res.get(), url_var, protocols, 2, 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MakeCallback()); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be sent a "Connect" message. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMessageCallParams params; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Message msg; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(sink().GetFirstResourceCallMatching( 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiHostMsg_WebSocket_Connect::ID, ¶ms, &msg)); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiHostMsg_WebSocket_Connect::Schema::Param p; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiHostMsg_WebSocket_Connect::Read(&msg, &p); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(url, p.a); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(protocol0, p.b[0]); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(protocol1, p.b[1]); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synthesize a response. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMessageReplyParams reply_params(params.pp_resource(), 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.sequence()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_params.set_result(PP_OK); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_ResourceReply(reply_params, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ConnectReply(url, protocol1)))); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(PP_OK, g_callback_result); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(true, g_callback_called); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does a test for unsolicited replies. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WebSocketResourceTest, UnsolicitedReplies) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PPB_WebSocket_1_0* websocket_iface = 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thunk::GetPPB_WebSocket_1_0_Thunk(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LockingResourceReleaser res(websocket_iface->Create(pp_instance())); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if BufferedAmountReply is handled. 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ResourceMessageReplyParams reply_params(res.get(), 0); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_params.set_result(PP_OK); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_ResourceReply( 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_params, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_BufferedAmountReply(19760227u)))); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint64_t amount = websocket_iface->GetBufferedAmount(res.get()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(19760227u, amount); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if StateReply is handled. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_ResourceReply( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply_params, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_StateReply( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int32_t>(PP_WEBSOCKETREADYSTATE_CLOSING))))); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_WebSocketReadyState state = websocket_iface->GetReadyState(res.get()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, state); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WebSocketResourceTest, MessageError) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PPB_WebSocket_1_0* websocket_iface = 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thunk::GetPPB_WebSocket_1_0_Thunk(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url("ws://ws.google.com"); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Var url_var = MakeStringVar(url); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LockingResourceReleaser res(websocket_iface->Create(pp_instance())); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Establish the connection virtually. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32_t result = 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) websocket_iface->Connect(res.get(), url_var, NULL, 0, MakeCallback()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMessageCallParams params; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Message msg; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(sink().GetFirstResourceCallMatching( 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiHostMsg_WebSocket_Connect::ID, ¶ms, &msg)); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceMessageReplyParams connect_reply_params(params.pp_resource(), 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.sequence()); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_reply_params.set_result(PP_OK); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_ResourceReply(connect_reply_params, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ConnectReply(url, std::string())))); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(PP_OK, g_callback_result); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(g_callback_called); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Var message; 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result = websocket_iface->ReceiveMessage(res.get(), &message, MakeCallback()); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(g_callback_called); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synthesize a WebSocket_ErrorReply message. 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ResourceMessageReplyParams error_reply_params(res.get(), 0); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_reply_params.set_result(PP_OK); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_ResourceReply(error_reply_params, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PpapiPluginMsg_WebSocket_ErrorReply()))); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(PP_ERROR_FAILED, g_callback_result); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(g_callback_called); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace proxy 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ppapi 170