OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_tracker.h" | 5 #include "ppapi/proxy/plugin_var_tracker.h" |
6 | 6 |
7 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
9 #include "ppapi/c/ppb_var.h" | 9 #include "ppapi/c/ppb_var.h" |
10 #include "ppapi/proxy/plugin_dispatcher.h" | 10 #include "ppapi/proxy/plugin_dispatcher.h" |
11 #include "ppapi/proxy/ppapi_messages.h" | 11 #include "ppapi/proxy/ppapi_messages.h" |
12 #include "ppapi/proxy/interface_id.h" | 12 #include "ppapi/proxy/interface_id.h" |
| 13 #include "ppapi/proxy/proxy_object_var.h" |
| 14 #include "ppapi/shared_impl/var.h" |
| 15 |
| 16 using ppapi::ProxyObjectVar; |
| 17 using ppapi::Var; |
13 | 18 |
14 namespace pp { | 19 namespace pp { |
15 namespace proxy { | 20 namespace proxy { |
16 | 21 |
17 namespace { | 22 PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, int32 i) |
18 | |
19 // When non-NULL, this object overrides the VarTrackerSingleton. | |
20 PluginVarTracker* var_tracker_override = NULL; | |
21 | |
22 } // namespace | |
23 | |
24 PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i) | |
25 : dispatcher(d), | 23 : dispatcher(d), |
26 host_object_id(i) { | 24 host_object_id(i) { |
27 } | 25 } |
28 | 26 |
29 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const { | 27 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const { |
30 if (dispatcher < other.dispatcher) | 28 if (dispatcher < other.dispatcher) |
31 return true; | 29 return true; |
32 if (other.dispatcher < dispatcher) | 30 if (other.dispatcher < dispatcher) |
33 return false; | 31 return false; |
34 return host_object_id < other.host_object_id; | 32 return host_object_id < other.host_object_id; |
35 } | 33 } |
36 | 34 |
37 PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var) | 35 PluginVarTracker::PluginVarTracker() { |
38 : host_var(host_var), | |
39 ref_count(0), | |
40 track_with_no_reference_count(0) { | |
41 } | |
42 | |
43 PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) { | |
44 } | 36 } |
45 | 37 |
46 PluginVarTracker::~PluginVarTracker() { | 38 PluginVarTracker::~PluginVarTracker() { |
47 } | 39 } |
48 | 40 |
49 // static | 41 PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& host_var, |
50 void PluginVarTracker::SetInstanceForTest(PluginVarTracker* tracker) { | 42 PluginDispatcher* dispatcher) { |
51 var_tracker_override = tracker; | 43 DCHECK(host_var.type == PP_VARTYPE_OBJECT); |
52 } | |
53 | 44 |
54 // static | 45 // Get the object. |
55 PluginVarTracker* PluginVarTracker::GetInstance() { | 46 scoped_refptr<ProxyObjectVar> object( |
56 if (var_tracker_override) | 47 FindOrMakePluginVarFromHostVar(host_var, dispatcher)); |
57 return var_tracker_override; | |
58 return Singleton<PluginVarTracker>::get(); | |
59 } | |
60 | 48 |
61 PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) { | 49 // Actually create the PP_Var, this will add all the tracking info but not |
62 return MakeString(str.c_str(), str.length()); | 50 // adjust any refcounts. |
63 } | 51 PP_Var ret = GetOrCreateObjectVarID(object.get()); |
64 | 52 |
65 PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str, | 53 VarInfo& info = GetLiveVar(ret)->second; |
66 uint32_t len) { | 54 if (info.ref_count > 0) { |
67 std::pair<VarIDStringMap::iterator, bool> | 55 // We already had a reference to it before. That means the renderer now has |
68 iter_success_pair(var_id_to_string_.end(), false); | 56 // two references on our behalf. We want to transfer that extra reference |
69 VarID new_id(0); | 57 // to our list. This means we addref in the plugin, and release the extra |
70 RefCountedStringPtr str_ptr(new RefCountedString(str, len)); | 58 // one in the renderer. |
71 // Pick new IDs until one is successfully inserted. This loop is very unlikely | 59 SendReleaseObjectMsg(*object); |
72 // to ever run a 2nd time, since we have ~2^63 possible IDs to exhaust. | |
73 while (!iter_success_pair.second) { | |
74 new_id = GetNewVarID(); | |
75 iter_success_pair = | |
76 var_id_to_string_.insert(VarIDStringMap::value_type(new_id, str_ptr)); | |
77 } | 60 } |
78 // Release the local pointer. | 61 info.ref_count++; |
79 str_ptr = NULL; | |
80 // Now the map should have the only reference. | |
81 DCHECK(iter_success_pair.first->second->HasOneRef()); | |
82 iter_success_pair.first->second->AddRef(); | |
83 return new_id; | |
84 } | |
85 | |
86 const std::string* PluginVarTracker::GetExistingString( | |
87 const PP_Var& var) const { | |
88 if (var.type != PP_VARTYPE_STRING) | |
89 return NULL; | |
90 VarIDStringMap::const_iterator found = | |
91 var_id_to_string_.find(var.value.as_id); | |
92 if (found != var_id_to_string_.end()) | |
93 return &found->second->value(); | |
94 return NULL; | |
95 } | |
96 | |
97 void PluginVarTracker::AddRef(const PP_Var& var) { | |
98 if (var.type == PP_VARTYPE_STRING) { | |
99 VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id); | |
100 if (found == var_id_to_string_.end()) { | |
101 NOTREACHED() << "Requesting to addref an unknown string."; | |
102 return; | |
103 } | |
104 found->second->AddRef(); | |
105 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) { | |
106 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id); | |
107 if (found == plugin_var_info_.end()) { | |
108 NOTREACHED() << "Requesting to addref an unknown object."; | |
109 return; | |
110 } | |
111 | |
112 PluginVarInfo& info = found->second; | |
113 if (info.ref_count == 0) { | |
114 // Got an AddRef for an object we have no existing reference for. | |
115 // We need to tell the browser we've taken a ref. This comes up when the | |
116 // browser passes an object as an input param and holds a ref for us. | |
117 // This must be a sync message since otherwise the "addref" will actually | |
118 // occur after the return to the browser of the sync function that | |
119 // presumably sent the object. | |
120 SendAddRefObjectMsg(info.host_var); | |
121 } | |
122 info.ref_count++; | |
123 } | |
124 } | |
125 | |
126 void PluginVarTracker::Release(const PP_Var& var) { | |
127 if (var.type == PP_VARTYPE_STRING) { | |
128 VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id); | |
129 if (found == var_id_to_string_.end()) { | |
130 NOTREACHED() << "Requesting to release an unknown string."; | |
131 return; | |
132 } | |
133 found->second->Release(); | |
134 // If there is only 1 reference left, it's the map's reference. Erase it | |
135 // from the map, which will delete the string. | |
136 if (found->second->HasOneRef()) | |
137 var_id_to_string_.erase(found); | |
138 } else if (var.type == PP_VARTYPE_OBJECT) { | |
139 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id); | |
140 if (found == plugin_var_info_.end()) { | |
141 NOTREACHED() << "Requesting to release an unknown object."; | |
142 return; | |
143 } | |
144 | |
145 PluginVarInfo& info = found->second; | |
146 if (info.ref_count == 0) { | |
147 NOTREACHED() << "Releasing an object with zero ref."; | |
148 return; | |
149 } | |
150 | |
151 info.ref_count--; | |
152 if (info.ref_count == 0) | |
153 SendReleaseObjectMsg(info.host_var); | |
154 DeletePluginVarInfoIfNecessary(found); | |
155 } | |
156 } | |
157 | |
158 PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var, | |
159 PluginDispatcher* dispatcher) { | |
160 DCHECK(var.type == PP_VARTYPE_OBJECT); | |
161 | |
162 // Find the plugin info. | |
163 PluginVarInfoMap::iterator found = | |
164 FindOrMakePluginVarFromHostVar(var, dispatcher); | |
165 if (found == plugin_var_info_.end()) { | |
166 // The above code should have always made an entry in the map. | |
167 NOTREACHED(); | |
168 return PP_MakeUndefined(); | |
169 } | |
170 | |
171 // Fix up the references. The host (renderer) just sent us a ref. The | |
172 // renderer has addrefed the var in its tracker for us since it's returning | |
173 // it. | |
174 PluginVarInfo& info = found->second; | |
175 if (info.ref_count == 0) { | |
176 // We don't have a reference to this already, then we just add it to our | |
177 // tracker and use that one ref. | |
178 info.ref_count = 1; | |
179 } else { | |
180 // We already have a reference to it, that means the renderer now has two | |
181 // references on our behalf. We want to transfer that extra reference to | |
182 // our list. This means we addref in the plugin, and release the extra one | |
183 // in the renderer. | |
184 SendReleaseObjectMsg(info.host_var); | |
185 info.ref_count++; | |
186 } | |
187 | |
188 PP_Var ret; | |
189 ret.type = PP_VARTYPE_OBJECT; | |
190 ret.value.as_id = found->first; | |
191 return ret; | 62 return ret; |
192 } | 63 } |
193 | 64 |
194 PP_Var PluginVarTracker::TrackObjectWithNoReference( | 65 PP_Var PluginVarTracker::TrackObjectWithNoReference( |
195 const PP_Var& host_var, | 66 const PP_Var& host_var, |
196 PluginDispatcher* dispatcher) { | 67 PluginDispatcher* dispatcher) { |
197 DCHECK(host_var.type == PP_VARTYPE_OBJECT); | 68 DCHECK(host_var.type == PP_VARTYPE_OBJECT); |
198 | 69 |
199 PluginVarInfoMap::iterator found = | 70 // Get the object. |
200 FindOrMakePluginVarFromHostVar(host_var, dispatcher); | 71 scoped_refptr<ProxyObjectVar> object( |
201 if (found == plugin_var_info_.end()) { | 72 FindOrMakePluginVarFromHostVar(host_var, dispatcher)); |
202 // The above code should have always made an entry in the map. | |
203 NOTREACHED(); | |
204 return PP_MakeUndefined(); | |
205 } | |
206 | 73 |
207 found->second.track_with_no_reference_count++; | 74 // Actually create the PP_Var, this will add all the tracking info but not |
| 75 // adjust any refcounts. |
| 76 PP_Var ret = GetOrCreateObjectVarID(object.get()); |
208 | 77 |
209 PP_Var ret; | 78 VarInfo& info = GetLiveVar(ret)->second; |
210 ret.type = PP_VARTYPE_OBJECT; | 79 info.track_with_no_reference_count++; |
211 ret.value.as_id = found->first; | |
212 return ret; | 80 return ret; |
213 } | 81 } |
214 | 82 |
215 void PluginVarTracker::StopTrackingObjectWithNoReference( | 83 void PluginVarTracker::StopTrackingObjectWithNoReference( |
216 const PP_Var& plugin_var) { | 84 const PP_Var& plugin_var) { |
217 DCHECK(plugin_var.type == PP_VARTYPE_OBJECT); | 85 DCHECK(plugin_var.type == PP_VARTYPE_OBJECT); |
218 PluginVarInfoMap::iterator found = plugin_var_info_.find( | 86 VarMap::iterator found = GetLiveVar(plugin_var); |
219 plugin_var.value.as_id); | 87 if (found == live_vars_.end()) { |
220 if (found == plugin_var_info_.end()) { | |
221 NOTREACHED(); | 88 NOTREACHED(); |
222 return; | 89 return; |
223 } | 90 } |
224 | 91 |
| 92 DCHECK(found->second.track_with_no_reference_count > 0); |
225 found->second.track_with_no_reference_count--; | 93 found->second.track_with_no_reference_count--; |
226 DeletePluginVarInfoIfNecessary(found); | 94 DeleteObjectInfoIfNecessary(found); |
227 } | 95 } |
228 | 96 |
229 PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const { | 97 PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const { |
230 DCHECK(plugin_object.type == PP_VARTYPE_OBJECT); | 98 if (plugin_object.type != PP_VARTYPE_OBJECT) { |
231 PluginVarInfoMap::const_iterator found = plugin_var_info_.find( | |
232 plugin_object.value.as_id); | |
233 if (found == plugin_var_info_.end()) { | |
234 NOTREACHED(); | 99 NOTREACHED(); |
235 return PP_MakeUndefined(); | 100 return PP_MakeUndefined(); |
236 } | 101 } |
| 102 |
| 103 Var* var = GetVar(plugin_object); |
| 104 ProxyObjectVar* object = var->AsProxyObjectVar(); |
| 105 if (!object) { |
| 106 NOTREACHED(); |
| 107 return PP_MakeUndefined(); |
| 108 } |
| 109 |
| 110 // Make a var with the host ID. |
237 PP_Var ret; | 111 PP_Var ret; |
238 ret.type = PP_VARTYPE_OBJECT; | 112 ret.type = PP_VARTYPE_OBJECT; |
239 ret.value.as_id = found->second.host_var.host_object_id; | 113 ret.value.as_id = object->host_var_id(); |
240 return ret; | 114 return ret; |
241 } | 115 } |
242 | 116 |
243 PluginDispatcher* PluginVarTracker::DispatcherForPluginObject( | 117 PluginDispatcher* PluginVarTracker::DispatcherForPluginObject( |
244 const PP_Var& plugin_object) const { | 118 const PP_Var& plugin_object) const { |
245 DCHECK(plugin_object.type == PP_VARTYPE_OBJECT); | 119 if (plugin_object.type != PP_VARTYPE_OBJECT) |
246 PluginVarInfoMap::const_iterator found = plugin_var_info_.find( | 120 return NULL; |
247 plugin_object.value.as_id); | 121 |
248 if (found != plugin_var_info_.end()) | 122 VarMap::const_iterator found = GetLiveVar(plugin_object); |
249 return found->second.host_var.dispatcher; | 123 if (found == live_vars_.end()) |
250 return NULL; | 124 return NULL; |
| 125 |
| 126 ProxyObjectVar* object = found->second.var->AsProxyObjectVar(); |
| 127 if (!object) |
| 128 return NULL; |
| 129 return object->dispatcher(); |
251 } | 130 } |
252 | 131 |
253 void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher, | 132 void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher, |
254 const PP_Var& host_object) { | 133 const PP_Var& host_object) { |
255 // Convert the host object to a normal var valid in the plugin. | 134 // Convert the host object to a normal var valid in the plugin. |
256 DCHECK(host_object.type == PP_VARTYPE_OBJECT); | 135 DCHECK(host_object.type == PP_VARTYPE_OBJECT); |
257 HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find( | 136 HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find( |
258 HostVar(dispatcher, host_object.value.as_id)); | 137 HostVar(dispatcher, static_cast<int32>(host_object.value.as_id))); |
259 if (found == host_var_to_plugin_var_.end()) { | 138 if (found == host_var_to_plugin_var_.end()) { |
260 NOTREACHED(); | 139 NOTREACHED(); |
261 return; | 140 return; |
262 } | 141 } |
263 | 142 |
264 // Now just release the object like normal. | 143 // Now just release the object given the plugin var ID. |
265 PP_Var plugin_object; | 144 ReleaseVar(found->second); |
266 plugin_object.type = PP_VARTYPE_OBJECT; | |
267 plugin_object.value.as_id = found->second; | |
268 Release(plugin_object); | |
269 } | 145 } |
270 | 146 |
271 int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) { | 147 int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) { |
272 PluginVarInfoMap::iterator found = plugin_var_info_.find( | 148 VarMap::iterator found = GetLiveVar(plugin_object); |
273 plugin_object.value.as_id); | 149 if (found == live_vars_.end()) |
274 if (found == plugin_var_info_.end()) | |
275 return -1; | 150 return -1; |
276 return found->second.ref_count; | 151 return found->second.ref_count; |
277 } | 152 } |
278 | 153 |
279 int PluginVarTracker::GetTrackedWithNoReferenceCountForObject( | 154 int PluginVarTracker::GetTrackedWithNoReferenceCountForObject( |
280 const PP_Var& plugin_object) { | 155 const PP_Var& plugin_object) { |
281 PluginVarInfoMap::iterator found = plugin_var_info_.find( | 156 VarMap::iterator found = GetLiveVar(plugin_object); |
282 plugin_object.value.as_id); | 157 if (found == live_vars_.end()) |
283 if (found == plugin_var_info_.end()) | |
284 return -1; | 158 return -1; |
285 return found->second.track_with_no_reference_count; | 159 return found->second.track_with_no_reference_count; |
286 } | 160 } |
287 | 161 |
288 void PluginVarTracker::SendAddRefObjectMsg(const HostVar& host_var) { | 162 int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) { |
289 int unused; | 163 // Normal adding. |
290 host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_AddRefObject( | 164 int32 new_id = VarTracker::AddVarInternal(var, mode); |
291 INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id, &unused)); | 165 |
| 166 // Need to add proxy objects to the host var map. |
| 167 ProxyObjectVar* proxy_object = var->AsProxyObjectVar(); |
| 168 if (proxy_object) { |
| 169 HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id()); |
| 170 DCHECK(host_var_to_plugin_var_.find(host_var) == |
| 171 host_var_to_plugin_var_.end()); // Adding an object twice, use |
| 172 // FindOrMakePluginVarFromHostVar. |
| 173 host_var_to_plugin_var_[host_var] = new_id; |
| 174 } |
| 175 return new_id; |
292 } | 176 } |
293 | 177 |
294 void PluginVarTracker::SendReleaseObjectMsg(const HostVar& host_var) { | 178 void PluginVarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator iter) { |
295 host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_ReleaseObject( | 179 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
296 INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id)); | 180 if (!object) { |
| 181 NOTREACHED(); |
| 182 return; |
| 183 } |
| 184 |
| 185 DCHECK(iter->second.ref_count == 0); |
| 186 |
| 187 // Got an AddRef for an object we have no existing reference for. |
| 188 // We need to tell the browser we've taken a ref. This comes up when the |
| 189 // browser passes an object as an input param and holds a ref for us. |
| 190 // This must be a sync message since otherwise the "addref" will actually |
| 191 // occur after the return to the browser of the sync function that |
| 192 // presumably sent the object. |
| 193 SendAddRefObjectMsg(*object); |
297 } | 194 } |
298 | 195 |
299 PluginVarTracker::PluginVarInfoMap::iterator | 196 void PluginVarTracker::ObjectGettingZeroRef(VarMap::iterator iter) { |
300 PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var, | 197 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
301 PluginDispatcher* dispatcher) { | 198 if (!object) { |
| 199 NOTREACHED(); |
| 200 return; |
| 201 } |
| 202 |
| 203 // Notify the host we're no longer holding our ref. |
| 204 DCHECK(iter->second.ref_count == 0); |
| 205 SendReleaseObjectMsg(*object); |
| 206 |
| 207 // This will optionally delete the info from live_vars_. |
| 208 VarTracker::ObjectGettingZeroRef(iter); |
| 209 } |
| 210 |
| 211 bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) { |
| 212 // Get the info before calling the base class's version of this function, |
| 213 // which may delete the object. |
| 214 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
| 215 HostVar host_var(object->dispatcher(), object->host_var_id()); |
| 216 |
| 217 if (!VarTracker::DeleteObjectInfoIfNecessary(iter)) |
| 218 return false; |
| 219 |
| 220 // Clean up the host var mapping. |
| 221 DCHECK(host_var_to_plugin_var_.find(host_var) != |
| 222 host_var_to_plugin_var_.end()); |
| 223 host_var_to_plugin_var_.erase(host_var); |
| 224 return true; |
| 225 } |
| 226 |
| 227 PP_Var PluginVarTracker::GetOrCreateObjectVarID(ProxyObjectVar* object) { |
| 228 // We can't use object->GetPPVar() because we don't want to affect the |
| 229 // refcount, so we have to add everything manually here. |
| 230 int32 var_id = object->GetExistingVarID(); |
| 231 if (!var_id) { |
| 232 var_id = AddVarInternal(object, ADD_VAR_CREATE_WITH_NO_REFERENCE); |
| 233 object->AssignVarID(var_id); |
| 234 } |
| 235 |
| 236 PP_Var ret; |
| 237 ret.type = PP_VARTYPE_OBJECT; |
| 238 ret.value.as_id = var_id; |
| 239 return ret; |
| 240 } |
| 241 |
| 242 void PluginVarTracker::SendAddRefObjectMsg( |
| 243 const ProxyObjectVar& proxy_object) { |
| 244 int unused; |
| 245 proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_AddRefObject( |
| 246 INTERFACE_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id(), &unused)); |
| 247 } |
| 248 |
| 249 void PluginVarTracker::SendReleaseObjectMsg( |
| 250 const ProxyObjectVar& proxy_object) { |
| 251 proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_ReleaseObject( |
| 252 INTERFACE_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id())); |
| 253 } |
| 254 |
| 255 scoped_refptr<ProxyObjectVar> PluginVarTracker::FindOrMakePluginVarFromHostVar( |
| 256 const PP_Var& var, |
| 257 PluginDispatcher* dispatcher) { |
302 DCHECK(var.type == PP_VARTYPE_OBJECT); | 258 DCHECK(var.type == PP_VARTYPE_OBJECT); |
303 HostVar host_var(dispatcher, var.value.as_id); | 259 HostVar host_var(dispatcher, var.value.as_id); |
304 | 260 |
305 HostVarToPluginVarMap::iterator found = | 261 HostVarToPluginVarMap::iterator found = |
306 host_var_to_plugin_var_.find(host_var); | 262 host_var_to_plugin_var_.find(host_var); |
307 if (found != host_var_to_plugin_var_.end()) { | 263 if (found == host_var_to_plugin_var_.end()) { |
308 PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second); | 264 // Create a new object. |
309 DCHECK(ret != plugin_var_info_.end()); | 265 return scoped_refptr<ProxyObjectVar>( |
310 return ret; // Already know about this var return the ID. | 266 new ProxyObjectVar(dispatcher, static_cast<int32>(var.value.as_id))); |
311 } | 267 } |
312 | 268 |
313 // Make a new var, adding references to both maps. | 269 // Have this host var, look up the object. |
314 VarID new_plugin_var_id = GetNewVarID(); | 270 VarMap::iterator ret = live_vars_.find(found->second); |
315 host_var_to_plugin_var_[host_var] = new_plugin_var_id; | 271 DCHECK(ret != live_vars_.end()); |
316 return plugin_var_info_.insert( | |
317 std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first; | |
318 } | |
319 | 272 |
320 void PluginVarTracker::DeletePluginVarInfoIfNecessary( | 273 // All objects should be proxy objects. |
321 PluginVarInfoMap::iterator iter) { | 274 DCHECK(ret->second.var->AsProxyObjectVar()); |
322 if (iter->second.ref_count != 0 || | 275 return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar()); |
323 iter->second.track_with_no_reference_count != 0) | |
324 return; // Object still alive. | |
325 | |
326 // Object ref counts are all zero, delete from both maps. | |
327 DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) != | |
328 host_var_to_plugin_var_.end()); | |
329 host_var_to_plugin_var_.erase(iter->second.host_var); | |
330 plugin_var_info_.erase(iter); | |
331 } | |
332 | |
333 PluginVarTracker::VarID PluginVarTracker::GetNewVarID() { | |
334 if (last_plugin_var_id_ == std::numeric_limits<VarID>::max()) | |
335 last_plugin_var_id_ = 0; | |
336 return ++last_plugin_var_id_; | |
337 } | 276 } |
338 | 277 |
339 } // namesace proxy | 278 } // namesace proxy |
340 } // namespace pp | 279 } // namespace pp |
OLD | NEW |