Index: ppapi/proxy/plugin_var_tracker.cc |
diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc |
index 151fd2bf25db38e4804bfdb406899d3967c5315f..5734f961027b6c89c25489f3bdad938bd66cceff 100644 |
--- a/ppapi/proxy/plugin_var_tracker.cc |
+++ b/ppapi/proxy/plugin_var_tracker.cc |
@@ -19,28 +19,6 @@ namespace { |
// When non-NULL, this object overrides the VarTrackerSingleton. |
PluginVarTracker* var_tracker_override = NULL; |
-class RefCountedString : public base::RefCounted<RefCountedString> { |
- public: |
- RefCountedString() { |
- } |
- RefCountedString(const std::string& str) : value_(str) { |
- } |
- RefCountedString(const char* data, size_t len) |
- : value_(data, len) { |
- } |
- |
- const std::string& value() const { return value_; } |
- |
- private: |
- std::string value_; |
-}; |
- |
-// When running in the plugin, this will convert the string ID to the object |
-// using casting. No validity checking is done. |
-RefCountedString* PluginStringFromID(PluginVarTracker::VarID id) { |
- return reinterpret_cast<RefCountedString*>(static_cast<intptr_t>(id)); |
-} |
- |
} // namespace |
PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i) |
@@ -62,7 +40,7 @@ PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var) |
track_with_no_reference_count(0) { |
} |
-PluginVarTracker::PluginVarTracker() : last_plugin_object_id_(0) { |
+PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) { |
} |
PluginVarTracker::~PluginVarTracker() { |
@@ -81,33 +59,45 @@ PluginVarTracker* PluginVarTracker::GetInstance() { |
} |
PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) { |
- RefCountedString* out = new RefCountedString(str); |
- out->AddRef(); |
- return static_cast<VarID>(reinterpret_cast<intptr_t>(out)); |
+ return MakeString(str.c_str(), str.length()); |
} |
PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str, |
uint32_t len) { |
- RefCountedString* out = new RefCountedString(str, len); |
- out->AddRef(); |
- return static_cast<VarID>(reinterpret_cast<intptr_t>(out)); |
-} |
- |
-std::string PluginVarTracker::GetString(const PP_Var& var) const { |
- return PluginStringFromID(var.value.as_id)->value(); |
+ 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)); |
+ } |
+ 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; |
- RefCountedString* str = PluginStringFromID(var.value.as_id); |
- return &str->value(); |
+ 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) { |
- PluginStringFromID(var.value.as_id)->AddRef(); |
+ 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()) { |
@@ -131,7 +121,16 @@ void PluginVarTracker::AddRef(const PP_Var& var) { |
void PluginVarTracker::Release(const PP_Var& var) { |
if (var.type == PP_VARTYPE_STRING) { |
- PluginStringFromID(var.value.as_id)->Release(); |
+ 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()) { |
@@ -308,7 +307,7 @@ PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var, |
} |
// Make a new var, adding references to both maps. |
- VarID new_plugin_var_id = ++last_plugin_object_id_; |
+ 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; |
@@ -327,5 +326,11 @@ void PluginVarTracker::DeletePluginVarInfoIfNecessary( |
plugin_var_info_.erase(iter); |
} |
+PluginVarTracker::VarID PluginVarTracker::GetNewVarID() { |
+ if (last_plugin_var_id_ == std::numeric_limits<VarID>::max()) |
+ last_plugin_var_id_ = 0; |
+ return ++last_plugin_var_id_; |
+} |
+ |
} // namesace proxy |
} // namespace pp |