summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/plugin_var_tracker.cc
diff options
context:
space:
mode:
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