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 "ppapi/proxy/ppb_var_deprecated_proxy.h"
      6 
      7 #include <stdlib.h>  // For malloc
      8 
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "ppapi/c/dev/ppb_var_deprecated.h"
     13 #include "ppapi/c/pp_var.h"
     14 #include "ppapi/c/ppb_core.h"
     15 #include "ppapi/c/ppb_var.h"
     16 #include "ppapi/proxy/host_dispatcher.h"
     17 #include "ppapi/proxy/plugin_dispatcher.h"
     18 #include "ppapi/proxy/plugin_globals.h"
     19 #include "ppapi/proxy/plugin_resource_tracker.h"
     20 #include "ppapi/proxy/plugin_var_tracker.h"
     21 #include "ppapi/proxy/ppapi_messages.h"
     22 #include "ppapi/proxy/ppp_class_proxy.h"
     23 #include "ppapi/proxy/proxy_object_var.h"
     24 #include "ppapi/proxy/serialized_var.h"
     25 #include "ppapi/shared_impl/ppb_var_shared.h"
     26 #include "ppapi/shared_impl/proxy_lock.h"
     27 #include "ppapi/shared_impl/var.h"
     28 
     29 namespace ppapi {
     30 namespace proxy {
     31 
     32 namespace {
     33 
     34 // Used to do get the set-up information for calling a var object. If the
     35 // exception is set, returns NULL. Otherwise, computes the dispatcher for the
     36 // given var object. If the var is not a valid object, returns NULL and sets
     37 // the exception.
     38 PluginDispatcher* CheckExceptionAndGetDispatcher(const PP_Var& object,
     39                                                  PP_Var* exception) {
     40   // If an exception is already set, we don't need to do anything, just return
     41   // an error to the caller.
     42   if (exception && exception->type != PP_VARTYPE_UNDEFINED)
     43     return NULL;
     44 
     45 
     46   if (object.type == PP_VARTYPE_OBJECT) {
     47     // Get the dispatcher for the object.
     48     PluginDispatcher* dispatcher =
     49         PluginGlobals::Get()->plugin_var_tracker()->
     50             DispatcherForPluginObject(object);
     51     if (dispatcher)
     52       return dispatcher;
     53   }
     54 
     55   // The object is invalid. This means we can't figure out which dispatcher
     56   // to use, which is OK because the call will fail anyway. Set the exception.
     57   if (exception) {
     58     *exception = StringVar::StringToPPVar(
     59         std::string("Attempting to use an invalid object"));
     60   }
     61   return NULL;
     62 }
     63 
     64 // PPB_Var_Deprecated plugin ---------------------------------------------------
     65 
     66 bool HasProperty(PP_Var var,
     67                  PP_Var name,
     68                  PP_Var* exception) {
     69   ProxyAutoLock lock;
     70   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
     71   if (!dispatcher)
     72     return false;
     73 
     74   ReceiveSerializedException se(dispatcher, exception);
     75   PP_Bool result = PP_FALSE;
     76   if (!se.IsThrown()) {
     77     dispatcher->Send(new PpapiHostMsg_PPBVar_HasProperty(
     78         API_ID_PPB_VAR_DEPRECATED,
     79         SerializedVarSendInput(dispatcher, var),
     80         SerializedVarSendInput(dispatcher, name), &se, &result));
     81   }
     82   return PP_ToBool(result);
     83 }
     84 
     85 bool HasMethod(PP_Var var,
     86                PP_Var name,
     87                PP_Var* exception) {
     88   ProxyAutoLock lock;
     89   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
     90   if (!dispatcher)
     91     return false;
     92 
     93   ReceiveSerializedException se(dispatcher, exception);
     94   PP_Bool result = PP_FALSE;
     95   if (!se.IsThrown()) {
     96     dispatcher->Send(new PpapiHostMsg_PPBVar_HasMethodDeprecated(
     97         API_ID_PPB_VAR_DEPRECATED,
     98         SerializedVarSendInput(dispatcher, var),
     99         SerializedVarSendInput(dispatcher, name), &se, &result));
    100   }
    101   return PP_ToBool(result);
    102 }
    103 
    104 PP_Var GetProperty(PP_Var var,
    105                    PP_Var name,
    106                    PP_Var* exception) {
    107   ProxyAutoLock lock;
    108   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
    109   if (!dispatcher)
    110     return PP_MakeUndefined();
    111 
    112   ReceiveSerializedException se(dispatcher, exception);
    113   ReceiveSerializedVarReturnValue result;
    114   if (!se.IsThrown()) {
    115     dispatcher->Send(new PpapiHostMsg_PPBVar_GetProperty(
    116         API_ID_PPB_VAR_DEPRECATED,
    117         SerializedVarSendInput(dispatcher, var),
    118         SerializedVarSendInput(dispatcher, name), &se, &result));
    119   }
    120   return result.Return(dispatcher);
    121 }
    122 
    123 void EnumerateProperties(PP_Var var,
    124                          uint32_t* property_count,
    125                          PP_Var** properties,
    126                          PP_Var* exception) {
    127   ProxyAutoLock lock;
    128   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
    129   if (!dispatcher) {
    130     *property_count = 0;
    131     *properties = NULL;
    132     return;
    133   }
    134 
    135   ReceiveSerializedVarVectorOutParam out_vector(dispatcher,
    136                                                 property_count, properties);
    137   ReceiveSerializedException se(dispatcher, exception);
    138   if (!se.IsThrown()) {
    139     dispatcher->Send(new PpapiHostMsg_PPBVar_EnumerateProperties(
    140         API_ID_PPB_VAR_DEPRECATED,
    141         SerializedVarSendInput(dispatcher, var),
    142         out_vector.OutParam(), &se));
    143   }
    144 }
    145 
    146 void SetProperty(PP_Var var,
    147                  PP_Var name,
    148                  PP_Var value,
    149                  PP_Var* exception) {
    150   ProxyAutoLock lock;
    151   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
    152   if (!dispatcher)
    153     return;
    154 
    155   ReceiveSerializedException se(dispatcher, exception);
    156   if (!se.IsThrown()) {
    157     dispatcher->Send(new PpapiHostMsg_PPBVar_SetPropertyDeprecated(
    158         API_ID_PPB_VAR_DEPRECATED,
    159         SerializedVarSendInput(dispatcher, var),
    160         SerializedVarSendInput(dispatcher, name),
    161         SerializedVarSendInput(dispatcher, value), &se));
    162   }
    163 }
    164 
    165 void RemoveProperty(PP_Var var,
    166                     PP_Var name,
    167                     PP_Var* exception) {
    168   ProxyAutoLock lock;
    169   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, exception);
    170   if (!dispatcher)
    171     return;
    172 
    173   ReceiveSerializedException se(dispatcher, exception);
    174   PP_Bool result = PP_FALSE;
    175   if (!se.IsThrown()) {
    176     dispatcher->Send(new PpapiHostMsg_PPBVar_DeleteProperty(
    177         API_ID_PPB_VAR_DEPRECATED,
    178         SerializedVarSendInput(dispatcher, var),
    179         SerializedVarSendInput(dispatcher, name), &se, &result));
    180   }
    181 }
    182 
    183 PP_Var Call(PP_Var object,
    184             PP_Var method_name,
    185             uint32_t argc,
    186             PP_Var* argv,
    187             PP_Var* exception) {
    188   ProxyAutoLock lock;
    189   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(object, exception);
    190   if (!dispatcher)
    191     return PP_MakeUndefined();
    192 
    193   ReceiveSerializedVarReturnValue result;
    194   ReceiveSerializedException se(dispatcher, exception);
    195   if (!se.IsThrown()) {
    196     std::vector<SerializedVar> argv_vect;
    197     SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
    198 
    199     dispatcher->Send(new PpapiHostMsg_PPBVar_CallDeprecated(
    200         API_ID_PPB_VAR_DEPRECATED,
    201         SerializedVarSendInput(dispatcher, object),
    202         SerializedVarSendInput(dispatcher, method_name), argv_vect,
    203         &se, &result));
    204   }
    205   return result.Return(dispatcher);
    206 }
    207 
    208 PP_Var Construct(PP_Var object,
    209                  uint32_t argc,
    210                  PP_Var* argv,
    211                  PP_Var* exception) {
    212   ProxyAutoLock lock;
    213   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(object, exception);
    214   if (!dispatcher)
    215     return PP_MakeUndefined();
    216 
    217   ReceiveSerializedVarReturnValue result;
    218   ReceiveSerializedException se(dispatcher, exception);
    219   if (!se.IsThrown()) {
    220     std::vector<SerializedVar> argv_vect;
    221     SerializedVarSendInput::ConvertVector(dispatcher, argv, argc, &argv_vect);
    222 
    223     dispatcher->Send(new PpapiHostMsg_PPBVar_Construct(
    224         API_ID_PPB_VAR_DEPRECATED,
    225         SerializedVarSendInput(dispatcher, object),
    226         argv_vect, &se, &result));
    227   }
    228   return result.Return(dispatcher);
    229 }
    230 
    231 bool IsInstanceOf(PP_Var var,
    232                   const PPP_Class_Deprecated* ppp_class,
    233                   void** ppp_class_data) {
    234   ProxyAutoLock lock;
    235   Dispatcher* dispatcher = CheckExceptionAndGetDispatcher(var, NULL);
    236   if (!dispatcher)
    237     return false;
    238 
    239   PP_Bool result = PP_FALSE;
    240   int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
    241   int64 class_data_int = 0;
    242   dispatcher->Send(new PpapiHostMsg_PPBVar_IsInstanceOfDeprecated(
    243       API_ID_PPB_VAR_DEPRECATED, SerializedVarSendInput(dispatcher, var),
    244       class_int, &class_data_int, &result));
    245   *ppp_class_data =
    246       reinterpret_cast<void*>(static_cast<intptr_t>(class_data_int));
    247   return PP_ToBool(result);
    248 }
    249 
    250 PP_Var CreateObject(PP_Instance instance,
    251                     const PPP_Class_Deprecated* ppp_class,
    252                     void* ppp_class_data) {
    253   ProxyAutoLock lock;
    254   Dispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
    255   if (!dispatcher)
    256     return PP_MakeUndefined();
    257 
    258   PluginVarTracker* tracker = PluginGlobals::Get()->plugin_var_tracker();
    259   if (tracker->IsPluginImplementedObjectAlive(ppp_class_data))
    260     return PP_MakeUndefined();  // Object already exists with this user data.
    261 
    262   ReceiveSerializedVarReturnValue result;
    263   int64 class_int = static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class));
    264   int64 data_int =
    265       static_cast<int64>(reinterpret_cast<intptr_t>(ppp_class_data));
    266   dispatcher->Send(new PpapiHostMsg_PPBVar_CreateObjectDeprecated(
    267       API_ID_PPB_VAR_DEPRECATED, instance, class_int, data_int,
    268       &result));
    269   PP_Var ret_var = result.Return(dispatcher);
    270 
    271   // Register this object as being implemented by the plugin.
    272   if (ret_var.type == PP_VARTYPE_OBJECT) {
    273     tracker->PluginImplementedObjectCreated(instance, ret_var,
    274                                             ppp_class, ppp_class_data);
    275   }
    276   return ret_var;
    277 }
    278 
    279 InterfaceProxy* CreateVarDeprecatedProxy(Dispatcher* dispatcher) {
    280   return new PPB_Var_Deprecated_Proxy(dispatcher );
    281 }
    282 
    283 }  // namespace
    284 
    285 PPB_Var_Deprecated_Proxy::PPB_Var_Deprecated_Proxy(
    286     Dispatcher* dispatcher)
    287     : InterfaceProxy(dispatcher),
    288       task_factory_(this),
    289       ppb_var_impl_(NULL) {
    290   if (!dispatcher->IsPlugin()) {
    291     ppb_var_impl_ = static_cast<const PPB_Var_Deprecated*>(
    292         dispatcher->local_get_interface()(PPB_VAR_DEPRECATED_INTERFACE));
    293   }
    294 }
    295 
    296 PPB_Var_Deprecated_Proxy::~PPB_Var_Deprecated_Proxy() {
    297 }
    298 
    299 // static
    300 const InterfaceProxy::Info* PPB_Var_Deprecated_Proxy::GetInfo() {
    301   static const PPB_Var_Deprecated var_deprecated_interface = {
    302     ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
    303     ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
    304     ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
    305     ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
    306     &HasProperty,
    307     &HasMethod,
    308     &GetProperty,
    309     &EnumerateProperties,
    310     &SetProperty,
    311     &RemoveProperty,
    312     &Call,
    313     &Construct,
    314     &IsInstanceOf,
    315     &CreateObject
    316   };
    317 
    318   static const Info info = {
    319     &var_deprecated_interface,
    320     PPB_VAR_DEPRECATED_INTERFACE,
    321     API_ID_PPB_VAR_DEPRECATED,
    322     false,
    323     &CreateVarDeprecatedProxy,
    324   };
    325   return &info;
    326 }
    327 
    328 bool PPB_Var_Deprecated_Proxy::OnMessageReceived(const IPC::Message& msg) {
    329   if (!dispatcher()->permissions().HasPermission(PERMISSION_DEV))
    330     return false;
    331 
    332   // Prevent the dispatcher from going away during a call to Call or other
    333   // function that could mutate the DOM. This must happen OUTSIDE of
    334   // the message handlers since the SerializedVars use the dispatcher upon
    335   // return of the function (converting the SerializedVarReturnValue/OutParam
    336   // to a SerializedVar in the destructor).
    337   ScopedModuleReference death_grip(dispatcher());
    338 
    339   bool handled = true;
    340   IPC_BEGIN_MESSAGE_MAP(PPB_Var_Deprecated_Proxy, msg)
    341     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_AddRefObject, OnMsgAddRefObject)
    342     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_ReleaseObject, OnMsgReleaseObject)
    343     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasProperty,
    344                         OnMsgHasProperty)
    345     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_HasMethodDeprecated,
    346                         OnMsgHasMethodDeprecated)
    347     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_GetProperty,
    348                         OnMsgGetProperty)
    349     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_DeleteProperty,
    350                         OnMsgDeleteProperty)
    351     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_EnumerateProperties,
    352                         OnMsgEnumerateProperties)
    353     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_SetPropertyDeprecated,
    354                         OnMsgSetPropertyDeprecated)
    355     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CallDeprecated,
    356                         OnMsgCallDeprecated)
    357     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_Construct,
    358                         OnMsgConstruct)
    359     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_IsInstanceOfDeprecated,
    360                         OnMsgIsInstanceOfDeprecated)
    361     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBVar_CreateObjectDeprecated,
    362                         OnMsgCreateObjectDeprecated)
    363     IPC_MESSAGE_UNHANDLED(handled = false)
    364   IPC_END_MESSAGE_MAP()
    365   // TODO(brettw) handle bad messages!
    366   return handled;
    367 }
    368 
    369 void PPB_Var_Deprecated_Proxy::OnMsgAddRefObject(int64 object_id,
    370                                                  int* /* unused */) {
    371   PP_Var var = { PP_VARTYPE_OBJECT };
    372   var.value.as_id = object_id;
    373   ppb_var_impl_->AddRef(var);
    374 }
    375 
    376 void PPB_Var_Deprecated_Proxy::OnMsgReleaseObject(int64 object_id) {
    377   // Ok, so this is super subtle.
    378   // When the browser side sends a sync IPC message that returns a var, and the
    379   // plugin wants to give ownership of that var to the browser, dropping all
    380   // references, it may call ReleaseObject right after returning the result.
    381   // However, the IPC system doesn't enforce strict ordering of messages in that
    382   // case, where a message that is set to unblock (e.g. a sync message, or in
    383   // our case all messages coming from the plugin) that is sent *after* the
    384   // result may be dispatched on the browser side *before* the sync send
    385   // returned (see ipc_sync_channel.cc). In this case, that means it could
    386   // release the object before it is AddRef'ed on the browser side.
    387   // To work around this, we post a task here, that will not execute before
    388   // control goes back to the main message loop, that will ensure the sync send
    389   // has returned and the browser side can take its reference before we Release.
    390   // Note: if the instance is gone by the time the task is executed, then it
    391   // will Release the objects itself and this Release will be a NOOP (aside of a
    392   // spurious warning).
    393   // TODO(piman): See if we can fix the IPC code to enforce strict ordering, and
    394   // then remove this.
    395   base::MessageLoop::current()->PostNonNestableTask(
    396       FROM_HERE,
    397       RunWhileLocked(base::Bind(&PPB_Var_Deprecated_Proxy::DoReleaseObject,
    398                                 task_factory_.GetWeakPtr(),
    399                                 object_id)));
    400 }
    401 
    402 void PPB_Var_Deprecated_Proxy::OnMsgHasProperty(
    403     SerializedVarReceiveInput var,
    404     SerializedVarReceiveInput name,
    405     SerializedVarOutParam exception,
    406     PP_Bool* result) {
    407   SetAllowPluginReentrancy();
    408   *result = PP_FromBool(ppb_var_impl_->HasProperty(
    409       var.Get(dispatcher()),
    410       name.Get(dispatcher()),
    411       exception.OutParam(dispatcher())));
    412 }
    413 
    414 void PPB_Var_Deprecated_Proxy::OnMsgHasMethodDeprecated(
    415     SerializedVarReceiveInput var,
    416     SerializedVarReceiveInput name,
    417     SerializedVarOutParam exception,
    418     PP_Bool* result) {
    419   SetAllowPluginReentrancy();
    420   *result = PP_FromBool(ppb_var_impl_->HasMethod(
    421       var.Get(dispatcher()),
    422       name.Get(dispatcher()),
    423       exception.OutParam(dispatcher())));
    424 }
    425 
    426 void PPB_Var_Deprecated_Proxy::OnMsgGetProperty(
    427     SerializedVarReceiveInput var,
    428     SerializedVarReceiveInput name,
    429     SerializedVarOutParam exception,
    430     SerializedVarReturnValue result) {
    431   SetAllowPluginReentrancy();
    432   result.Return(dispatcher(), ppb_var_impl_->GetProperty(
    433       var.Get(dispatcher()), name.Get(dispatcher()),
    434       exception.OutParam(dispatcher())));
    435 }
    436 
    437 void PPB_Var_Deprecated_Proxy::OnMsgEnumerateProperties(
    438     SerializedVarReceiveInput var,
    439     SerializedVarVectorOutParam props,
    440     SerializedVarOutParam exception) {
    441   SetAllowPluginReentrancy();
    442   ppb_var_impl_->GetAllPropertyNames(var.Get(dispatcher()),
    443       props.CountOutParam(), props.ArrayOutParam(dispatcher()),
    444       exception.OutParam(dispatcher()));
    445 }
    446 
    447 void PPB_Var_Deprecated_Proxy::OnMsgSetPropertyDeprecated(
    448     SerializedVarReceiveInput var,
    449     SerializedVarReceiveInput name,
    450     SerializedVarReceiveInput value,
    451     SerializedVarOutParam exception) {
    452   SetAllowPluginReentrancy();
    453   ppb_var_impl_->SetProperty(var.Get(dispatcher()),
    454                                 name.Get(dispatcher()),
    455                                 value.Get(dispatcher()),
    456                                 exception.OutParam(dispatcher()));
    457 }
    458 
    459 void PPB_Var_Deprecated_Proxy::OnMsgDeleteProperty(
    460     SerializedVarReceiveInput var,
    461     SerializedVarReceiveInput name,
    462     SerializedVarOutParam exception,
    463     PP_Bool* result) {
    464   SetAllowPluginReentrancy();
    465   ppb_var_impl_->RemoveProperty(var.Get(dispatcher()),
    466                                    name.Get(dispatcher()),
    467                                    exception.OutParam(dispatcher()));
    468   // This deprecated function doesn't actually return a value, but we re-use
    469   // the message from the non-deprecated interface with the return value.
    470   *result = PP_TRUE;
    471 }
    472 
    473 void PPB_Var_Deprecated_Proxy::OnMsgCallDeprecated(
    474     SerializedVarReceiveInput object,
    475     SerializedVarReceiveInput method_name,
    476     SerializedVarVectorReceiveInput arg_vector,
    477     SerializedVarOutParam exception,
    478     SerializedVarReturnValue result) {
    479   SetAllowPluginReentrancy();
    480   uint32_t arg_count = 0;
    481   PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
    482   result.Return(dispatcher(), ppb_var_impl_->Call(
    483       object.Get(dispatcher()),
    484       method_name.Get(dispatcher()),
    485       arg_count, args,
    486       exception.OutParam(dispatcher())));
    487 }
    488 
    489 void PPB_Var_Deprecated_Proxy::OnMsgConstruct(
    490     SerializedVarReceiveInput var,
    491     SerializedVarVectorReceiveInput arg_vector,
    492     SerializedVarOutParam exception,
    493     SerializedVarReturnValue result) {
    494   SetAllowPluginReentrancy();
    495   uint32_t arg_count = 0;
    496   PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
    497   result.Return(dispatcher(), ppb_var_impl_->Construct(
    498       var.Get(dispatcher()), arg_count, args,
    499       exception.OutParam(dispatcher())));
    500 }
    501 
    502 void PPB_Var_Deprecated_Proxy::OnMsgIsInstanceOfDeprecated(
    503     SerializedVarReceiveInput var,
    504     int64 ppp_class,
    505     int64* ppp_class_data,
    506     PP_Bool* result) {
    507   SetAllowPluginReentrancy();
    508   *result = PPP_Class_Proxy::IsInstanceOf(ppb_var_impl_,
    509                                           var.Get(dispatcher()),
    510                                           ppp_class,
    511                                           ppp_class_data);
    512 }
    513 
    514 void PPB_Var_Deprecated_Proxy::OnMsgCreateObjectDeprecated(
    515     PP_Instance instance,
    516     int64 ppp_class,
    517     int64 class_data,
    518     SerializedVarReturnValue result) {
    519   SetAllowPluginReentrancy();
    520   result.Return(dispatcher(), PPP_Class_Proxy::CreateProxiedObject(
    521       ppb_var_impl_, dispatcher(), instance, ppp_class, class_data));
    522 }
    523 
    524 void PPB_Var_Deprecated_Proxy::SetAllowPluginReentrancy() {
    525   if (dispatcher()->IsPlugin())
    526     NOTREACHED();
    527   else
    528     static_cast<HostDispatcher*>(dispatcher())->set_allow_plugin_reentrancy();
    529 }
    530 
    531 void PPB_Var_Deprecated_Proxy::DoReleaseObject(int64 object_id) {
    532   PP_Var var = { PP_VARTYPE_OBJECT };
    533   var.value.as_id = object_id;
    534   ppb_var_impl_->Release(var);
    535 }
    536 
    537 }  // namespace proxy
    538 }  // namespace ppapi
    539