Home | History | Annotate | Download | only in proxy
      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/message_loop.h"
      7 #include "base/test/test_timeouts.h"
      8 #include "base/time/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 
     22 namespace ppapi {
     23 
     24 // A fake version of NPObjectVar for testing.
     25 class 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 
     35 namespace proxy {
     36 
     37 namespace {
     38 const PP_Instance kInstance = 0xdeadbeef;
     39 
     40 PP_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 
     46 PluginDispatcher* plugin_dispatcher = NULL;
     47 // Return the plugin-side proxy for PPB_Var_Deprecated.
     48 const 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.
     58 PP_Var instance_obj;
     59 PP_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 
     67 PPP_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.
     73 void Deallocate(void* object) {
     74 }
     75 
     76 const 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.
     91 PP_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 
    102 void 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 
    108 PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy };
    109 
    110 // Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var.
    111 PP_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 
    118 const 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 
    135 class 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 TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) {
    151   // This test controls its own instance; we can't use the one that
    152   // PluginProxyTestHarness provides.
    153   ASSERT_NE(kInstance, pp_instance());
    154   HostDispatcher::SetForInstance(kInstance, host().host_dispatcher());
    155 
    156   // Requires dev interfaces.
    157   InterfaceList::SetProcessGlobalPermissions(
    158       PpapiPermissions::AllPermissions());
    159 
    160   // This file-local global is used by the PPP_Instance mock above in order to
    161   // access PPB_Var_Deprecated.
    162   plugin_dispatcher = plugin().plugin_dispatcher();
    163 
    164   // Grab the host-side proxy for PPP_Instance and PPP_Instance_Private.
    165   const PPP_Instance_Private* ppp_instance_private =
    166       static_cast<const PPP_Instance_Private*>(
    167           host().host_dispatcher()->GetProxiedInterface(
    168               PPP_INSTANCE_PRIVATE_INTERFACE));
    169   const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>(
    170       host().host_dispatcher()->GetProxiedInterface(
    171           PPP_INSTANCE_INTERFACE_1_1));
    172 
    173   // Initialize an Instance, so that the plugin-side machinery will work
    174   // properly.
    175   EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL));
    176 
    177   // Check the plugin-side reference count.
    178   EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj));
    179   // Check the host-side var exists with the expected id and has 1 refcount (the
    180   // refcount on behalf of the plugin).
    181   int32 expected_host_id =
    182       plugin().var_tracker().GetHostObject(instance_obj).value.as_id;
    183   Var* host_var = host().var_tracker().GetVar(expected_host_id);
    184   ASSERT_TRUE(host_var);
    185   EXPECT_EQ(
    186       1,
    187       host().var_tracker().GetRefCountForObject(GetPPVarNoAddRef(host_var)));
    188 
    189   // Call from the browser side to get the instance object.
    190   PP_Var host_pp_var = ppp_instance_private->GetInstanceObject(kInstance);
    191   EXPECT_EQ(instance_obj.type, host_pp_var.type);
    192   EXPECT_EQ(host_pp_var.value.as_id, expected_host_id);
    193   EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj));
    194   // A reference is passed to the browser, which we consume here.
    195   host().var_tracker().ReleaseVar(host_pp_var);
    196   EXPECT_EQ(1, host().var_tracker().GetRefCountForObject(host_pp_var));
    197 
    198   // The plugin is going away; generally, so will all references to its instance
    199   // object.
    200   host().var_tracker().ReleaseVar(host_pp_var);
    201   // Destroy the instance. DidDestroy above decrements the reference count for
    202   // instance_obj, so it should also be destroyed.
    203   ppp_instance->DidDestroy(kInstance);
    204   EXPECT_EQ(-1, plugin().var_tracker().GetRefCountForObject(instance_obj));
    205   EXPECT_EQ(-1, host().var_tracker().GetRefCountForObject(host_pp_var));
    206 }
    207 
    208 }  // namespace proxy
    209 }  // namespace ppapi
    210 
    211