| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/proxy/plugin_var_serialization_rules.h" | 5 #include "ppapi/proxy/plugin_var_serialization_rules.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "ppapi/proxy/plugin_dispatcher.h" | 8 #include "ppapi/proxy/plugin_dispatcher.h" |
| 9 #include "ppapi/proxy/plugin_globals.h" | 9 #include "ppapi/proxy/plugin_globals.h" |
| 10 #include "ppapi/proxy/plugin_resource_tracker.h" | 10 #include "ppapi/proxy/plugin_resource_tracker.h" |
| 11 #include "ppapi/proxy/plugin_var_tracker.h" | 11 #include "ppapi/proxy/plugin_var_tracker.h" |
| 12 #include "ppapi/shared_impl/ppapi_globals.h" | 12 #include "ppapi/shared_impl/ppapi_globals.h" |
| 13 #include "ppapi/shared_impl/var.h" | 13 #include "ppapi/shared_impl/var.h" |
| 14 | 14 |
| 15 namespace ppapi { | 15 namespace ppapi { |
| 16 namespace proxy { | 16 namespace proxy { |
| 17 | 17 |
| 18 PluginVarSerializationRules::PluginVarSerializationRules() | 18 PluginVarSerializationRules::PluginVarSerializationRules() |
| 19 : var_tracker_(PluginGlobals::Get()->plugin_var_tracker()) { | 19 : var_tracker_(PluginGlobals::Get()->plugin_var_tracker()) { |
| 20 } | 20 } |
| 21 | 21 |
| 22 PluginVarSerializationRules::~PluginVarSerializationRules() { | 22 PluginVarSerializationRules::~PluginVarSerializationRules() { |
| 23 } | 23 } |
| 24 | 24 |
| 25 PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var, | 25 PP_Var PluginVarSerializationRules::SendCallerOwned( |
| 26 std::string* str_val) { | 26 const PP_Var& var, |
| 27 const std::string** str_ptr_out) { |
| 27 // Objects need special translations to get the IDs valid in the host. | 28 // Objects need special translations to get the IDs valid in the host. |
| 28 if (var.type == PP_VARTYPE_OBJECT) | 29 if (var.type == PP_VARTYPE_OBJECT) |
| 29 return var_tracker_->GetHostObject(var); | 30 return var_tracker_->GetHostObject(var); |
| 30 | 31 |
| 31 // Retrieve the string to use for IPC. | 32 // Retrieve the pointer to the string in the tracker in order to send the |
| 33 // string over IPC without unnecessary copies. |
| 32 if (var.type == PP_VARTYPE_STRING) { | 34 if (var.type == PP_VARTYPE_STRING) { |
| 33 StringVar* string_var = StringVar::FromPPVar(var); | 35 StringVar* string_var = StringVar::FromPPVar(var); |
| 34 if (string_var) | 36 if (string_var) |
| 35 *str_val = string_var->value(); | 37 *str_ptr_out = string_var->ptr(); |
| 36 else | 38 else |
| 37 NOTREACHED() << "Trying to send unknown string over IPC."; | 39 NOTREACHED() << "Trying to send unknown string over IPC."; |
| 38 } | 40 } |
| 39 return var; | 41 return var; |
| 40 } | 42 } |
| 41 | 43 |
| 42 PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned( | 44 PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned( |
| 43 const PP_Var& var, | 45 const PP_Var& var, |
| 44 const std::string* str_val, | 46 scoped_ptr<std::string> str, |
| 45 Dispatcher* dispatcher) { | 47 Dispatcher* dispatcher) { |
| 46 if (var.type == PP_VARTYPE_STRING) | 48 if (var.type == PP_VARTYPE_STRING) |
| 47 return StringVar::StringToPPVar(*str_val); | 49 return StringVar::StringToPPVar(str.Pass()); |
| 48 | 50 |
| 49 if (var.type == PP_VARTYPE_OBJECT) { | 51 if (var.type == PP_VARTYPE_OBJECT) { |
| 50 DCHECK(dispatcher->IsPlugin()); | 52 DCHECK(dispatcher->IsPlugin()); |
| 51 return var_tracker_->TrackObjectWithNoReference( | 53 return var_tracker_->TrackObjectWithNoReference( |
| 52 var, static_cast<PluginDispatcher*>(dispatcher)); | 54 var, static_cast<PluginDispatcher*>(dispatcher)); |
| 53 } | 55 } |
| 54 | 56 |
| 55 return var; | 57 return var; |
| 56 } | 58 } |
| 57 | 59 |
| 58 void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { | 60 void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { |
| 59 if (var.type == PP_VARTYPE_STRING) { | 61 if (var.type == PP_VARTYPE_STRING) { |
| 60 // Destroy the string BeginReceiveCallerOwned created above. | 62 // Destroy the string BeginReceiveCallerOwned created above. |
| 61 var_tracker_->ReleaseVar(var); | 63 var_tracker_->ReleaseVar(var); |
| 62 } else if (var.type == PP_VARTYPE_OBJECT) { | 64 } else if (var.type == PP_VARTYPE_OBJECT) { |
| 63 var_tracker_->StopTrackingObjectWithNoReference(var); | 65 var_tracker_->StopTrackingObjectWithNoReference(var); |
| 64 } | 66 } |
| 65 } | 67 } |
| 66 | 68 |
| 67 PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var, | 69 PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var, |
| 68 const std::string& str_val, | 70 scoped_ptr<std::string> str, |
| 69 Dispatcher* dispatcher) { | 71 Dispatcher* dispatcher) { |
| 70 if (var.type == PP_VARTYPE_STRING) | 72 if (var.type == PP_VARTYPE_STRING) |
| 71 return StringVar::StringToPPVar(str_val); | 73 return StringVar::StringToPPVar(str.Pass()); |
| 72 | 74 |
| 73 // Overview of sending an object with "pass ref" from the browser to the | 75 // Overview of sending an object with "pass ref" from the browser to the |
| 74 // plugin: | 76 // plugin: |
| 75 // Example 1 Example 2 | 77 // Example 1 Example 2 |
| 76 // Plugin Browser Plugin Browser | 78 // Plugin Browser Plugin Browser |
| 77 // Before send 3 2 0 1 | 79 // Before send 3 2 0 1 |
| 78 // Browser calls BeginSendPassRef 3 2 0 1 | 80 // Browser calls BeginSendPassRef 3 2 0 1 |
| 79 // Plugin calls ReceivePassRef 4 1 1 1 | 81 // Plugin calls ReceivePassRef 4 1 1 1 |
| 80 // Browser calls EndSendPassRef 4 1 1 1 | 82 // Browser calls EndSendPassRef 4 1 1 1 |
| 81 // | 83 // |
| 82 // In example 1 before the send, the plugin has 3 refs which are represented | 84 // In example 1 before the send, the plugin has 3 refs which are represented |
| 83 // as one ref in the browser (since the plugin only tells the browser when | 85 // as one ref in the browser (since the plugin only tells the browser when |
| 84 // it's refcount goes from 1 -> 0). The initial state is that the browser | 86 // it's refcount goes from 1 -> 0). The initial state is that the browser |
| 85 // plugin code started to return a value, which means it gets another ref | 87 // plugin code started to return a value, which means it gets another ref |
| 86 // on behalf of the caller. This needs to be transferred to the plugin and | 88 // on behalf of the caller. This needs to be transferred to the plugin and |
| 87 // folded in to its set of refs it maintains (with one ref representing all | 89 // folded in to its set of refs it maintains (with one ref representing all |
| 88 // of them in the browser). | 90 // of them in the browser). |
| 89 if (var.type == PP_VARTYPE_OBJECT) { | 91 if (var.type == PP_VARTYPE_OBJECT) { |
| 90 DCHECK(dispatcher->IsPlugin()); | 92 DCHECK(dispatcher->IsPlugin()); |
| 91 return var_tracker_->ReceiveObjectPassRef( | 93 return var_tracker_->ReceiveObjectPassRef( |
| 92 var, static_cast<PluginDispatcher*>(dispatcher)); | 94 var, static_cast<PluginDispatcher*>(dispatcher)); |
| 93 } | 95 } |
| 94 | 96 |
| 95 // Other types are unchanged. | 97 // Other types are unchanged. |
| 96 return var; | 98 return var; |
| 97 } | 99 } |
| 98 | 100 |
| 99 PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var, | 101 PP_Var PluginVarSerializationRules::BeginSendPassRef( |
| 100 std::string* str_val) { | 102 const PP_Var& var, |
| 103 const std::string** str_ptr_out) { |
| 101 // Overview of sending an object with "pass ref" from the plugin to the | 104 // Overview of sending an object with "pass ref" from the plugin to the |
| 102 // browser: | 105 // browser: |
| 103 // Example 1 Example 2 | 106 // Example 1 Example 2 |
| 104 // Plugin Browser Plugin Browser | 107 // Plugin Browser Plugin Browser |
| 105 // Before send 3 1 1 1 | 108 // Before send 3 1 1 1 |
| 106 // Plugin calls BeginSendPassRef 3 1 1 1 | 109 // Plugin calls BeginSendPassRef 3 1 1 1 |
| 107 // Browser calls ReceivePassRef 3 2 1 2 | 110 // Browser calls ReceivePassRef 3 2 1 2 |
| 108 // Plugin calls EndSendPassRef 2 2 0 1 | 111 // Plugin calls EndSendPassRef 2 2 0 1 |
| 109 // | 112 // |
| 110 // The plugin maintains one ref count in the browser on behalf of the | 113 // The plugin maintains one ref count in the browser on behalf of the |
| 111 // entire ref count in the plugin. When the plugin refcount goes to 0, it | 114 // entire ref count in the plugin. When the plugin refcount goes to 0, it |
| 112 // will call the browser to deref the object. This is why in example 2 | 115 // will call the browser to deref the object. This is why in example 2 |
| 113 // transferring the object ref to the browser involves no net change in the | 116 // transferring the object ref to the browser involves no net change in the |
| 114 // browser's refcount. | 117 // browser's refcount. |
| 115 | 118 |
| 116 // Objects need special translations to get the IDs valid in the host. | 119 // Objects need special translations to get the IDs valid in the host. |
| 117 if (var.type == PP_VARTYPE_OBJECT) | 120 if (var.type == PP_VARTYPE_OBJECT) |
| 118 return var_tracker_->GetHostObject(var); | 121 return var_tracker_->GetHostObject(var); |
| 119 | 122 |
| 120 if (var.type == PP_VARTYPE_STRING) { | 123 if (var.type == PP_VARTYPE_STRING) { |
| 124 // Get the pointer to the string that's in the tracker and return it, so we |
| 125 // can avoid an extra copy of the string when serializing over IPC. |
| 121 StringVar* string_var = StringVar::FromPPVar(var); | 126 StringVar* string_var = StringVar::FromPPVar(var); |
| 122 if (string_var) | 127 if (string_var) |
| 123 *str_val = string_var->value(); | 128 *str_ptr_out = string_var->ptr(); |
| 124 else | 129 else |
| 125 NOTREACHED() << "Trying to send unknown string over IPC."; | 130 NOTREACHED() << "Trying to send unknown string over IPC."; |
| 126 } | 131 } |
| 127 return var; | 132 return var; |
| 128 } | 133 } |
| 129 | 134 |
| 130 void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var, | 135 void PluginVarSerializationRules::EndSendPassRef(const PP_Var& var, |
| 131 Dispatcher* dispatcher) { | 136 Dispatcher* dispatcher) { |
| 132 // See BeginSendPassRef for an example of why we release our ref here. | 137 // See BeginSendPassRef for an example of why we release our ref here. |
| 133 // The var we have in our inner class has been converted to a host object | 138 // The var we have in our inner class has been converted to a host object |
| 134 // by BeginSendPassRef. This means it's not a normal var valid in the plugin, | 139 // by BeginSendPassRef. This means it's not a normal var valid in the plugin, |
| 135 // so we need to use the special ReleaseHostObject. | 140 // so we need to use the special ReleaseHostObject. |
| 136 if (var.type == PP_VARTYPE_OBJECT) { | 141 if (var.type == PP_VARTYPE_OBJECT) { |
| 137 var_tracker_->ReleaseHostObject( | 142 var_tracker_->ReleaseHostObject( |
| 138 static_cast<PluginDispatcher*>(dispatcher), var); | 143 static_cast<PluginDispatcher*>(dispatcher), var); |
| 139 } else if (var.type == PP_VARTYPE_STRING) { | 144 } else if (var.type == PP_VARTYPE_STRING) { |
| 140 var_tracker_->ReleaseVar(var); | 145 var_tracker_->ReleaseVar(var); |
| 141 } | 146 } |
| 142 } | 147 } |
| 143 | 148 |
| 144 void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { | 149 void PluginVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { |
| 145 var_tracker_->ReleaseVar(var); | 150 var_tracker_->ReleaseVar(var); |
| 146 } | 151 } |
| 147 | 152 |
| 148 } // namespace proxy | 153 } // namespace proxy |
| 149 } // namespace ppapi | 154 } // namespace ppapi |
| OLD | NEW |