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 15 namespace ppapi { 16 namespace proxy { 17 18 PluginVarSerializationRules::PluginVarSerializationRules( 19 const base::WeakPtr<PluginDispatcher>& dispatcher) 20 : var_tracker_(PluginGlobals::Get()->plugin_var_tracker()), 21 dispatcher_(dispatcher) { 22 } 23 24 PluginVarSerializationRules::~PluginVarSerializationRules() { 25 } 26 27 PP_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 34 PP_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 44 void 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 53 PP_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 80 PP_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 102 void 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 115 void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { 116 var_tracker_->ReleaseVar(var); 117 } 118 119 } // namespace proxy 120 } // namespace ppapi 121