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 "base/memory/ref_counted.h" 6 #include "base/message_loop/message_loop.h" 7 #include "ppapi/c/pp_errors.h" 8 #include "ppapi/c/ppb_var.h" 9 #include "ppapi/c/ppb_websocket.h" 10 #include "ppapi/proxy/locking_resource_releaser.h" 11 #include "ppapi/proxy/ppapi_messages.h" 12 #include "ppapi/proxy/ppapi_proxy_test.h" 13 #include "ppapi/proxy/websocket_resource.h" 14 #include "ppapi/shared_impl/ppapi_globals.h" 15 #include "ppapi/shared_impl/ppb_var_shared.h" 16 #include "ppapi/shared_impl/proxy_lock.h" 17 #include "ppapi/shared_impl/resource_tracker.h" 18 #include "ppapi/shared_impl/scoped_pp_resource.h" 19 #include "ppapi/shared_impl/scoped_pp_var.h" 20 #include "ppapi/shared_impl/tracked_callback.h" 21 #include "ppapi/shared_impl/var.h" 22 #include "ppapi/thunk/thunk.h" 23 24 namespace ppapi { 25 namespace proxy { 26 27 namespace { 28 29 typedef PluginProxyTest WebSocketResourceTest; 30 31 bool g_callback_called; 32 int32_t g_callback_result; 33 const PPB_Var* ppb_var_ = NULL; 34 35 void Callback(void* user_data, int32_t result) { 36 g_callback_called = true; 37 g_callback_result = result; 38 } 39 40 PP_CompletionCallback MakeCallback() { 41 g_callback_called = false; 42 g_callback_result = PP_OK; 43 return PP_MakeCompletionCallback(Callback, NULL); 44 } 45 46 PP_Var MakeStringVar(const std::string& string) { 47 if (!ppb_var_) 48 ppb_var_ = ppapi::PPB_Var_Shared::GetVarInterface1_1(); 49 return ppb_var_->VarFromUtf8(string.c_str(), string.length()); 50 } 51 52 } // namespace 53 54 55 // Does a test of Connect(). 56 TEST_F(WebSocketResourceTest, Connect) { 57 const PPB_WebSocket_1_0* websocket_iface = 58 thunk::GetPPB_WebSocket_1_0_Thunk(); 59 60 std::string url("ws://ws.google.com"); 61 std::string protocol0("x-foo"); 62 std::string protocol1("x-bar"); 63 PP_Var url_var = MakeStringVar(url); 64 PP_Var protocols[] = { MakeStringVar(protocol0), MakeStringVar(protocol1) }; 65 66 LockingResourceReleaser res(websocket_iface->Create(pp_instance())); 67 68 int32_t result = websocket_iface->Connect(res.get(), url_var, protocols, 2, 69 MakeCallback()); 70 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); 71 72 // Should be sent a "Connect" message. 73 ResourceMessageCallParams params; 74 IPC::Message msg; 75 ASSERT_TRUE(sink().GetFirstResourceCallMatching( 76 PpapiHostMsg_WebSocket_Connect::ID, ¶ms, &msg)); 77 PpapiHostMsg_WebSocket_Connect::Schema::Param p; 78 PpapiHostMsg_WebSocket_Connect::Read(&msg, &p); 79 EXPECT_EQ(url, p.a); 80 EXPECT_EQ(protocol0, p.b[0]); 81 EXPECT_EQ(protocol1, p.b[1]); 82 83 // Synthesize a response. 84 ResourceMessageReplyParams reply_params(params.pp_resource(), 85 params.sequence()); 86 reply_params.set_result(PP_OK); 87 ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 88 PpapiPluginMsg_ResourceReply(reply_params, 89 PpapiPluginMsg_WebSocket_ConnectReply(url, protocol1)))); 90 91 EXPECT_EQ(PP_OK, g_callback_result); 92 EXPECT_EQ(true, g_callback_called); 93 } 94 95 // Does a test for unsolicited replies. 96 TEST_F(WebSocketResourceTest, UnsolicitedReplies) { 97 const PPB_WebSocket_1_0* websocket_iface = 98 thunk::GetPPB_WebSocket_1_0_Thunk(); 99 100 LockingResourceReleaser res(websocket_iface->Create(pp_instance())); 101 102 // Check if BufferedAmountReply is handled. 103 ResourceMessageReplyParams reply_params(res.get(), 0); 104 reply_params.set_result(PP_OK); 105 ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 106 PpapiPluginMsg_ResourceReply( 107 reply_params, 108 PpapiPluginMsg_WebSocket_BufferedAmountReply(19760227u)))); 109 110 uint64_t amount = websocket_iface->GetBufferedAmount(res.get()); 111 EXPECT_EQ(19760227u, amount); 112 113 // Check if StateReply is handled. 114 ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 115 PpapiPluginMsg_ResourceReply( 116 reply_params, 117 PpapiPluginMsg_WebSocket_StateReply( 118 static_cast<int32_t>(PP_WEBSOCKETREADYSTATE_CLOSING))))); 119 120 PP_WebSocketReadyState state = websocket_iface->GetReadyState(res.get()); 121 EXPECT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING, state); 122 } 123 124 TEST_F(WebSocketResourceTest, MessageError) { 125 const PPB_WebSocket_1_0* websocket_iface = 126 thunk::GetPPB_WebSocket_1_0_Thunk(); 127 128 std::string url("ws://ws.google.com"); 129 PP_Var url_var = MakeStringVar(url); 130 131 LockingResourceReleaser res(websocket_iface->Create(pp_instance())); 132 133 // Establish the connection virtually. 134 int32_t result = 135 websocket_iface->Connect(res.get(), url_var, NULL, 0, MakeCallback()); 136 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); 137 138 ResourceMessageCallParams params; 139 IPC::Message msg; 140 ASSERT_TRUE(sink().GetFirstResourceCallMatching( 141 PpapiHostMsg_WebSocket_Connect::ID, ¶ms, &msg)); 142 143 ResourceMessageReplyParams connect_reply_params(params.pp_resource(), 144 params.sequence()); 145 connect_reply_params.set_result(PP_OK); 146 ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 147 PpapiPluginMsg_ResourceReply(connect_reply_params, 148 PpapiPluginMsg_WebSocket_ConnectReply(url, std::string())))); 149 150 EXPECT_EQ(PP_OK, g_callback_result); 151 EXPECT_TRUE(g_callback_called); 152 153 PP_Var message; 154 result = websocket_iface->ReceiveMessage(res.get(), &message, MakeCallback()); 155 EXPECT_FALSE(g_callback_called); 156 157 // Synthesize a WebSocket_ErrorReply message. 158 ResourceMessageReplyParams error_reply_params(res.get(), 0); 159 error_reply_params.set_result(PP_OK); 160 ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived( 161 PpapiPluginMsg_ResourceReply(error_reply_params, 162 PpapiPluginMsg_WebSocket_ErrorReply()))); 163 164 EXPECT_EQ(PP_ERROR_FAILED, g_callback_result); 165 EXPECT_TRUE(g_callback_called); 166 } 167 168 } // namespace proxy 169 } // namespace ppapi 170