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>2011-08-09 23:14:13 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-09 23:14:13 +0000
commit2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f (patch)
tree79595eeb026dd29841a7380fd7753f992c2e466b /ppapi/proxy/plugin_var_tracker.cc
parent32131b9030d8313f7adc9b765f706ffbee7ca709 (diff)
downloadchromium_src-2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f.zip
chromium_src-2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f.tar.gz
chromium_src-2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f.tar.bz2
Unify var tracking between webkit and the proxy.
This replaces the var tracking in the proxy with the var tracking in the shared_impl that's used by the implementation. It adds a new ProxyObjectVar to be the proxied plugin analog of NPObjectVar in the impl. This new object just keeps track of the host data. The tricky part is to make the var tracker able to do all the crazy messaging. This adds some virtual functions to the shared var tracker that we override in the plugin in PluginVarTracker. This removes the calls to the GetLiveObjectsForInstance in the var deprecated test. It turns out this function really can't be implemented properly in the proxy, and I don't know why it even worked before. A Release() call posts a non-nestable task so the object isn't released until later. So to implement the proxy for GetLiveObjectsForInstance we would also need to post a non-nestable task. But when the test runs we're getting called from within the plugin, so blocking on a non-nestable task deadlocks. So I just gave up and deleted the parts of the test that uses it. TEST=included BUG=none Review URL: http://codereview.chromium.org/7578001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96094 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy/plugin_var_tracker.cc')
-rw-r--r--ppapi/proxy/plugin_var_tracker.cc395
1 files changed, 167 insertions, 228 deletions
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc
index 16d5992..0c834a5 100644
--- a/ppapi/proxy/plugin_var_tracker.cc
+++ b/ppapi/proxy/plugin_var_tracker.cc
@@ -10,18 +10,16 @@
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/interface_id.h"
+#include "ppapi/proxy/proxy_object_var.h"
+#include "ppapi/shared_impl/var.h"
+
+using ppapi::ProxyObjectVar;
+using ppapi::Var;
namespace pp {
namespace proxy {
-namespace {
-
-// When non-NULL, this object overrides the VarTrackerSingleton.
-PluginVarTracker* var_tracker_override = NULL;
-
-} // namespace
-
-PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i)
+PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, int32 i)
: dispatcher(d),
host_object_id(i) {
}
@@ -34,160 +32,33 @@ bool PluginVarTracker::HostVar::operator<(const HostVar& other) const {
return host_object_id < other.host_object_id;
}
-PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var)
- : host_var(host_var),
- ref_count(0),
- track_with_no_reference_count(0) {
-}
-
-PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) {
+PluginVarTracker::PluginVarTracker() {
}
PluginVarTracker::~PluginVarTracker() {
}
-// static
-void PluginVarTracker::SetInstanceForTest(PluginVarTracker* tracker) {
- var_tracker_override = tracker;
-}
-
-// static
-PluginVarTracker* PluginVarTracker::GetInstance() {
- if (var_tracker_override)
- return var_tracker_override;
- return Singleton<PluginVarTracker>::get();
-}
-
-PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) {
- return MakeString(str.c_str(), str.length());
-}
-
-PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str,
- uint32_t len) {
- std::pair<VarIDStringMap::iterator, bool>
- iter_success_pair(var_id_to_string_.end(), false);
- VarID new_id(0);
- RefCountedStringPtr str_ptr(new RefCountedString(str, len));
- // Pick new IDs until one is successfully inserted. This loop is very unlikely
- // to ever run a 2nd time, since we have ~2^63 possible IDs to exhaust.
- while (!iter_success_pair.second) {
- new_id = GetNewVarID();
- iter_success_pair =
- var_id_to_string_.insert(VarIDStringMap::value_type(new_id, str_ptr));
- }
- // Release the local pointer.
- str_ptr = NULL;
- // Now the map should have the only reference.
- DCHECK(iter_success_pair.first->second->HasOneRef());
- iter_success_pair.first->second->AddRef();
- return new_id;
-}
-
-const std::string* PluginVarTracker::GetExistingString(
- const PP_Var& var) const {
- if (var.type != PP_VARTYPE_STRING)
- return NULL;
- VarIDStringMap::const_iterator found =
- var_id_to_string_.find(var.value.as_id);
- if (found != var_id_to_string_.end())
- return &found->second->value();
- return NULL;
-}
-
-void PluginVarTracker::AddRef(const PP_Var& var) {
- if (var.type == PP_VARTYPE_STRING) {
- VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
- if (found == var_id_to_string_.end()) {
- NOTREACHED() << "Requesting to addref an unknown string.";
- return;
- }
- found->second->AddRef();
- } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) {
- PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
- if (found == plugin_var_info_.end()) {
- NOTREACHED() << "Requesting to addref an unknown object.";
- return;
- }
-
- PluginVarInfo& info = found->second;
- if (info.ref_count == 0) {
- // Got an AddRef for an object we have no existing reference for.
- // We need to tell the browser we've taken a ref. This comes up when the
- // browser passes an object as an input param and holds a ref for us.
- // This must be a sync message since otherwise the "addref" will actually
- // occur after the return to the browser of the sync function that
- // presumably sent the object.
- SendAddRefObjectMsg(info.host_var);
- }
- info.ref_count++;
- }
-}
-
-void PluginVarTracker::Release(const PP_Var& var) {
- if (var.type == PP_VARTYPE_STRING) {
- VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id);
- if (found == var_id_to_string_.end()) {
- NOTREACHED() << "Requesting to release an unknown string.";
- return;
- }
- found->second->Release();
- // If there is only 1 reference left, it's the map's reference. Erase it
- // from the map, which will delete the string.
- if (found->second->HasOneRef())
- var_id_to_string_.erase(found);
- } else if (var.type == PP_VARTYPE_OBJECT) {
- PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id);
- if (found == plugin_var_info_.end()) {
- NOTREACHED() << "Requesting to release an unknown object.";
- return;
- }
-
- PluginVarInfo& info = found->second;
- if (info.ref_count == 0) {
- NOTREACHED() << "Releasing an object with zero ref.";
- return;
- }
-
- info.ref_count--;
- if (info.ref_count == 0)
- SendReleaseObjectMsg(info.host_var);
- DeletePluginVarInfoIfNecessary(found);
- }
-}
-
-PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var,
+PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& host_var,
PluginDispatcher* dispatcher) {
- DCHECK(var.type == PP_VARTYPE_OBJECT);
-
- // Find the plugin info.
- PluginVarInfoMap::iterator found =
- FindOrMakePluginVarFromHostVar(var, dispatcher);
- if (found == plugin_var_info_.end()) {
- // The above code should have always made an entry in the map.
- NOTREACHED();
- return PP_MakeUndefined();
- }
+ DCHECK(host_var.type == PP_VARTYPE_OBJECT);
- // Fix up the references. The host (renderer) just sent us a ref. The
- // renderer has addrefed the var in its tracker for us since it's returning
- // it.
- PluginVarInfo& info = found->second;
- if (info.ref_count == 0) {
- // We don't have a reference to this already, then we just add it to our
- // tracker and use that one ref.
- info.ref_count = 1;
- } else {
- // We already have a reference to it, that means the renderer now has two
- // references on our behalf. We want to transfer that extra reference to
- // our list. This means we addref in the plugin, and release the extra one
- // in the renderer.
- SendReleaseObjectMsg(info.host_var);
- info.ref_count++;
+ // Get the object.
+ scoped_refptr<ProxyObjectVar> object(
+ FindOrMakePluginVarFromHostVar(host_var, dispatcher));
+
+ // Actually create the PP_Var, this will add all the tracking info but not
+ // adjust any refcounts.
+ PP_Var ret = GetOrCreateObjectVarID(object.get());
+
+ VarInfo& info = GetLiveVar(ret)->second;
+ if (info.ref_count > 0) {
+ // We already had a reference to it before. That means the renderer now has
+ // two references on our behalf. We want to transfer that extra reference
+ // to our list. This means we addref in the plugin, and release the extra
+ // one in the renderer.
+ SendReleaseObjectMsg(*object);
}
-
- PP_Var ret;
- ret.type = PP_VARTYPE_OBJECT;
- ret.value.as_id = found->first;
+ info.ref_count++;
return ret;
}
@@ -196,58 +67,66 @@ PP_Var PluginVarTracker::TrackObjectWithNoReference(
PluginDispatcher* dispatcher) {
DCHECK(host_var.type == PP_VARTYPE_OBJECT);
- PluginVarInfoMap::iterator found =
- FindOrMakePluginVarFromHostVar(host_var, dispatcher);
- if (found == plugin_var_info_.end()) {
- // The above code should have always made an entry in the map.
- NOTREACHED();
- return PP_MakeUndefined();
- }
+ // Get the object.
+ scoped_refptr<ProxyObjectVar> object(
+ FindOrMakePluginVarFromHostVar(host_var, dispatcher));
- found->second.track_with_no_reference_count++;
+ // Actually create the PP_Var, this will add all the tracking info but not
+ // adjust any refcounts.
+ PP_Var ret = GetOrCreateObjectVarID(object.get());
- PP_Var ret;
- ret.type = PP_VARTYPE_OBJECT;
- ret.value.as_id = found->first;
+ VarInfo& info = GetLiveVar(ret)->second;
+ info.track_with_no_reference_count++;
return ret;
}
void PluginVarTracker::StopTrackingObjectWithNoReference(
const PP_Var& plugin_var) {
DCHECK(plugin_var.type == PP_VARTYPE_OBJECT);
- PluginVarInfoMap::iterator found = plugin_var_info_.find(
- plugin_var.value.as_id);
- if (found == plugin_var_info_.end()) {
+ VarMap::iterator found = GetLiveVar(plugin_var);
+ if (found == live_vars_.end()) {
NOTREACHED();
return;
}
+ DCHECK(found->second.track_with_no_reference_count > 0);
found->second.track_with_no_reference_count--;
- DeletePluginVarInfoIfNecessary(found);
+ DeleteObjectInfoIfNecessary(found);
}
PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const {
- DCHECK(plugin_object.type == PP_VARTYPE_OBJECT);
- PluginVarInfoMap::const_iterator found = plugin_var_info_.find(
- plugin_object.value.as_id);
- if (found == plugin_var_info_.end()) {
+ if (plugin_object.type != PP_VARTYPE_OBJECT) {
NOTREACHED();
return PP_MakeUndefined();
}
+
+ Var* var = GetVar(plugin_object);
+ ProxyObjectVar* object = var->AsProxyObjectVar();
+ if (!object) {
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+
+ // Make a var with the host ID.
PP_Var ret;
ret.type = PP_VARTYPE_OBJECT;
- ret.value.as_id = found->second.host_var.host_object_id;
+ ret.value.as_id = object->host_var_id();
return ret;
}
PluginDispatcher* PluginVarTracker::DispatcherForPluginObject(
const PP_Var& plugin_object) const {
- DCHECK(plugin_object.type == PP_VARTYPE_OBJECT);
- PluginVarInfoMap::const_iterator found = plugin_var_info_.find(
- plugin_object.value.as_id);
- if (found != plugin_var_info_.end())
- return found->second.host_var.dispatcher;
- return NULL;
+ if (plugin_object.type != PP_VARTYPE_OBJECT)
+ return NULL;
+
+ VarMap::const_iterator found = GetLiveVar(plugin_object);
+ if (found == live_vars_.end())
+ return NULL;
+
+ ProxyObjectVar* object = found->second.var->AsProxyObjectVar();
+ if (!object)
+ return NULL;
+ return object->dispatcher();
}
void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher,
@@ -255,85 +134,145 @@ void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher,
// Convert the host object to a normal var valid in the plugin.
DCHECK(host_object.type == PP_VARTYPE_OBJECT);
HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find(
- HostVar(dispatcher, host_object.value.as_id));
+ HostVar(dispatcher, static_cast<int32>(host_object.value.as_id)));
if (found == host_var_to_plugin_var_.end()) {
NOTREACHED();
return;
}
- // Now just release the object like normal.
- PP_Var plugin_object;
- plugin_object.type = PP_VARTYPE_OBJECT;
- plugin_object.value.as_id = found->second;
- Release(plugin_object);
+ // Now just release the object given the plugin var ID.
+ ReleaseVar(found->second);
}
int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) {
- PluginVarInfoMap::iterator found = plugin_var_info_.find(
- plugin_object.value.as_id);
- if (found == plugin_var_info_.end())
+ VarMap::iterator found = GetLiveVar(plugin_object);
+ if (found == live_vars_.end())
return -1;
return found->second.ref_count;
}
int PluginVarTracker::GetTrackedWithNoReferenceCountForObject(
const PP_Var& plugin_object) {
- PluginVarInfoMap::iterator found = plugin_var_info_.find(
- plugin_object.value.as_id);
- if (found == plugin_var_info_.end())
+ VarMap::iterator found = GetLiveVar(plugin_object);
+ if (found == live_vars_.end())
return -1;
return found->second.track_with_no_reference_count;
}
-void PluginVarTracker::SendAddRefObjectMsg(const HostVar& host_var) {
+int32 PluginVarTracker::AddVarInternal(Var* var, AddVarRefMode mode) {
+ // Normal adding.
+ int32 new_id = VarTracker::AddVarInternal(var, mode);
+
+ // Need to add proxy objects to the host var map.
+ ProxyObjectVar* proxy_object = var->AsProxyObjectVar();
+ if (proxy_object) {
+ HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id());
+ DCHECK(host_var_to_plugin_var_.find(host_var) ==
+ host_var_to_plugin_var_.end()); // Adding an object twice, use
+ // FindOrMakePluginVarFromHostVar.
+ host_var_to_plugin_var_[host_var] = new_id;
+ }
+ return new_id;
+}
+
+void PluginVarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator iter) {
+ ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
+ if (!object) {
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK(iter->second.ref_count == 0);
+
+ // Got an AddRef for an object we have no existing reference for.
+ // We need to tell the browser we've taken a ref. This comes up when the
+ // browser passes an object as an input param and holds a ref for us.
+ // This must be a sync message since otherwise the "addref" will actually
+ // occur after the return to the browser of the sync function that
+ // presumably sent the object.
+ SendAddRefObjectMsg(*object);
+}
+
+void PluginVarTracker::ObjectGettingZeroRef(VarMap::iterator iter) {
+ ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
+ if (!object) {
+ NOTREACHED();
+ return;
+ }
+
+ // Notify the host we're no longer holding our ref.
+ DCHECK(iter->second.ref_count == 0);
+ SendReleaseObjectMsg(*object);
+
+ // This will optionally delete the info from live_vars_.
+ VarTracker::ObjectGettingZeroRef(iter);
+}
+
+bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) {
+ // Get the info before calling the base class's version of this function,
+ // which may delete the object.
+ ProxyObjectVar* object = iter->second.var->AsProxyObjectVar();
+ HostVar host_var(object->dispatcher(), object->host_var_id());
+
+ if (!VarTracker::DeleteObjectInfoIfNecessary(iter))
+ return false;
+
+ // Clean up the host var mapping.
+ DCHECK(host_var_to_plugin_var_.find(host_var) !=
+ host_var_to_plugin_var_.end());
+ host_var_to_plugin_var_.erase(host_var);
+ return true;
+}
+
+PP_Var PluginVarTracker::GetOrCreateObjectVarID(ProxyObjectVar* object) {
+ // We can't use object->GetPPVar() because we don't want to affect the
+ // refcount, so we have to add everything manually here.
+ int32 var_id = object->GetExistingVarID();
+ if (!var_id) {
+ var_id = AddVarInternal(object, ADD_VAR_CREATE_WITH_NO_REFERENCE);
+ object->AssignVarID(var_id);
+ }
+
+ PP_Var ret;
+ ret.type = PP_VARTYPE_OBJECT;
+ ret.value.as_id = var_id;
+ return ret;
+}
+
+void PluginVarTracker::SendAddRefObjectMsg(
+ const ProxyObjectVar& proxy_object) {
int unused;
- host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_AddRefObject(
- INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id, &unused));
+ proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_AddRefObject(
+ INTERFACE_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id(), &unused));
}
-void PluginVarTracker::SendReleaseObjectMsg(const HostVar& host_var) {
- host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
- INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id));
+void PluginVarTracker::SendReleaseObjectMsg(
+ const ProxyObjectVar& proxy_object) {
+ proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_ReleaseObject(
+ INTERFACE_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id()));
}
-PluginVarTracker::PluginVarInfoMap::iterator
-PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var,
- PluginDispatcher* dispatcher) {
+scoped_refptr<ProxyObjectVar> PluginVarTracker::FindOrMakePluginVarFromHostVar(
+ const PP_Var& var,
+ PluginDispatcher* dispatcher) {
DCHECK(var.type == PP_VARTYPE_OBJECT);
HostVar host_var(dispatcher, var.value.as_id);
HostVarToPluginVarMap::iterator found =
host_var_to_plugin_var_.find(host_var);
- if (found != host_var_to_plugin_var_.end()) {
- PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second);
- DCHECK(ret != plugin_var_info_.end());
- return ret; // Already know about this var return the ID.
+ if (found == host_var_to_plugin_var_.end()) {
+ // Create a new object.
+ return scoped_refptr<ProxyObjectVar>(
+ new ProxyObjectVar(dispatcher, static_cast<int32>(var.value.as_id)));
}
- // Make a new var, adding references to both maps.
- VarID new_plugin_var_id = GetNewVarID();
- host_var_to_plugin_var_[host_var] = new_plugin_var_id;
- return plugin_var_info_.insert(
- std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first;
-}
-
-void PluginVarTracker::DeletePluginVarInfoIfNecessary(
- PluginVarInfoMap::iterator iter) {
- if (iter->second.ref_count != 0 ||
- iter->second.track_with_no_reference_count != 0)
- return; // Object still alive.
-
- // Object ref counts are all zero, delete from both maps.
- DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) !=
- host_var_to_plugin_var_.end());
- host_var_to_plugin_var_.erase(iter->second.host_var);
- plugin_var_info_.erase(iter);
-}
+ // Have this host var, look up the object.
+ VarMap::iterator ret = live_vars_.find(found->second);
+ DCHECK(ret != live_vars_.end());
-PluginVarTracker::VarID PluginVarTracker::GetNewVarID() {
- if (last_plugin_var_id_ == std::numeric_limits<VarID>::max())
- last_plugin_var_id_ = 0;
- return ++last_plugin_var_id_;
+ // All objects should be proxy objects.
+ DCHECK(ret->second.var->AsProxyObjectVar());
+ return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar());
}
} // namesace proxy