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/plugin_var_serialization_rules.h" 6 7#include "base/logging.h" 8#include "ppapi/proxy/plugin_dispatcher.h" 9#include "ppapi/proxy/plugin_globals.h" 10#include "ppapi/proxy/plugin_resource_tracker.h" 11#include "ppapi/proxy/plugin_var_tracker.h" 12#include "ppapi/shared_impl/ppapi_globals.h" 13#include "ppapi/shared_impl/var.h" 14 15namespace ppapi { 16namespace proxy { 17 18PluginVarSerializationRules::PluginVarSerializationRules( 19 const base::WeakPtr<PluginDispatcher>& dispatcher) 20 : var_tracker_(PluginGlobals::Get()->plugin_var_tracker()), 21 dispatcher_(dispatcher) { 22} 23 24PluginVarSerializationRules::~PluginVarSerializationRules() { 25} 26 27PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var) { 28 // Objects need special translations to get the IDs valid in the host. 29 if (var.type == PP_VARTYPE_OBJECT) 30 return var_tracker_->GetHostObject(var); 31 return var; 32} 33 34PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned(const PP_Var& var) { 35 if (var.type == PP_VARTYPE_OBJECT) { 36 return dispatcher_.get() ? var_tracker_->TrackObjectWithNoReference( 37 var, dispatcher_.get()) 38 : PP_MakeUndefined(); 39 } 40 41 return var; 42} 43 44void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { 45 if (var.type == PP_VARTYPE_OBJECT) { 46 var_tracker_->StopTrackingObjectWithNoReference(var); 47 } else if (var.type >= PP_VARTYPE_STRING) { 48 // Release our reference to the local Var. 49 var_tracker_->ReleaseVar(var); 50 } 51} 52 53PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var) { 54 // Overview of sending an object with "pass ref" from the browser to the 55 // plugin: 56 // Example 1 Example 2 57 // Plugin Browser Plugin Browser 58 // Before send 3 2 0 1 59 // Browser calls BeginSendPassRef 3 2 0 1 60 // Plugin calls ReceivePassRef 4 1 1 1 61 // Browser calls EndSendPassRef 4 1 1 1 62 // 63 // In example 1 before the send, the plugin has 3 refs which are represented 64 // as one ref in the browser (since the plugin only tells the browser when 65 // it's refcount goes from 1 -> 0). The initial state is that the browser 66 // plugin code started to return a value, which means it gets another ref 67 // on behalf of the caller. This needs to be transferred to the plugin and 68 // folded in to its set of refs it maintains (with one ref representing all 69 // of them in the browser). 70 if (var.type == PP_VARTYPE_OBJECT) { 71 return dispatcher_.get() 72 ? var_tracker_->ReceiveObjectPassRef(var, dispatcher_.get()) 73 : PP_MakeUndefined(); 74 } 75 76 // Other types are unchanged. 77 return var; 78} 79 80PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var) { 81 // Overview of sending an object with "pass ref" from the plugin to the 82 // browser: 83 // Example 1 Example 2 84 // Plugin Browser Plugin Browser 85 // Before send 3 1 1 1 86 // Plugin calls BeginSendPassRef 3 1 1 1 87 // Browser calls ReceivePassRef 3 2 1 2 88 // Plugin calls EndSendPassRef 2 2 0 1 89 // 90 // The plugin maintains one ref count in the browser on behalf of the 91 // entire ref count in the plugin. When the plugin refcount goes to 0, it 92 // will call the browser to deref the object. This is why in example 2 93 // transferring the object ref to the browser involves no net change in the 94 // browser's refcount. 95 96 // Objects need special translations to get the IDs valid in the host. 97 if (var.type == PP_VARTYPE_OBJECT) 98 return var_tracker_->GetHostObject(var); 99 return var; 100} 101 102void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var) { 103 // See BeginSendPassRef for an example of why we release our ref here. 104 // The var we have in our inner class has been converted to a host object 105 // by BeginSendPassRef. This means it's not a normal var valid in the plugin, 106 // so we need to use the special ReleaseHostObject. 107 if (var.type == PP_VARTYPE_OBJECT) { 108 if (dispatcher_.get()) 109 var_tracker_->ReleaseHostObject(dispatcher_.get(), var); 110 } else if (var.type >= PP_VARTYPE_STRING) { 111 var_tracker_->ReleaseVar(var); 112 } 113} 114 115void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { 116 var_tracker_->ReleaseVar(var); 117} 118 119} // namespace proxy 120} // namespace ppapi 121