OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/synchronization/waitable_event.h" |
| 6 #include "ipc/ipc_message_utils.h" |
| 7 #include "ppapi/c/dev/ppb_fullscreen_dev.h" |
| 8 #include "ppapi/c/ppb_core.h" |
| 9 #include "ppapi/c/ppb_url_loader.h" |
| 10 #include "ppapi/c/ppp_instance.h" |
| 11 #include "ppapi/proxy/ppapi_messages.h" |
| 12 #include "ppapi/proxy/ppapi_proxy_test.h" |
| 13 |
| 14 namespace pp { |
| 15 namespace proxy { |
| 16 |
| 17 namespace { |
| 18 // This is a poor man's mock of PPP_Instance using global variables. Eventually |
| 19 // we should generalize making PPAPI interface mocks by using IDL or macro/ |
| 20 // template magic. |
| 21 PP_Instance received_instance; |
| 22 uint32_t received_argc; |
| 23 std::vector<std::string> received_argn; |
| 24 std::vector<std::string> received_argv; |
| 25 PP_Bool bool_to_return; |
| 26 PP_Bool DidCreate(PP_Instance instance, uint32_t argc, const char* argn[], |
| 27 const char* argv[]) { |
| 28 received_instance = instance; |
| 29 received_argc = argc; |
| 30 received_argn.clear(); |
| 31 received_argn.insert(received_argn.begin(), argn, argn + argc); |
| 32 received_argv.clear(); |
| 33 received_argv.insert(received_argv.begin(), argv, argv + argc); |
| 34 return bool_to_return; |
| 35 } |
| 36 |
| 37 void DidDestroy(PP_Instance instance) { |
| 38 received_instance = instance; |
| 39 } |
| 40 |
| 41 PP_Rect received_position; |
| 42 PP_Rect received_clip; |
| 43 // DidChangeView is asynchronous. We wait until the call has completed before |
| 44 // proceeding on to the next test. |
| 45 base::WaitableEvent did_change_view_called(false, false); |
| 46 void DidChangeView(PP_Instance instance, const PP_Rect* position, |
| 47 const PP_Rect* clip) { |
| 48 received_instance = instance; |
| 49 received_position = *position; |
| 50 received_clip = *clip; |
| 51 did_change_view_called.Signal(); |
| 52 } |
| 53 |
| 54 PP_Bool received_has_focus; |
| 55 base::WaitableEvent did_change_focus_called(false, false); |
| 56 void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { |
| 57 received_instance = instance; |
| 58 received_has_focus = has_focus; |
| 59 did_change_focus_called.Signal(); |
| 60 } |
| 61 |
| 62 PP_InputEvent received_event; |
| 63 PP_Bool HandleInputEvent(PP_Instance instance, const PP_InputEvent* event) { |
| 64 received_instance = instance; |
| 65 memcpy(&received_event, event, sizeof(*event));; |
| 66 return bool_to_return; |
| 67 } |
| 68 |
| 69 PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) { |
| 70 // This one requires use of the PPB_URLLoader proxy and PPB_Core, plus a |
| 71 // resource tracker for the url_loader resource. |
| 72 // TODO(dmichael): Mock those out and test this function. |
| 73 NOTREACHED(); |
| 74 return PP_FALSE; |
| 75 } |
| 76 |
| 77 PP_Var var_to_return; |
| 78 PP_Var GetInstanceObject(PP_Instance instance) { |
| 79 received_instance = instance; |
| 80 return var_to_return; |
| 81 } |
| 82 |
| 83 // Clear all the 'received' values for our mock. Call this before you expect |
| 84 // one of the functions to be invoked. TODO(dmichael): It would be better to |
| 85 // have a flag also for each function, so we know the right one got called. |
| 86 void ResetReceived() { |
| 87 received_instance = 0; |
| 88 received_argc = 0; |
| 89 received_argn.clear(); |
| 90 received_argv.clear(); |
| 91 memset(&received_position, 0, sizeof(received_position)); |
| 92 memset(&received_clip, 0, sizeof(received_clip)); |
| 93 received_has_focus = PP_FALSE; |
| 94 memset(&received_event, 0, sizeof(received_event)); |
| 95 } |
| 96 |
| 97 PPP_Instance_0_4 ppp_instance_0_4 = { |
| 98 &DidCreate, |
| 99 &DidDestroy, |
| 100 &DidChangeView, |
| 101 &DidChangeFocus, |
| 102 &HandleInputEvent, |
| 103 &HandleDocumentLoad, |
| 104 &GetInstanceObject |
| 105 }; |
| 106 |
| 107 PPP_Instance_0_5 ppp_instance_0_5 = { |
| 108 &DidCreate, |
| 109 &DidDestroy, |
| 110 &DidChangeView, |
| 111 &DidChangeFocus, |
| 112 &HandleInputEvent, |
| 113 &HandleDocumentLoad |
| 114 }; |
| 115 |
| 116 // PPP_Instance_Proxy::DidChangeView relies on PPB_FullscreenDev being |
| 117 // available with a valid implementation of IsFullScreen, so we mock it. |
| 118 PP_Bool IsFullscreen(PP_Instance instance) { |
| 119 return PP_FALSE; |
| 120 } |
| 121 PPB_Fullscreen_Dev ppb_fullscreen_dev = { &IsFullscreen }; |
| 122 |
| 123 } // namespace |
| 124 |
| 125 class PPP_Instance_ProxyTest : public TwoWayTest { |
| 126 public: |
| 127 PPP_Instance_ProxyTest() |
| 128 : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { |
| 129 } |
| 130 }; |
| 131 |
| 132 TEST_F(PPP_Instance_ProxyTest, PPPInstance0_4) { |
| 133 plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_0_4, &ppp_instance_0_4); |
| 134 host().RegisterTestInterface(PPB_FULLSCREEN_DEV_INTERFACE, |
| 135 &ppb_fullscreen_dev); |
| 136 |
| 137 // Try requesting the 0.5 version, like the browser does. This should come |
| 138 // back NULL, since we're not registering 0.5. But this ensures that the |
| 139 // behavior through the proxy code reflects more closely what happens for a |
| 140 // real plug-in. |
| 141 const void* interface = |
| 142 host().host_dispatcher()->GetProxiedInterface(PPP_INSTANCE_INTERFACE_0_5); |
| 143 EXPECT_EQ(NULL, interface); |
| 144 |
| 145 // Grab the host-side proxy for the 0.4 interface. |
| 146 const PPP_Instance_0_4* ppp_instance = static_cast<const PPP_Instance_0_4*>( |
| 147 host().host_dispatcher()->GetProxiedInterface( |
| 148 PPP_INSTANCE_INTERFACE_0_4)); |
| 149 |
| 150 // Call each function in turn, make sure we get the expected values and |
| 151 // returns. |
| 152 // |
| 153 // We don't test DidDestroy, because it has the side-effect of removing the |
| 154 // PP_Instance from the PluginDispatcher, which will cause a failure later |
| 155 // when the test is torn down. |
| 156 PP_Instance expected_instance = pp_instance(); |
| 157 std::vector<std::string> expected_argn, expected_argv; |
| 158 expected_argn.push_back("Hello"); |
| 159 expected_argn.push_back("world."); |
| 160 expected_argv.push_back("elloHay"); |
| 161 expected_argv.push_back("orldway."); |
| 162 std::vector<const char*> argn_to_pass, argv_to_pass; |
| 163 CHECK(expected_argn.size() == expected_argv.size()); |
| 164 for (size_t i = 0; i < expected_argn.size(); ++i) { |
| 165 argn_to_pass.push_back(expected_argn[i].c_str()); |
| 166 argv_to_pass.push_back(expected_argv[i].c_str()); |
| 167 } |
| 168 uint32_t expected_argc = expected_argn.size(); |
| 169 bool_to_return = PP_TRUE; |
| 170 ResetReceived(); |
| 171 EXPECT_EQ(bool_to_return, ppp_instance->DidCreate(expected_instance, |
| 172 expected_argc, |
| 173 &argn_to_pass[0], |
| 174 &argv_to_pass[0])); |
| 175 EXPECT_EQ(received_instance, expected_instance); |
| 176 EXPECT_EQ(received_argc, expected_argc); |
| 177 EXPECT_EQ(received_argn, expected_argn); |
| 178 EXPECT_EQ(received_argv, expected_argv); |
| 179 |
| 180 PP_Rect expected_position = { {1, 2}, {3, 4} }; |
| 181 PP_Rect expected_clip = { {5, 6}, {7, 8} }; |
| 182 ResetReceived(); |
| 183 ppp_instance->DidChangeView(expected_instance, &expected_position, |
| 184 &expected_clip); |
| 185 did_change_view_called.Wait(); |
| 186 EXPECT_EQ(received_instance, expected_instance); |
| 187 // If I define operator== for PP_Rect, it has to come before gtest's template |
| 188 // definitions in the translation unit, or else it's not found. So instead of |
| 189 // defining operator== before the #include that brings in gtest, I compare the |
| 190 // individual parts. |
| 191 EXPECT_EQ(received_position.point.x, expected_position.point.x); |
| 192 EXPECT_EQ(received_position.point.y, expected_position.point.y); |
| 193 EXPECT_EQ(received_position.size.width, expected_position.size.width); |
| 194 EXPECT_EQ(received_position.size.height, expected_position.size.height); |
| 195 EXPECT_EQ(received_clip.point.x, expected_clip.point.x); |
| 196 EXPECT_EQ(received_clip.point.y, expected_clip.point.y); |
| 197 EXPECT_EQ(received_clip.size.width, expected_clip.size.width); |
| 198 EXPECT_EQ(received_clip.size.height, expected_clip.size.height); |
| 199 |
| 200 PP_Bool expected_has_focus = PP_TRUE; |
| 201 ResetReceived(); |
| 202 ppp_instance->DidChangeFocus(expected_instance, expected_has_focus); |
| 203 did_change_focus_called.Wait(); |
| 204 EXPECT_EQ(received_instance, expected_instance); |
| 205 EXPECT_EQ(received_has_focus, expected_has_focus); |
| 206 |
| 207 PP_InputEvent expected_event = { PP_INPUTEVENT_TYPE_KEYDOWN, // type |
| 208 0, // padding |
| 209 1.0, // time_stamp |
| 210 { { 2, 3 } } }; // u (as PP_InputEvent_Key) |
| 211 ResetReceived(); |
| 212 EXPECT_EQ(bool_to_return, |
| 213 ppp_instance->HandleInputEvent(expected_instance, &expected_event)); |
| 214 EXPECT_EQ(received_instance, expected_instance); |
| 215 ASSERT_EQ(received_event.type, expected_event.type); |
| 216 // Ignore padding; it's okay if it's not serialized. |
| 217 EXPECT_EQ(received_event.time_stamp, expected_event.time_stamp); |
| 218 EXPECT_EQ(received_event.u.key.modifier, expected_event.u.key.modifier); |
| 219 EXPECT_EQ(received_event.u.key.key_code, expected_event.u.key.key_code); |
| 220 |
| 221 // TODO(dmichael): Need to mock out a resource Tracker to be able to test |
| 222 // HandleResourceLoad. It also requires |
| 223 // PPB_Core.AddRefResource and for PPB_URLLoader to be |
| 224 // registered. |
| 225 |
| 226 var_to_return = PP_MakeInt32(100); |
| 227 ResetReceived(); |
| 228 PP_Var result(ppp_instance->GetInstanceObject(expected_instance)); |
| 229 ASSERT_EQ(var_to_return.type, result.type); |
| 230 EXPECT_EQ(var_to_return.value.as_int, result.value.as_int); |
| 231 EXPECT_EQ(received_instance, expected_instance); |
| 232 } |
| 233 |
| 234 TEST_F(PPP_Instance_ProxyTest, PPPInstance0_5) { |
| 235 plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_0_5, &ppp_instance_0_5); |
| 236 host().RegisterTestInterface(PPB_FULLSCREEN_DEV_INTERFACE, |
| 237 &ppb_fullscreen_dev); |
| 238 |
| 239 // Grab the host-side proxy for the 0.5 interface. |
| 240 const PPP_Instance_0_5* ppp_instance = static_cast<const PPP_Instance_0_5*>( |
| 241 host().host_dispatcher()->GetProxiedInterface( |
| 242 PPP_INSTANCE_INTERFACE_0_5)); |
| 243 |
| 244 // Call each function in turn, make sure we get the expected values and |
| 245 // returns. |
| 246 // |
| 247 // We don't test DidDestroy, because it has the side-effect of removing the |
| 248 // PP_Instance from the PluginDispatcher, which will cause a failure later |
| 249 // when the test is torn down. |
| 250 PP_Instance expected_instance = pp_instance(); |
| 251 std::vector<std::string> expected_argn, expected_argv; |
| 252 expected_argn.push_back("Hello"); |
| 253 expected_argn.push_back("world."); |
| 254 expected_argv.push_back("elloHay"); |
| 255 expected_argv.push_back("orldway."); |
| 256 std::vector<const char*> argn_to_pass, argv_to_pass; |
| 257 CHECK(expected_argn.size() == expected_argv.size()); |
| 258 for (size_t i = 0; i < expected_argn.size(); ++i) { |
| 259 argn_to_pass.push_back(expected_argn[i].c_str()); |
| 260 argv_to_pass.push_back(expected_argv[i].c_str()); |
| 261 } |
| 262 uint32_t expected_argc = expected_argn.size(); |
| 263 bool_to_return = PP_TRUE; |
| 264 ResetReceived(); |
| 265 EXPECT_EQ(bool_to_return, ppp_instance->DidCreate(expected_instance, |
| 266 expected_argc, |
| 267 &argn_to_pass[0], |
| 268 &argv_to_pass[0])); |
| 269 EXPECT_EQ(received_instance, expected_instance); |
| 270 EXPECT_EQ(received_argc, expected_argc); |
| 271 EXPECT_EQ(received_argn, expected_argn); |
| 272 EXPECT_EQ(received_argv, expected_argv); |
| 273 |
| 274 PP_Rect expected_position = { {1, 2}, {3, 4} }; |
| 275 PP_Rect expected_clip = { {5, 6}, {7, 8} }; |
| 276 ResetReceived(); |
| 277 ppp_instance->DidChangeView(expected_instance, &expected_position, |
| 278 &expected_clip); |
| 279 did_change_view_called.Wait(); |
| 280 EXPECT_EQ(received_instance, expected_instance); |
| 281 EXPECT_EQ(received_position.point.x, expected_position.point.x); |
| 282 EXPECT_EQ(received_position.point.y, expected_position.point.y); |
| 283 EXPECT_EQ(received_position.size.width, expected_position.size.width); |
| 284 EXPECT_EQ(received_position.size.height, expected_position.size.height); |
| 285 EXPECT_EQ(received_clip.point.x, expected_clip.point.x); |
| 286 EXPECT_EQ(received_clip.point.y, expected_clip.point.y); |
| 287 EXPECT_EQ(received_clip.size.width, expected_clip.size.width); |
| 288 EXPECT_EQ(received_clip.size.height, expected_clip.size.height); |
| 289 |
| 290 PP_Bool expected_has_focus = PP_TRUE; |
| 291 ResetReceived(); |
| 292 ppp_instance->DidChangeFocus(expected_instance, expected_has_focus); |
| 293 did_change_focus_called.Wait(); |
| 294 EXPECT_EQ(received_instance, expected_instance); |
| 295 EXPECT_EQ(received_has_focus, expected_has_focus); |
| 296 |
| 297 PP_InputEvent expected_event = { PP_INPUTEVENT_TYPE_KEYDOWN, // type |
| 298 0, // padding |
| 299 1.0, // time_stamp |
| 300 { { 2, 3 } } }; // u (as PP_InputEvent_Key) |
| 301 ResetReceived(); |
| 302 EXPECT_EQ(bool_to_return, |
| 303 ppp_instance->HandleInputEvent(expected_instance, &expected_event)); |
| 304 EXPECT_EQ(received_instance, expected_instance); |
| 305 ASSERT_EQ(received_event.type, expected_event.type); |
| 306 // Ignore padding; it's okay if it's not serialized. |
| 307 EXPECT_EQ(received_event.time_stamp, expected_event.time_stamp); |
| 308 EXPECT_EQ(received_event.u.key.modifier, expected_event.u.key.modifier); |
| 309 EXPECT_EQ(received_event.u.key.key_code, expected_event.u.key.key_code); |
| 310 |
| 311 // TODO(dmichael): Need to mock out a resource Tracker to be able to test |
| 312 // HandleResourceLoad. It also requires |
| 313 // PPB_Core.AddRefResource and for PPB_URLLoader to be |
| 314 // registered. |
| 315 } |
| 316 |
| 317 } // namespace proxy |
| 318 } // namespace pp |
| 319 |
OLD | NEW |