Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | |
| 6 #include "base/message_loop.h" | |
| 7 #include "base/test/test_timeouts.h" | |
| 8 #include "base/time.h" | |
| 5 #include "ppapi/c/dev/ppb_var_deprecated.h" | 9 #include "ppapi/c/dev/ppb_var_deprecated.h" |
| 6 #include "ppapi/c/dev/ppp_class_deprecated.h" | 10 #include "ppapi/c/dev/ppp_class_deprecated.h" |
| 7 #include "ppapi/c/pp_var.h" | 11 #include "ppapi/c/pp_var.h" |
| 8 #include "ppapi/c/ppb_var.h" | 12 #include "ppapi/c/ppb_var.h" |
| 9 #include "ppapi/c/ppp_instance.h" | 13 #include "ppapi/c/ppp_instance.h" |
| 10 #include "ppapi/c/private/ppp_instance_private.h" | 14 #include "ppapi/c/private/ppp_instance_private.h" |
| 11 #include "ppapi/proxy/host_dispatcher.h" | 15 #include "ppapi/proxy/host_dispatcher.h" |
| 12 #include "ppapi/proxy/ppapi_proxy_test.h" | 16 #include "ppapi/proxy/ppapi_proxy_test.h" |
| 17 #include "ppapi/shared_impl/ppb_var_shared.h" | |
| 18 #include "ppapi/shared_impl/var.h" | |
| 13 | 19 |
| 14 namespace ppapi { | 20 namespace ppapi { |
| 21 PP_Var GetPPVarNoAddRef(Var* var) { | |
|
brettw
2012/01/05 23:41:20
Blank line before this.
dmichael (off chromium)
2012/01/06 18:18:45
Done.
| |
| 22 PP_Var var_to_return = var->GetPPVar(); | |
| 23 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var_to_return); | |
| 24 return var_to_return; | |
| 25 } | |
| 26 | |
| 27 // A fake version of NPObjectVar for testing. | |
| 28 class NPObjectVar : public Var { | |
|
brettw
2012/01/05 23:41:20
Is it possible to put this in the anon namespace f
dmichael (off chromium)
2012/01/06 18:18:45
Unfortunately not; I'm providing a definition for
| |
| 29 public: | |
| 30 NPObjectVar() {} | |
| 31 virtual ~NPObjectVar() {} | |
| 32 | |
| 33 // Var overrides. | |
| 34 virtual NPObjectVar* AsNPObjectVar() OVERRIDE { return this; } | |
| 35 virtual PP_VarType GetType() const OVERRIDE { return PP_VARTYPE_OBJECT; } | |
| 36 }; | |
| 37 | |
| 15 namespace proxy { | 38 namespace proxy { |
| 16 | 39 |
| 17 namespace { | 40 namespace { |
| 18 const PP_Instance kInstance = 0xdeadbeef; | 41 const PP_Instance kInstance = 0xdeadbeef; |
| 19 | 42 |
| 20 PP_Var MakeObjectVar(int64_t object_id) { | |
| 21 PP_Var ret; | |
| 22 ret.type = PP_VARTYPE_OBJECT; | |
| 23 ret.value.as_id = object_id; | |
| 24 return ret; | |
| 25 } | |
| 26 | |
| 27 PluginDispatcher* plugin_dispatcher = NULL; | 43 PluginDispatcher* plugin_dispatcher = NULL; |
| 28 // Return the plugin-side proxy for PPB_Var_Deprecated. | 44 // Return the plugin-side proxy for PPB_Var_Deprecated. |
| 29 const PPB_Var_Deprecated* plugin_var_deprecated_if() { | 45 const PPB_Var_Deprecated* plugin_var_deprecated_if() { |
| 30 // The test code must set the plugin dispatcher. | 46 // The test code must set the plugin dispatcher. |
| 31 CHECK(plugin_dispatcher); | 47 CHECK(plugin_dispatcher); |
| 32 // Grab the plugin-side proxy for PPB_Var_Deprecated (for CreateObject). | 48 // Grab the plugin-side proxy for PPB_Var_Deprecated (for CreateObject). |
| 33 return static_cast<const PPB_Var_Deprecated*>( | 49 return static_cast<const PPB_Var_Deprecated*>( |
| 34 plugin_dispatcher->GetBrowserInterface( | 50 plugin_dispatcher->GetBrowserInterface( |
| 35 PPB_VAR_DEPRECATED_INTERFACE)); | 51 PPB_VAR_DEPRECATED_INTERFACE)); |
| 36 } | 52 } |
| 37 | 53 |
| 38 // Mock PPP_Instance_Private. | 54 // Mock PPP_Instance_Private. |
| 39 PP_Var instance_obj; | 55 PP_Var instance_obj; |
| 40 PP_Var GetInstanceObject(PP_Instance /*instance*/) { | 56 PP_Var GetInstanceObject(PP_Instance /*instance*/) { |
| 41 // The 1 ref we got from CreateObject will be passed to the host. We want to | 57 // The 1 ref we got from CreateObject will be passed to the host. We want to |
| 42 // have a ref of our own. | 58 // have a ref of our own. |
| 43 plugin_var_deprecated_if()->AddRef(instance_obj); | 59 printf("GetInstanceObject called\n"); |
| 60 PpapiGlobals::Get()->GetVarTracker()->AddRefVar(instance_obj); | |
| 44 return instance_obj; | 61 return instance_obj; |
| 45 } | 62 } |
| 46 | 63 |
| 47 PPP_Instance_Private ppp_instance_private_mock = { | 64 PPP_Instance_Private ppp_instance_private_mock = { |
| 48 &GetInstanceObject | 65 &GetInstanceObject |
| 49 }; | 66 }; |
| 50 | 67 |
| 51 // We need to mock PPP_Instance, so that we can create and destroy the pretend | 68 // We need to mock PPP_Instance, so that we can create and destroy the pretend |
| 52 // instance that PPP_Instance_Private uses. | 69 // instance that PPP_Instance_Private uses. |
| 53 PP_Bool DidCreate(PP_Instance /*instance*/, uint32_t /*argc*/, | 70 PP_Bool DidCreate(PP_Instance /*instance*/, uint32_t /*argc*/, |
| 54 const char* /*argn*/[], const char* /*argv*/[]) { | 71 const char* /*argn*/[], const char* /*argv*/[]) { |
| 55 // Create an object var. This should exercise the typical path for creating | 72 // Create an object var. This should exercise the typical path for creating |
| 56 // instance objects. | 73 // instance objects. |
| 57 instance_obj = | 74 instance_obj = |
| 58 plugin_var_deprecated_if()->CreateObject(kInstance, NULL, NULL); | 75 plugin_var_deprecated_if()->CreateObject(kInstance, NULL, NULL); |
| 59 return PP_TRUE; | 76 return PP_TRUE; |
| 60 } | 77 } |
| 61 | 78 |
| 62 void DidDestroy(PP_Instance /*instance*/) { | 79 void DidDestroy(PP_Instance /*instance*/) { |
| 63 // Decrement the reference count for our instance object. It should be | 80 // Decrement the reference count for our instance object. It should be |
| 64 // deleted. | 81 // deleted. |
| 65 plugin_var_deprecated_if()->Release(instance_obj); | 82 plugin_var_deprecated_if()->Release(instance_obj); |
| 66 } | 83 } |
| 67 | 84 |
| 68 PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy }; | 85 PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy }; |
| 69 | 86 |
| 70 } // namespace | |
| 71 | |
| 72 // Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var. | 87 // Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var. |
| 73 std::map<int64_t, int> id_refcount_map; | 88 PP_Var CreateObject(PP_Instance /*instance*/, |
| 74 void AddRefVar(PP_Var var) { | |
| 75 CHECK(var.type >= PP_VARTYPE_STRING); // Must be a ref-counted type. | |
| 76 CHECK(id_refcount_map.find(var.value.as_id) != id_refcount_map.end()); | |
| 77 ++id_refcount_map[var.value.as_id]; | |
| 78 } | |
| 79 | |
| 80 void ReleaseVar(PP_Var var) { | |
| 81 CHECK(var.type >= PP_VARTYPE_STRING); // Must be a ref-counted type. | |
| 82 std::map<int64_t, int>::iterator iter = id_refcount_map.find(var.value.as_id); | |
| 83 CHECK(iter != id_refcount_map.end()); | |
| 84 CHECK(iter->second > 0); | |
| 85 if (--(iter->second) == 0) | |
| 86 id_refcount_map.erase(iter); | |
| 87 } | |
| 88 | |
| 89 PP_Var CreateObject(PP_Instance instance, | |
| 90 const PPP_Class_Deprecated* /*ppp_class*/, | 89 const PPP_Class_Deprecated* /*ppp_class*/, |
| 91 void* /*ppp_class_data*/) { | 90 void* /*ppp_class_data*/) { |
| 92 static int64_t last_id = 0; | 91 NPObjectVar* obj_var = new NPObjectVar; |
| 93 ++last_id; | 92 return obj_var->GetPPVar(); |
| 94 // Set the refcount to 0. It should really be 1, but that ref gets passed to | |
| 95 // the plugin immediately (and we don't emulate all of that behavior here). | |
| 96 id_refcount_map[last_id] = 0; | |
| 97 return MakeObjectVar(last_id); | |
| 98 } | 93 } |
| 99 | 94 |
| 100 const PPB_Var_Deprecated ppb_var_deprecated_mock = { | 95 const PPB_Var_Deprecated ppb_var_deprecated_mock = { |
| 101 &AddRefVar, | 96 PPB_Var_Shared::GetVarInterface1_0()->AddRef, |
| 102 &ReleaseVar, | 97 PPB_Var_Shared::GetVarInterface1_0()->Release, |
| 103 NULL, // VarFromUtf8 | 98 PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8, |
| 104 NULL, // VarToUtf8 | 99 PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8, |
| 105 NULL, // HasProperty | 100 NULL, // HasProperty |
| 106 NULL, // HasMethod | 101 NULL, // HasMethod |
| 107 NULL, // GetProperty | 102 NULL, // GetProperty |
| 108 NULL, // EnumerateProperties | 103 NULL, // EnumerateProperties |
| 109 NULL, // SetProperty | 104 NULL, // SetProperty |
| 110 NULL, // RemoveProperty | 105 NULL, // RemoveProperty |
| 111 NULL, // Call | 106 NULL, // Call |
| 112 NULL, // Construct | 107 NULL, // Construct |
| 113 NULL, // IsInstanceOf | 108 NULL, // IsInstanceOf |
| 114 &CreateObject | 109 &CreateObject |
| 115 }; | 110 }; |
| 116 | 111 |
| 117 const PPB_Var ppb_var_mock = { &AddRefVar, &ReleaseVar }; | 112 } // namespace |
| 118 | 113 |
| 119 class PPP_Instance_Private_ProxyTest : public TwoWayTest { | 114 class PPP_Instance_Private_ProxyTest : public TwoWayTest { |
| 120 public: | 115 public: |
| 121 PPP_Instance_Private_ProxyTest() | 116 PPP_Instance_Private_ProxyTest() |
| 122 : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { | 117 : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { |
| 123 plugin().RegisterTestInterface(PPP_INSTANCE_PRIVATE_INTERFACE, | 118 plugin().RegisterTestInterface(PPP_INSTANCE_PRIVATE_INTERFACE, |
| 124 &ppp_instance_private_mock); | 119 &ppp_instance_private_mock); |
| 125 plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, | 120 plugin().RegisterTestInterface(PPP_INSTANCE_INTERFACE_1_0, |
| 126 &ppp_instance_mock); | 121 &ppp_instance_mock); |
| 127 host().RegisterTestInterface(PPB_VAR_DEPRECATED_INTERFACE, | 122 host().RegisterTestInterface(PPB_VAR_DEPRECATED_INTERFACE, |
| 128 &ppb_var_deprecated_mock); | 123 &ppb_var_deprecated_mock); |
| 129 host().RegisterTestInterface(PPB_VAR_INTERFACE, | |
| 130 &ppb_var_mock); | |
| 131 } | 124 } |
| 132 }; | 125 }; |
| 133 | 126 |
| 134 TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) { | 127 TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) { |
| 135 // This test controls its own instance; we can't use the one that | 128 // This test controls its own instance; we can't use the one that |
| 136 // PluginProxyTestHarness provides. | 129 // PluginProxyTestHarness provides. |
| 137 ASSERT_NE(kInstance, pp_instance()); | 130 ASSERT_NE(kInstance, pp_instance()); |
| 138 HostDispatcher::SetForInstance(kInstance, host().host_dispatcher()); | 131 HostDispatcher::SetForInstance(kInstance, host().host_dispatcher()); |
| 139 | 132 |
| 140 // This file-local global is used by the PPP_Instance mock above in order to | 133 // This file-local global is used by the PPP_Instance mock above in order to |
| 141 // access PPB_Var_Deprecated. | 134 // access PPB_Var_Deprecated. |
| 142 plugin_dispatcher = plugin().plugin_dispatcher(); | 135 plugin_dispatcher = plugin().plugin_dispatcher(); |
| 143 | 136 |
| 144 // Grab the host-side proxy for PPP_Instance and PPP_Instance_Private. | 137 // Grab the host-side proxy for PPP_Instance and PPP_Instance_Private. |
| 145 const PPP_Instance_Private* ppp_instance_private = | 138 const PPP_Instance_Private* ppp_instance_private = |
| 146 static_cast<const PPP_Instance_Private*>( | 139 static_cast<const PPP_Instance_Private*>( |
| 147 host().host_dispatcher()->GetProxiedInterface( | 140 host().host_dispatcher()->GetProxiedInterface( |
| 148 PPP_INSTANCE_PRIVATE_INTERFACE)); | 141 PPP_INSTANCE_PRIVATE_INTERFACE)); |
| 149 const PPP_Instance_1_0* ppp_instance = static_cast<const PPP_Instance_1_0*>( | 142 const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>( |
| 150 host().host_dispatcher()->GetProxiedInterface( | 143 host().host_dispatcher()->GetProxiedInterface( |
| 151 PPP_INSTANCE_INTERFACE_1_0)); | 144 PPP_INSTANCE_INTERFACE_1_1)); |
| 152 | 145 |
| 153 // Initialize an Instance, so that the plugin-side machinery will work | 146 // Initialize an Instance, so that the plugin-side machinery will work |
| 154 // properly. | 147 // properly. |
| 155 EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL)); | 148 EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL)); |
| 156 | 149 |
| 157 // Now instance_obj is valid and should have a ref-count of 1. | |
| 158 PluginVarTracker& plugin_var_tracker = | |
| 159 *PluginGlobals::Get()->plugin_var_tracker(); | |
| 160 // Check the plugin-side reference count. | 150 // Check the plugin-side reference count. |
| 161 EXPECT_EQ(1, plugin_var_tracker.GetRefCountForObject(instance_obj)); | 151 EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj)); |
| 162 // Check the host-side var and reference count. | 152 // Check the host-side var exists with the expected id and has 1 refcount (the |
| 163 ASSERT_EQ(1u, id_refcount_map.size()); | 153 // refcount on behalf of the plugin). |
| 164 EXPECT_EQ(plugin_var_tracker.GetHostObject(instance_obj).value.as_id, | 154 int32 expected_host_id = |
| 165 id_refcount_map.begin()->first); | 155 plugin().var_tracker().GetHostObject(instance_obj).value.as_id; |
| 166 EXPECT_EQ(0, id_refcount_map.begin()->second); | 156 Var* host_var = host().var_tracker().GetVar(expected_host_id); |
| 157 ASSERT_TRUE(host_var); | |
| 158 EXPECT_EQ( | |
| 159 1, | |
| 160 host().var_tracker().GetRefCountForObject(GetPPVarNoAddRef(host_var))); | |
| 167 | 161 |
| 168 // Call from the browser side to get the instance object. | 162 // Call from the browser side to get the instance object. |
| 169 PP_Var host_obj = ppp_instance_private->GetInstanceObject(kInstance); | 163 PP_Var host_pp_var = ppp_instance_private->GetInstanceObject(kInstance); |
| 170 EXPECT_EQ(instance_obj.type, host_obj.type); | 164 EXPECT_EQ(instance_obj.type, host_pp_var.type); |
| 171 EXPECT_EQ(host_obj.value.as_id, | 165 EXPECT_EQ(host_pp_var.value.as_id, expected_host_id); |
| 172 plugin_var_tracker.GetHostObject(instance_obj).value.as_id); | 166 EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj)); |
| 173 EXPECT_EQ(1, plugin_var_tracker.GetRefCountForObject(instance_obj)); | 167 // A reference is passed to the browser, which we consume here. |
| 174 ASSERT_EQ(1u, id_refcount_map.size()); | 168 host().var_tracker().ReleaseVar(host_pp_var); |
| 175 // The browser should be passed a reference. | 169 EXPECT_EQ(1, host().var_tracker().GetRefCountForObject(host_pp_var)); |
| 176 EXPECT_EQ(1, id_refcount_map.begin()->second); | |
| 177 | 170 |
| 178 // The plugin is going away; generally, so will all references to its instance | 171 // The plugin is going away; generally, so will all references to its instance |
| 179 // object. | 172 // object. |
| 180 ReleaseVar(host_obj); | 173 host().var_tracker().ReleaseVar(host_pp_var); |
| 181 // Destroy the instance. DidDestroy above decrements the reference count for | 174 // Destroy the instance. DidDestroy above decrements the reference count for |
| 182 // instance_obj, so it should also be destroyed. | 175 // instance_obj, so it should also be destroyed. |
| 183 ppp_instance->DidDestroy(kInstance); | 176 ppp_instance->DidDestroy(kInstance); |
| 184 EXPECT_EQ(-1, plugin_var_tracker.GetRefCountForObject(instance_obj)); | 177 EXPECT_EQ(-1, plugin().var_tracker().GetRefCountForObject(instance_obj)); |
| 185 // Check the host-side reference count. | 178 EXPECT_EQ(-1, host().var_tracker().GetRefCountForObject(host_pp_var)); |
| 186 EXPECT_EQ(0u, id_refcount_map.size()); | |
| 187 } | 179 } |
| 188 | 180 |
| 189 } // namespace proxy | 181 } // namespace proxy |
| 190 } // namespace ppapi | 182 } // namespace ppapi |
| 191 | 183 |
| OLD | NEW |