summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/plugin_var_tracker.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-18 19:41:30 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-18 19:41:30 +0000
commitedb5b05700f53fb7b1827727777cc15b50370ccb (patch)
tree4cc0fc0bf581503e6fd273a037a63353ca41bf9c /ppapi/proxy/plugin_var_tracker.cc
parentdc20acdfb4026b23709beec34a187dfde58af437 (diff)
downloadchromium_src-edb5b05700f53fb7b1827727777cc15b50370ccb.zip
chromium_src-edb5b05700f53fb7b1827727777cc15b50370ccb.tar.gz
chromium_src-edb5b05700f53fb7b1827727777cc15b50370ccb.tar.bz2
Actually free plugin implement vars when running out of process when the
plugin holds a reference beyond the lifetime of the instance. Review URL: https://chromiumcodereview.appspot.com/10542150 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@142787 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy/plugin_var_tracker.cc')
-rw-r--r--ppapi/proxy/plugin_var_tracker.cc90
1 files changed, 90 insertions, 0 deletions
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc
index 74cd557..52ecad8 100644
--- a/ppapi/proxy/plugin_var_tracker.cc
+++ b/ppapi/proxy/plugin_var_tracker.cc
@@ -6,6 +6,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
+#include "ppapi/c/dev/ppp_class_deprecated.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/proxy/plugin_array_buffer_var.h"
#include "ppapi/proxy/plugin_dispatcher.h"
@@ -151,10 +152,79 @@ void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher,
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 to_remove = i;
+ ++i;
+ to_remove->second.ppp_class->Deallocate(to_remove->first);
+ user_data_to_plugin_.erase(to_remove);
+ } 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 +270,26 @@ void PluginVarTracker::ObjectGettingZeroRef(VarMap::iterator iter) {
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);
}