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