| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "base/synchronization/waitable_event.h" |
| #include "ipc/ipc_message_utils.h" |
| #include "ppapi/c/pp_var.h" |
| #include "ppapi/c/ppb_core.h" |
| #include "ppapi/c/ppb_fullscreen.h" |
| #include "ppapi/c/ppb_url_loader.h" |
| #include "ppapi/c/ppp_instance.h" |
| #include "ppapi/proxy/locking_resource_releaser.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| #include "ppapi/proxy/ppapi_proxy_test.h" |
| #include "ppapi/shared_impl/ppb_view_shared.h" |
| |
| namespace ppapi { |
| namespace proxy { |
| |
| namespace { |
| |
| // This is an ad-hoc mock of PPP_Instance using global variables. Eventually, |
| // generalize making PPAPI interface mocks by using IDL or macro/template magic. |
| PP_Instance received_instance; |
| uint32_t received_argc; |
| std::vector<std::string> received_argn; |
| std::vector<std::string> received_argv; |
| PP_Bool bool_to_return; |
| PP_Bool DidCreate(PP_Instance instance, uint32_t argc, const char* argn[], |
| const char* argv[]) { |
| received_instance = instance; |
| received_argc = argc; |
| received_argn.clear(); |
| received_argn.insert(received_argn.begin(), argn, argn + argc); |
| received_argv.clear(); |
| received_argv.insert(received_argv.begin(), argv, argv + argc); |
| return bool_to_return; |
| } |
| |
| void DidDestroy(PP_Instance instance) { |
| received_instance = instance; |
| } |
| |
| PP_Rect received_position; |
| PP_Rect received_clip; |
| // DidChangeView is asynchronous. We wait until the call has completed before |
| // proceeding on to the next test. |
| base::WaitableEvent did_change_view_called( |
| base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| base::WaitableEvent::InitialState::NOT_SIGNALED); |
| void DidChangeView(PP_Instance instance, const PP_Rect* position, |
| const PP_Rect* clip) { |
| received_instance = instance; |
| received_position = *position; |
| received_clip = *clip; |
| did_change_view_called.Signal(); |
| } |
| |
| PP_Bool received_has_focus; |
| base::WaitableEvent did_change_focus_called( |
| base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| base::WaitableEvent::InitialState::NOT_SIGNALED); |
| void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) { |
| received_instance = instance; |
| received_has_focus = has_focus; |
| did_change_focus_called.Signal(); |
| } |
| |
| PP_Bool HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader) { |
| // This one requires use of the PPB_URLLoader proxy and PPB_Core, plus a |
| // resource tracker for the url_loader resource. |
| // TODO(dmichael): Mock those out and test this function. |
| NOTREACHED(); |
| return PP_FALSE; |
| } |
| |
| // Clear all the 'received' values for our mock. Call this before you expect |
| // one of the functions to be invoked. TODO(dmichael): It would be better to |
| // have a flag also for each function, so we know the right one got called. |
| void ResetReceived() { |
| received_instance = 0; |
| received_argc = 0; |
| received_argn.clear(); |
| received_argv.clear(); |
| memset(&received_position, 0, sizeof(received_position)); |
| memset(&received_clip, 0, sizeof(received_clip)); |
| received_has_focus = PP_FALSE; |
| } |
| |
| PPP_Instance_1_0 ppp_instance_1_0 = { |
| &DidCreate, |
| &DidDestroy, |
| &DidChangeView, |
| &DidChangeFocus, |
| &HandleDocumentLoad |
| }; |
| |
| // PPP_Instance_Proxy::DidChangeView relies on PPB_Fullscreen being |
| // available with a valid implementation of IsFullScreen, so we mock it. |
| PP_Bool IsFullscreen(PP_Instance instance) { |
| return PP_FALSE; |
| } |
| PPB_Fullscreen ppb_fullscreen = { &IsFullscreen }; |
| |
| } // namespace |
| |
| class PPP_Instance_ProxyTest : public TwoWayTest { |
| public: |
| PPP_Instance_ProxyTest() |
| : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { |
| } |
| }; |
| |
| TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) { |
| plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, &ppp_instance_1_0); |
| host().RegisterTestInterface(PPB_FULLSCREEN_INTERFACE, |
| &ppb_fullscreen); |
| |
| // Grab the host-side proxy for the interface. The browser only speaks 1.1, |
| // while the proxy ensures support for the 1.0 version on the plugin side. |
| const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>( |
| host().host_dispatcher()->GetProxiedInterface( |
| PPP_INSTANCE_INTERFACE_1_1)); |
| |
| // Call each function in turn, make sure we get the expected values and |
| // returns. |
| // |
| // We don't test DidDestroy, because it has the side-effect of removing the |
| // PP_Instance from the PluginDispatcher, which will cause a failure later |
| // when the test is torn down. |
| PP_Instance expected_instance = pp_instance(); |
| std::vector<std::string> expected_argn, expected_argv; |
| expected_argn.push_back("Hello"); |
| expected_argn.push_back("world."); |
| expected_argv.push_back("elloHay"); |
| expected_argv.push_back("orldway."); |
| std::vector<const char*> argn_to_pass, argv_to_pass; |
| CHECK(expected_argn.size() == expected_argv.size()); |
| for (size_t i = 0; i < expected_argn.size(); ++i) { |
| argn_to_pass.push_back(expected_argn[i].c_str()); |
| argv_to_pass.push_back(expected_argv[i].c_str()); |
| } |
| uint32_t expected_argc = static_cast<uint32_t>(expected_argn.size()); |
| bool_to_return = PP_TRUE; |
| ResetReceived(); |
| // Tell the host resource tracker about the instance. |
| host().resource_tracker().DidCreateInstance(expected_instance); |
| EXPECT_EQ(bool_to_return, ppp_instance->DidCreate(expected_instance, |
| expected_argc, |
| &argn_to_pass[0], |
| &argv_to_pass[0])); |
| EXPECT_EQ(received_instance, expected_instance); |
| EXPECT_EQ(received_argc, expected_argc); |
| EXPECT_EQ(received_argn, expected_argn); |
| EXPECT_EQ(received_argv, expected_argv); |
| |
| PP_Rect expected_position = { {1, 2}, {3, 4} }; |
| PP_Rect expected_clip = { {5, 6}, {7, 8} }; |
| ViewData data; |
| data.rect = expected_position; |
| data.is_fullscreen = false; |
| data.is_page_visible = true; |
| data.clip_rect = expected_clip; |
| data.device_scale = 1.0f; |
| ResetReceived(); |
| LockingResourceReleaser view_resource( |
| (new PPB_View_Shared(OBJECT_IS_IMPL, |
| expected_instance, data))->GetReference()); |
| ppp_instance->DidChangeView(expected_instance, view_resource.get()); |
| did_change_view_called.Wait(); |
| EXPECT_EQ(received_instance, expected_instance); |
| EXPECT_EQ(received_position.point.x, expected_position.point.x); |
| EXPECT_EQ(received_position.point.y, expected_position.point.y); |
| EXPECT_EQ(received_position.size.width, expected_position.size.width); |
| EXPECT_EQ(received_position.size.height, expected_position.size.height); |
| EXPECT_EQ(received_clip.point.x, expected_clip.point.x); |
| EXPECT_EQ(received_clip.point.y, expected_clip.point.y); |
| EXPECT_EQ(received_clip.size.width, expected_clip.size.width); |
| EXPECT_EQ(received_clip.size.height, expected_clip.size.height); |
| |
| PP_Bool expected_has_focus = PP_TRUE; |
| ResetReceived(); |
| ppp_instance->DidChangeFocus(expected_instance, expected_has_focus); |
| did_change_focus_called.Wait(); |
| EXPECT_EQ(received_instance, expected_instance); |
| EXPECT_EQ(received_has_focus, expected_has_focus); |
| |
| // TODO(dmichael): Need to mock out a resource Tracker to be able to test |
| // HandleResourceLoad. It also requires |
| // PPB_Core.AddRefResource and for PPB_URLLoader to be |
| // registered. |
| |
| host().resource_tracker().DidDeleteInstance(expected_instance); |
| } |
| |
| } // namespace proxy |
| } // namespace ppapi |