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/synchronization/waitable_event.h" 6 #include "ipc/ipc_message_utils.h" 7 #include "ppapi/c/pp_var.h" 8 #include "ppapi/c/ppb_core.h" 9 #include "ppapi/c/ppb_fullscreen.h" 10 #include "ppapi/c/ppb_url_loader.h" 11 #include "ppapi/c/ppp_instance.h" 12 #include "ppapi/c/private/ppb_flash_fullscreen.h" 13 #include "ppapi/proxy/locking_resource_releaser.h" 14 #include "ppapi/proxy/ppapi_messages.h" 15 #include "ppapi/proxy/ppapi_proxy_test.h" 16 #include "ppapi/shared_impl/ppb_view_shared.h" 17 18 namespace ppapi { 19 namespace proxy { 20 21 namespace { 22 // This is a poor man's mock of PPP_Instance using global variables. Eventually 23 // we should generalize making PPAPI interface mocks by using IDL or macro/ 24 // template magic. 25 PP_Instance received_instance; 26 uint32_t received_argc; 27 std::vector<std::string> received_argn; 28 std::vector<std::string> received_argv; 29 PP_Bool bool_to_return; 30 PP_Bool DidCreate(PP_Instance instance, uint32_t argc, const char* argn[], 31 const char* argv[]) { 32 received_instance = instance; 33 received_argc = argc; 34 received_argn.clear(); 35 received_argn.insert(received_argn.begin(), argn, argn + argc); 36 received_argv.clear(); 37 received_argv.insert(received_argv.begin(), argv, argv + argc); 38 return bool_to_return; 39 } 40 41 void DidDestroy(PP_Instance instance) { 42 received_instance = instance; 43 } 44 45 PP_Rect received_position; 46 PP_Rect received_clip; 47 // DidChangeView is asynchronous. We wait until the call has completed before 48 // proceeding on to the next test. 49 base::WaitableEvent did_change_view_called(false, false); 50 void DidChangeView(PP_Instance instance, const PP_Rect* position, 51 const PP_Rect* clip) { 52 received_instance = instance; 53 received_position = *position; 54 received_clip = *clip; 55 did_change_view_called.Signal(); 56 } 57 58 PP_Bool received_has_focus; 59 base::WaitableEvent did_change_focus_called(false, false); 60 void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { 61 received_instance = instance; 62 received_has_focus = has_focus; 63 did_change_focus_called.Signal(); 64 } 65 66 PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) { 67 // This one requires use of the PPB_URLLoader proxy and PPB_Core, plus a 68 // resource tracker for the url_loader resource. 69 // TODO(dmichael): Mock those out and test this function. 70 NOTREACHED(); 71 return PP_FALSE; 72 } 73 74 // Clear all the 'received' values for our mock. Call this before you expect 75 // one of the functions to be invoked. TODO(dmichael): It would be better to 76 // have a flag also for each function, so we know the right one got called. 77 void ResetReceived() { 78 received_instance = 0; 79 received_argc = 0; 80 received_argn.clear(); 81 received_argv.clear(); 82 memset(&received_position, 0, sizeof(received_position)); 83 memset(&received_clip, 0, sizeof(received_clip)); 84 received_has_focus = PP_FALSE; 85 } 86 87 PPP_Instance_1_0 ppp_instance_1_0 = { 88 &DidCreate, 89 &DidDestroy, 90 &DidChangeView, 91 &DidChangeFocus, 92 &HandleDocumentLoad 93 }; 94 95 // PPP_Instance_Proxy::DidChangeView relies on PPB_(Flash)Fullscreen being 96 // available with a valid implementation of IsFullScreen, so we mock it. 97 PP_Bool IsFullscreen(PP_Instance instance) { 98 return PP_FALSE; 99 } 100 PPB_Fullscreen ppb_fullscreen = { &IsFullscreen }; 101 PPB_FlashFullscreen ppb_flash_fullscreen = { &IsFullscreen }; 102 103 } // namespace 104 105 class PPP_Instance_ProxyTest : public TwoWayTest { 106 public: 107 PPP_Instance_ProxyTest() 108 : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { 109 } 110 }; 111 112 TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) { 113 plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, &ppp_instance_1_0); 114 host().RegisterTestInterface(PPB_FLASHFULLSCREEN_INTERFACE, 115 &ppb_flash_fullscreen); 116 host().RegisterTestInterface(PPB_FULLSCREEN_INTERFACE, 117 &ppb_fullscreen); 118 119 // Grab the host-side proxy for the interface. The browser only speaks 1.1, 120 // while the proxy ensures support for the 1.0 version on the plugin side. 121 const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>( 122 host().host_dispatcher()->GetProxiedInterface( 123 PPP_INSTANCE_INTERFACE_1_1)); 124 125 // Call each function in turn, make sure we get the expected values and 126 // returns. 127 // 128 // We don't test DidDestroy, because it has the side-effect of removing the 129 // PP_Instance from the PluginDispatcher, which will cause a failure later 130 // when the test is torn down. 131 PP_Instance expected_instance = pp_instance(); 132 std::vector<std::string> expected_argn, expected_argv; 133 expected_argn.push_back("Hello"); 134 expected_argn.push_back("world."); 135 expected_argv.push_back("elloHay"); 136 expected_argv.push_back("orldway."); 137 std::vector<const char*> argn_to_pass, argv_to_pass; 138 CHECK(expected_argn.size() == expected_argv.size()); 139 for (size_t i = 0; i < expected_argn.size(); ++i) { 140 argn_to_pass.push_back(expected_argn[i].c_str()); 141 argv_to_pass.push_back(expected_argv[i].c_str()); 142 } 143 uint32_t expected_argc = expected_argn.size(); 144 bool_to_return = PP_TRUE; 145 ResetReceived(); 146 // Tell the host resource tracker about the instance. 147 host().resource_tracker().DidCreateInstance(expected_instance); 148 EXPECT_EQ(bool_to_return, ppp_instance->DidCreate(expected_instance, 149 expected_argc, 150 &argn_to_pass[0], 151 &argv_to_pass[0])); 152 EXPECT_EQ(received_instance, expected_instance); 153 EXPECT_EQ(received_argc, expected_argc); 154 EXPECT_EQ(received_argn, expected_argn); 155 EXPECT_EQ(received_argv, expected_argv); 156 157 PP_Rect expected_position = { {1, 2}, {3, 4} }; 158 PP_Rect expected_clip = { {5, 6}, {7, 8} }; 159 ViewData data; 160 data.rect = expected_position; 161 data.is_fullscreen = false; 162 data.is_page_visible = true; 163 data.clip_rect = expected_clip; 164 data.device_scale = 1.0f; 165 ResetReceived(); 166 LockingResourceReleaser view_resource( 167 (new PPB_View_Shared(OBJECT_IS_IMPL, 168 expected_instance, data))->GetReference()); 169 ppp_instance->DidChangeView(expected_instance, view_resource.get()); 170 did_change_view_called.Wait(); 171 EXPECT_EQ(received_instance, expected_instance); 172 EXPECT_EQ(received_position.point.x, expected_position.point.x); 173 EXPECT_EQ(received_position.point.y, expected_position.point.y); 174 EXPECT_EQ(received_position.size.width, expected_position.size.width); 175 EXPECT_EQ(received_position.size.height, expected_position.size.height); 176 EXPECT_EQ(received_clip.point.x, expected_clip.point.x); 177 EXPECT_EQ(received_clip.point.y, expected_clip.point.y); 178 EXPECT_EQ(received_clip.size.width, expected_clip.size.width); 179 EXPECT_EQ(received_clip.size.height, expected_clip.size.height); 180 181 PP_Bool expected_has_focus = PP_TRUE; 182 ResetReceived(); 183 ppp_instance->DidChangeFocus(expected_instance, expected_has_focus); 184 did_change_focus_called.Wait(); 185 EXPECT_EQ(received_instance, expected_instance); 186 EXPECT_EQ(received_has_focus, expected_has_focus); 187 188 // TODO(dmichael): Need to mock out a resource Tracker to be able to test 189 // HandleResourceLoad. It also requires 190 // PPB_Core.AddRefResource and for PPB_URLLoader to be 191 // registered. 192 193 host().resource_tracker().DidDeleteInstance(expected_instance); 194 } 195 196 } // namespace proxy 197 } // namespace ppapi 198