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 |