Chromium Code Reviews| Index: ppapi/proxy/plugin_var_tracker.cc |
| =================================================================== |
| --- ppapi/proxy/plugin_var_tracker.cc (revision 141525) |
| +++ ppapi/proxy/plugin_var_tracker.cc (working copy) |
| @@ -7,6 +7,7 @@ |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/singleton.h" |
| #include "ppapi/c/ppb_var.h" |
| +#include "ppapi/c/dev/ppp_class_deprecated.h" |
| #include "ppapi/proxy/plugin_array_buffer_var.h" |
| #include "ppapi/proxy/plugin_dispatcher.h" |
| #include "ppapi/proxy/ppapi_messages.h" |
| @@ -151,10 +152,80 @@ |
| ReleaseVar(found->second); |
| } |
| +void PluginVarTracker::DidDeleteInstance(PP_Instance instance) { |
| + // See the comment above user_data_to_plugin_ in the header file. We assume |
| + // there aren't that many objects so a brute-force search is reasonable. |
| + UserDataToPluginImplementedVarMap::iterator i = |
| + user_data_to_plugin_.begin(); |
| + while (i != user_data_to_plugin_.end()) { |
| + if (i->second.instance == instance) { |
| + if (!i->second.plugin_object_id) { |
| + // This object is for the freed instance and the plugin is not holding |
| + // any references to it. Deallocate immediately. |
| + UserDataToPluginImplementedVarMap::iterator next = i; |
|
viettrungluu
2012/06/15 21:45:24
I think it'd be clearer if you did:
...::iterator
|
| + ++next; |
| + i->second.ppp_class->Deallocate(i->first); |
| + user_data_to_plugin_.erase(i); |
| + i = next; |
| + } else { |
| + // The plugin is holding refs to this object. We don't want to call |
| + // Deallocate since the plugin may be depending on those refs to keep |
| + // its data alive. To avoid crashes in this case, just clear out the |
| + // instance to mark it and continue. When the plugin refs go to 0, |
| + // we'll notice there is no instance and call Deallocate. |
| + i->second.instance = 0; |
| + ++i; |
| + } |
| + } else { |
| + ++i; |
| + } |
| + } |
| +} |
| + |
| ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { |
| return new PluginArrayBufferVar(size_in_bytes); |
| } |
| +void PluginVarTracker::PluginImplementedObjectCreated( |
| + PP_Instance instance, |
| + const PP_Var& created_var, |
| + const PPP_Class_Deprecated* ppp_class, |
| + void* ppp_class_data) { |
| + PluginImplementedVar p; |
| + p.ppp_class = ppp_class; |
| + p.instance = instance; |
| + p.plugin_object_id = created_var.value.as_id; |
| + user_data_to_plugin_[ppp_class_data] = p; |
| + |
| + // Link the user data to the object. |
| + ProxyObjectVar* object = GetVar(created_var)->AsProxyObjectVar(); |
| + object->set_user_data(ppp_class_data); |
| +} |
| + |
| +void PluginVarTracker::PluginImplementedObjectDestroyed(void* user_data) { |
| + UserDataToPluginImplementedVarMap::iterator found = |
| + user_data_to_plugin_.find(user_data); |
| + if (found == user_data_to_plugin_.end()) { |
| + NOTREACHED(); |
| + return; |
| + } |
| + user_data_to_plugin_.erase(found); |
| +} |
| + |
| +bool PluginVarTracker::IsPluginImplementedObjectAlive(void* user_data) { |
| + return user_data_to_plugin_.find(user_data) != user_data_to_plugin_.end(); |
| +} |
| + |
| +bool PluginVarTracker::ValidatePluginObjectCall( |
| + const PPP_Class_Deprecated* ppp_class, |
| + void* user_data) { |
| + UserDataToPluginImplementedVarMap::iterator found = |
| + user_data_to_plugin_.find(user_data); |
| + if (found == user_data_to_plugin_.end()) |
| + return false; |
| + return found->second.ppp_class == ppp_class; |
| +} |
| + |
| int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) { |
| // Normal adding. |
| int32 new_id = VarTracker::AddVarInternal(var, mode); |
| @@ -200,6 +271,26 @@ |
| DCHECK(iter->second.ref_count == 0); |
| SendReleaseObjectMsg(*object); |
| + UserDataToPluginImplementedVarMap::iterator found = |
| + user_data_to_plugin_.find(object->user_data()); |
| + if (found != user_data_to_plugin_.end()) { |
| + // This object is implemented in the plugin. |
| + if (found->second.instance == 0) { |
| + // Instance is destroyed. This means that we'll never get a Deallocate |
| + // call from the renderer and we should do so now. |
| + found->second.ppp_class->Deallocate(found->first); |
| + user_data_to_plugin_.erase(found); |
| + } else { |
| + // The plugin is releasing its last reference to an object it implements. |
| + // Clear the tracking data that links our "plugin implemented object" to |
| + // the var. If the instance is destroyed and there is no ID, we know that |
| + // we should just call Deallocate on the object data. |
| + // |
| + // See the plugin_object_id declaration for more info. |
| + found->second.plugin_object_id = 0; |
| + } |
| + } |
| + |
| // This will optionally delete the info from live_vars_. |
| VarTracker::ObjectGettingZeroRef(iter); |
| } |