Chromium Code Reviews| 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_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/c/dev/ppp_class_deprecated.h" | |
| 10 #include "ppapi/proxy/plugin_array_buffer_var.h" | 11 #include "ppapi/proxy/plugin_array_buffer_var.h" |
| 11 #include "ppapi/proxy/plugin_dispatcher.h" | 12 #include "ppapi/proxy/plugin_dispatcher.h" |
| 12 #include "ppapi/proxy/ppapi_messages.h" | 13 #include "ppapi/proxy/ppapi_messages.h" |
| 13 #include "ppapi/proxy/proxy_object_var.h" | 14 #include "ppapi/proxy/proxy_object_var.h" |
| 14 #include "ppapi/shared_impl/api_id.h" | 15 #include "ppapi/shared_impl/api_id.h" |
| 15 #include "ppapi/shared_impl/var.h" | 16 #include "ppapi/shared_impl/var.h" |
| 16 | 17 |
| 17 namespace ppapi { | 18 namespace ppapi { |
| 18 namespace proxy { | 19 namespace proxy { |
| 19 | 20 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 HostVar(dispatcher, static_cast<int32>(host_object.value.as_id))); | 145 HostVar(dispatcher, static_cast<int32>(host_object.value.as_id))); |
| 145 if (found == host_var_to_plugin_var_.end()) { | 146 if (found == host_var_to_plugin_var_.end()) { |
| 146 NOTREACHED(); | 147 NOTREACHED(); |
| 147 return; | 148 return; |
| 148 } | 149 } |
| 149 | 150 |
| 150 // Now just release the object given the plugin var ID. | 151 // Now just release the object given the plugin var ID. |
| 151 ReleaseVar(found->second); | 152 ReleaseVar(found->second); |
| 152 } | 153 } |
| 153 | 154 |
| 155 void PluginVarTracker::DidDeleteInstance(PP_Instance instance) { | |
| 156 // See the comment above user_data_to_plugin_ in the header file. We assume | |
| 157 // there aren't that many objects so a brute-force search is reasonable. | |
| 158 UserDataToPluginImplementedVarMap::iterator i = | |
| 159 user_data_to_plugin_.begin(); | |
| 160 while (i != user_data_to_plugin_.end()) { | |
| 161 if (i->second.instance == instance) { | |
| 162 if (!i->second.plugin_object_id) { | |
| 163 // This object is for the freed instance and the plugin is not holding | |
| 164 // any references to it. Deallocate immediately. | |
| 165 UserDataToPluginImplementedVarMap::iterator next = i; | |
|
viettrungluu
2012/06/15 21:45:24
I think it'd be clearer if you did:
...::iterator
| |
| 166 ++next; | |
| 167 i->second.ppp_class->Deallocate(i->first); | |
| 168 user_data_to_plugin_.erase(i); | |
| 169 i = next; | |
| 170 } else { | |
| 171 // The plugin is holding refs to this object. We don't want to call | |
| 172 // Deallocate since the plugin may be depending on those refs to keep | |
| 173 // its data alive. To avoid crashes in this case, just clear out the | |
| 174 // instance to mark it and continue. When the plugin refs go to 0, | |
| 175 // we'll notice there is no instance and call Deallocate. | |
| 176 i->second.instance = 0; | |
| 177 ++i; | |
| 178 } | |
| 179 } else { | |
| 180 ++i; | |
| 181 } | |
| 182 } | |
| 183 } | |
| 184 | |
| 154 ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { | 185 ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { |
| 155 return new PluginArrayBufferVar(size_in_bytes); | 186 return new PluginArrayBufferVar(size_in_bytes); |
| 156 } | 187 } |
| 157 | 188 |
| 189 void PluginVarTracker::PluginImplementedObjectCreated( | |
| 190 PP_Instance instance, | |
| 191 const PP_Var& created_var, | |
| 192 const PPP_Class_Deprecated* ppp_class, | |
| 193 void* ppp_class_data) { | |
| 194 PluginImplementedVar p; | |
| 195 p.ppp_class = ppp_class; | |
| 196 p.instance = instance; | |
| 197 p.plugin_object_id = created_var.value.as_id; | |
| 198 user_data_to_plugin_[ppp_class_data] = p; | |
| 199 | |
| 200 // Link the user data to the object. | |
| 201 ProxyObjectVar* object = GetVar(created_var)->AsProxyObjectVar(); | |
| 202 object->set_user_data(ppp_class_data); | |
| 203 } | |
| 204 | |
| 205 void PluginVarTracker::PluginImplementedObjectDestroyed(void* user_data) { | |
| 206 UserDataToPluginImplementedVarMap::iterator found = | |
| 207 user_data_to_plugin_.find(user_data); | |
| 208 if (found == user_data_to_plugin_.end()) { | |
| 209 NOTREACHED(); | |
| 210 return; | |
| 211 } | |
| 212 user_data_to_plugin_.erase(found); | |
| 213 } | |
| 214 | |
| 215 bool PluginVarTracker::IsPluginImplementedObjectAlive(void* user_data) { | |
| 216 return user_data_to_plugin_.find(user_data) != user_data_to_plugin_.end(); | |
| 217 } | |
| 218 | |
| 219 bool PluginVarTracker::ValidatePluginObjectCall( | |
| 220 const PPP_Class_Deprecated* ppp_class, | |
| 221 void* user_data) { | |
| 222 UserDataToPluginImplementedVarMap::iterator found = | |
| 223 user_data_to_plugin_.find(user_data); | |
| 224 if (found == user_data_to_plugin_.end()) | |
| 225 return false; | |
| 226 return found->second.ppp_class == ppp_class; | |
| 227 } | |
| 228 | |
| 158 int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) { | 229 int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) { |
| 159 // Normal adding. | 230 // Normal adding. |
| 160 int32 new_id = VarTracker::AddVarInternal(var, mode); | 231 int32 new_id = VarTracker::AddVarInternal(var, mode); |
| 161 | 232 |
| 162 // Need to add proxy objects to the host var map. | 233 // Need to add proxy objects to the host var map. |
| 163 ProxyObjectVar* proxy_object = var->AsProxyObjectVar(); | 234 ProxyObjectVar* proxy_object = var->AsProxyObjectVar(); |
| 164 if (proxy_object) { | 235 if (proxy_object) { |
| 165 HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id()); | 236 HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id()); |
| 166 DCHECK(host_var_to_plugin_var_.find(host_var) == | 237 DCHECK(host_var_to_plugin_var_.find(host_var) == |
| 167 host_var_to_plugin_var_.end()); // Adding an object twice, use | 238 host_var_to_plugin_var_.end()); // Adding an object twice, use |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 193 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); | 264 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
| 194 if (!object) { | 265 if (!object) { |
| 195 NOTREACHED(); | 266 NOTREACHED(); |
| 196 return; | 267 return; |
| 197 } | 268 } |
| 198 | 269 |
| 199 // Notify the host we're no longer holding our ref. | 270 // Notify the host we're no longer holding our ref. |
| 200 DCHECK(iter->second.ref_count == 0); | 271 DCHECK(iter->second.ref_count == 0); |
| 201 SendReleaseObjectMsg(*object); | 272 SendReleaseObjectMsg(*object); |
| 202 | 273 |
| 274 UserDataToPluginImplementedVarMap::iterator found = | |
| 275 user_data_to_plugin_.find(object->user_data()); | |
| 276 if (found != user_data_to_plugin_.end()) { | |
| 277 // This object is implemented in the plugin. | |
| 278 if (found->second.instance == 0) { | |
| 279 // Instance is destroyed. This means that we'll never get a Deallocate | |
| 280 // call from the renderer and we should do so now. | |
| 281 found->second.ppp_class->Deallocate(found->first); | |
| 282 user_data_to_plugin_.erase(found); | |
| 283 } else { | |
| 284 // The plugin is releasing its last reference to an object it implements. | |
| 285 // Clear the tracking data that links our "plugin implemented object" to | |
| 286 // the var. If the instance is destroyed and there is no ID, we know that | |
| 287 // we should just call Deallocate on the object data. | |
| 288 // | |
| 289 // See the plugin_object_id declaration for more info. | |
| 290 found->second.plugin_object_id = 0; | |
| 291 } | |
| 292 } | |
| 293 | |
| 203 // This will optionally delete the info from live_vars_. | 294 // This will optionally delete the info from live_vars_. |
| 204 VarTracker::ObjectGettingZeroRef(iter); | 295 VarTracker::ObjectGettingZeroRef(iter); |
| 205 } | 296 } |
| 206 | 297 |
| 207 bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) { | 298 bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) { |
| 208 // Get the info before calling the base class's version of this function, | 299 // Get the info before calling the base class's version of this function, |
| 209 // which may delete the object. | 300 // which may delete the object. |
| 210 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); | 301 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
| 211 HostVar host_var(object->dispatcher(), object->host_var_id()); | 302 HostVar host_var(object->dispatcher(), object->host_var_id()); |
| 212 | 303 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 VarMap::iterator ret = live_vars_.find(found->second); | 356 VarMap::iterator ret = live_vars_.find(found->second); |
| 266 DCHECK(ret != live_vars_.end()); | 357 DCHECK(ret != live_vars_.end()); |
| 267 | 358 |
| 268 // All objects should be proxy objects. | 359 // All objects should be proxy objects. |
| 269 DCHECK(ret->second.var->AsProxyObjectVar()); | 360 DCHECK(ret->second.var->AsProxyObjectVar()); |
| 270 return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar()); | 361 return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar()); |
| 271 } | 362 } |
| 272 | 363 |
| 273 } // namesace proxy | 364 } // namesace proxy |
| 274 } // namespace ppapi | 365 } // namespace ppapi |
| OLD | NEW |