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