ppp_instance_private_proxy_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/bind.h" 6#include "base/message_loop.h" 7#include "base/test/test_timeouts.h" 8#include "base/time.h" 9#include "ppapi/c/dev/ppb_var_deprecated.h" 10#include "ppapi/c/dev/ppp_class_deprecated.h" 11#include "ppapi/c/pp_var.h" 12#include "ppapi/c/ppb_var.h" 13#include "ppapi/c/ppp_instance.h" 14#include "ppapi/c/private/ppp_instance_private.h" 15#include "ppapi/proxy/host_dispatcher.h" 16#include "ppapi/proxy/interface_list.h" 17#include "ppapi/proxy/ppapi_proxy_test.h" 18#include "ppapi/shared_impl/ppapi_permissions.h" 19#include "ppapi/shared_impl/ppb_var_shared.h" 20#include "ppapi/shared_impl/var.h" 21 22namespace ppapi { 23 24// A fake version of NPObjectVar for testing. 25class NPObjectVar : public ppapi::Var { 26 public: 27 NPObjectVar() {} 28 virtual ~NPObjectVar() {} 29 30 // Var overrides. 31 virtual NPObjectVar* AsNPObjectVar() OVERRIDE { return this; } 32 virtual PP_VarType GetType() const OVERRIDE { return PP_VARTYPE_OBJECT; } 33}; 34 35namespace proxy { 36 37namespace { 38const PP_Instance kInstance = 0xdeadbeef; 39 40PP_Var GetPPVarNoAddRef(Var* var) { 41 PP_Var var_to_return = var->GetPPVar(); 42 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var_to_return); 43 return var_to_return; 44} 45 46PluginDispatcher* plugin_dispatcher = NULL; 47// Return the plugin-side proxy for PPB_Var_Deprecated. 48const PPB_Var_Deprecated* plugin_var_deprecated_if() { 49 // The test code must set the plugin dispatcher. 50 CHECK(plugin_dispatcher); 51 // Grab the plugin-side proxy for PPB_Var_Deprecated (for CreateObject). 52 return static_cast<const PPB_Var_Deprecated*>( 53 plugin_dispatcher->GetBrowserInterface( 54 PPB_VAR_DEPRECATED_INTERFACE)); 55} 56 57// Mock PPP_Instance_Private. 58PP_Var instance_obj; 59PP_Var GetInstanceObject(PP_Instance /*instance*/) { 60 // The 1 ref we got from CreateObject will be passed to the host. We want to 61 // have a ref of our own. 62 printf("GetInstanceObject called\n"); 63 plugin_var_deprecated_if()->AddRef(instance_obj); 64 return instance_obj; 65} 66 67PPP_Instance_Private ppp_instance_private_mock = { 68 &GetInstanceObject 69}; 70 71// We need to pass in a |PPP_Class_Deprecated| to 72// |PPB_Var_Deprecated->CreateObject| for a mock |Deallocate| method. 73void Deallocate(void* object) { 74} 75 76const PPP_Class_Deprecated ppp_class_deprecated_mock = { 77 NULL, // HasProperty 78 NULL, // HasMethod 79 NULL, // GetProperty 80 NULL, // GetAllPropertyNames 81 NULL, // SetProperty 82 NULL, // RemoveProperty 83 NULL, // Call 84 NULL, // Construct 85 &Deallocate 86}; 87 88 89// We need to mock PPP_Instance, so that we can create and destroy the pretend 90// instance that PPP_Instance_Private uses. 91PP_Bool DidCreate(PP_Instance /*instance*/, uint32_t /*argc*/, 92 const char* /*argn*/[], const char* /*argv*/[]) { 93 // Create an object var. This should exercise the typical path for creating 94 // instance objects. 95 instance_obj = 96 plugin_var_deprecated_if()->CreateObject(kInstance, 97 &ppp_class_deprecated_mock, 98 NULL); 99 return PP_TRUE; 100} 101 102void DidDestroy(PP_Instance /*instance*/) { 103 // Decrement the reference count for our instance object. It should be 104 // deleted. 105 plugin_var_deprecated_if()->Release(instance_obj); 106} 107 108PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy }; 109 110// Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var. 111PP_Var CreateObject(PP_Instance /*instance*/, 112 const PPP_Class_Deprecated* /*ppp_class*/, 113 void* /*ppp_class_data*/) { 114 NPObjectVar* obj_var = new NPObjectVar; 115 return obj_var->GetPPVar(); 116} 117 118const PPB_Var_Deprecated ppb_var_deprecated_mock = { 119 PPB_Var_Shared::GetVarInterface1_0()->AddRef, 120 PPB_Var_Shared::GetVarInterface1_0()->Release, 121 PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8, 122 PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8, 123 NULL, // HasProperty 124 NULL, // HasMethod 125 NULL, // GetProperty 126 NULL, // EnumerateProperties 127 NULL, // SetProperty 128 NULL, // RemoveProperty 129 NULL, // Call 130 NULL, // Construct 131 NULL, // IsInstanceOf 132 &CreateObject 133}; 134 135class PPP_Instance_Private_ProxyTest : public TwoWayTest { 136 public: 137 PPP_Instance_Private_ProxyTest() 138 : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { 139 plugin().RegisterTestInterface(PPP_INSTANCE_PRIVATE_INTERFACE, 140 &ppp_instance_private_mock); 141 plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, 142 &ppp_instance_mock); 143 host().RegisterTestInterface(PPB_VAR_DEPRECATED_INTERFACE, 144 &ppb_var_deprecated_mock); 145 } 146}; 147 148} // namespace 149 150// TODO(raymes): This #ifdef is only here because we check the state of the 151// plugin globals on the main thread, rather than the plugin thread which causes 152// the thread checker to fail. Once ENABLE_PEPPER_THREADING is the default, 153// this will be safe to do anyway, so we can remove this. 154#ifdef ENABLE_PEPPER_THREADING 155TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) { 156#else 157TEST_F(PPP_Instance_Private_ProxyTest, DISABLED_PPPInstancePrivate) { 158#endif 159 // This test controls its own instance; we can't use the one that 160 // PluginProxyTestHarness provides. 161 ASSERT_NE(kInstance, pp_instance()); 162 HostDispatcher::SetForInstance(kInstance, host().host_dispatcher()); 163 164 // Requires dev interfaces. 165 InterfaceList::SetProcessGlobalPermissions( 166 PpapiPermissions::AllPermissions()); 167 168 // This file-local global is used by the PPP_Instance mock above in order to 169 // access PPB_Var_Deprecated. 170 plugin_dispatcher = plugin().plugin_dispatcher(); 171 172 // Grab the host-side proxy for PPP_Instance and PPP_Instance_Private. 173 const PPP_Instance_Private* ppp_instance_private = 174 static_cast<const PPP_Instance_Private*>( 175 host().host_dispatcher()->GetProxiedInterface( 176 PPP_INSTANCE_PRIVATE_INTERFACE)); 177 const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>( 178 host().host_dispatcher()->GetProxiedInterface( 179 PPP_INSTANCE_INTERFACE_1_1)); 180 181 // Initialize an Instance, so that the plugin-side machinery will work 182 // properly. 183 EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL)); 184 185 // Check the plugin-side reference count. 186 EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj)); 187 // Check the host-side var exists with the expected id and has 1 refcount (the 188 // refcount on behalf of the plugin). 189 int32 expected_host_id = 190 plugin().var_tracker().GetHostObject(instance_obj).value.as_id; 191 Var* host_var = host().var_tracker().GetVar(expected_host_id); 192 ASSERT_TRUE(host_var); 193 EXPECT_EQ( 194 1, 195 host().var_tracker().GetRefCountForObject(GetPPVarNoAddRef(host_var))); 196 197 // Call from the browser side to get the instance object. 198 PP_Var host_pp_var = ppp_instance_private->GetInstanceObject(kInstance); 199 EXPECT_EQ(instance_obj.type, host_pp_var.type); 200 EXPECT_EQ(host_pp_var.value.as_id, expected_host_id); 201 EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj)); 202 // A reference is passed to the browser, which we consume here. 203 host().var_tracker().ReleaseVar(host_pp_var); 204 EXPECT_EQ(1, host().var_tracker().GetRefCountForObject(host_pp_var)); 205 206 // The plugin is going away; generally, so will all references to its instance 207 // object. 208 host().var_tracker().ReleaseVar(host_pp_var); 209 // Destroy the instance. DidDestroy above decrements the reference count for 210 // instance_obj, so it should also be destroyed. 211 ppp_instance->DidDestroy(kInstance); 212 EXPECT_EQ(-1, plugin().var_tracker().GetRefCountForObject(instance_obj)); 213 EXPECT_EQ(-1, host().var_tracker().GetRefCountForObject(host_pp_var)); 214} 215 216} // namespace proxy 217} // namespace ppapi 218 219