| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/proxy/plugin_var_tracker.h" | 5 #include "ppapi/proxy/plugin_var_tracker.h" |
| 6 | 6 |
| 7 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
| 8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
| 9 #include "ppapi/c/ppb_var.h" | 9 #include "ppapi/c/ppb_var.h" |
| 10 #include "ppapi/proxy/plugin_dispatcher.h" | 10 #include "ppapi/proxy/plugin_dispatcher.h" |
| 11 #include "ppapi/proxy/ppapi_messages.h" | 11 #include "ppapi/proxy/ppapi_messages.h" |
| 12 #include "ppapi/proxy/interface_id.h" | 12 #include "ppapi/proxy/interface_id.h" |
| 13 #include "ppapi/proxy/proxy_object_var.h" |
| 14 #include "ppapi/shared_impl/var.h" |
| 15 |
| 16 using ppapi::ProxyObjectVar; |
| 17 using ppapi::Var; |
| 13 | 18 |
| 14 namespace pp { | 19 namespace pp { |
| 15 namespace proxy { | 20 namespace proxy { |
| 16 | 21 |
| 17 namespace { | 22 PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, int32 i) |
| 18 | |
| 19 // When non-NULL, this object overrides the VarTrackerSingleton. | |
| 20 PluginVarTracker* var_tracker_override = NULL; | |
| 21 | |
| 22 } // namespace | |
| 23 | |
| 24 PluginVarTracker::HostVar::HostVar(PluginDispatcher* d, VarID i) | |
| 25 : dispatcher(d), | 23 : dispatcher(d), |
| 26 host_object_id(i) { | 24 host_object_id(i) { |
| 27 } | 25 } |
| 28 | 26 |
| 29 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const { | 27 bool PluginVarTracker::HostVar::operator<(const HostVar& other) const { |
| 30 if (dispatcher < other.dispatcher) | 28 if (dispatcher < other.dispatcher) |
| 31 return true; | 29 return true; |
| 32 if (other.dispatcher < dispatcher) | 30 if (other.dispatcher < dispatcher) |
| 33 return false; | 31 return false; |
| 34 return host_object_id < other.host_object_id; | 32 return host_object_id < other.host_object_id; |
| 35 } | 33 } |
| 36 | 34 |
| 37 PluginVarTracker::PluginVarInfo::PluginVarInfo(const HostVar& host_var) | 35 PluginVarTracker::PluginVarTracker() { |
| 38 : host_var(host_var), | |
| 39 ref_count(0), | |
| 40 track_with_no_reference_count(0) { | |
| 41 } | |
| 42 | |
| 43 PluginVarTracker::PluginVarTracker() : last_plugin_var_id_(0) { | |
| 44 } | 36 } |
| 45 | 37 |
| 46 PluginVarTracker::~PluginVarTracker() { | 38 PluginVarTracker::~PluginVarTracker() { |
| 47 } | 39 } |
| 48 | 40 |
| 49 // static | 41 PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& host_var, |
| 50 void PluginVarTracker::SetInstanceForTest(PluginVarTracker* tracker) { | 42 PluginDispatcher* dispatcher) { |
| 51 var_tracker_override = tracker; | 43 DCHECK(host_var.type == PP_VARTYPE_OBJECT); |
| 52 } | |
| 53 | 44 |
| 54 // static | 45 // Get the object. |
| 55 PluginVarTracker* PluginVarTracker::GetInstance() { | 46 scoped_refptr<ProxyObjectVar> object( |
| 56 if (var_tracker_override) | 47 FindOrMakePluginVarFromHostVar(host_var, dispatcher)); |
| 57 return var_tracker_override; | |
| 58 return Singleton<PluginVarTracker>::get(); | |
| 59 } | |
| 60 | 48 |
| 61 PluginVarTracker::VarID PluginVarTracker::MakeString(const std::string& str) { | 49 // Actually create the PP_Var, this will add all the tracking info but not |
| 62 return MakeString(str.c_str(), str.length()); | 50 // adjust any refcounts. |
| 63 } | 51 PP_Var ret = GetOrCreateObjectVarID(object.get()); |
| 64 | 52 |
| 65 PluginVarTracker::VarID PluginVarTracker::MakeString(const char* str, | 53 VarInfo& info = GetLiveVar(ret)->second; |
| 66 uint32_t len) { | 54 if (info.ref_count > 0) { |
| 67 std::pair<VarIDStringMap::iterator, bool> | 55 // We already had a reference to it before. That means the renderer now has |
| 68 iter_success_pair(var_id_to_string_.end(), false); | 56 // two references on our behalf. We want to transfer that extra reference |
| 69 VarID new_id(0); | 57 // to our list. This means we addref in the plugin, and release the extra |
| 70 RefCountedStringPtr str_ptr(new RefCountedString(str, len)); | 58 // one in the renderer. |
| 71 // Pick new IDs until one is successfully inserted. This loop is very unlikely | 59 SendReleaseObjectMsg(*object); |
| 72 // to ever run a 2nd time, since we have ~2^63 possible IDs to exhaust. | |
| 73 while (!iter_success_pair.second) { | |
| 74 new_id = GetNewVarID(); | |
| 75 iter_success_pair = | |
| 76 var_id_to_string_.insert(VarIDStringMap::value_type(new_id, str_ptr)); | |
| 77 } | 60 } |
| 78 // Release the local pointer. | 61 info.ref_count++; |
| 79 str_ptr = NULL; | |
| 80 // Now the map should have the only reference. | |
| 81 DCHECK(iter_success_pair.first->second->HasOneRef()); | |
| 82 iter_success_pair.first->second->AddRef(); | |
| 83 return new_id; | |
| 84 } | |
| 85 | |
| 86 const std::string* PluginVarTracker::GetExistingString( | |
| 87 const PP_Var& var) const { | |
| 88 if (var.type != PP_VARTYPE_STRING) | |
| 89 return NULL; | |
| 90 VarIDStringMap::const_iterator found = | |
| 91 var_id_to_string_.find(var.value.as_id); | |
| 92 if (found != var_id_to_string_.end()) | |
| 93 return &found->second->value(); | |
| 94 return NULL; | |
| 95 } | |
| 96 | |
| 97 void PluginVarTracker::AddRef(const PP_Var& var) { | |
| 98 if (var.type == PP_VARTYPE_STRING) { | |
| 99 VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id); | |
| 100 if (found == var_id_to_string_.end()) { | |
| 101 NOTREACHED() << "Requesting to addref an unknown string."; | |
| 102 return; | |
| 103 } | |
| 104 found->second->AddRef(); | |
| 105 } else if (var.type == PP_VARTYPE_OBJECT && var.value.as_id != 0) { | |
| 106 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id); | |
| 107 if (found == plugin_var_info_.end()) { | |
| 108 NOTREACHED() << "Requesting to addref an unknown object."; | |
| 109 return; | |
| 110 } | |
| 111 | |
| 112 PluginVarInfo& info = found->second; | |
| 113 if (info.ref_count == 0) { | |
| 114 // Got an AddRef for an object we have no existing reference for. | |
| 115 // We need to tell the browser we've taken a ref. This comes up when the | |
| 116 // browser passes an object as an input param and holds a ref for us. | |
| 117 // This must be a sync message since otherwise the "addref" will actually | |
| 118 // occur after the return to the browser of the sync function that | |
| 119 // presumably sent the object. | |
| 120 SendAddRefObjectMsg(info.host_var); | |
| 121 } | |
| 122 info.ref_count++; | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 void PluginVarTracker::Release(const PP_Var& var) { | |
| 127 if (var.type == PP_VARTYPE_STRING) { | |
| 128 VarIDStringMap::iterator found = var_id_to_string_.find(var.value.as_id); | |
| 129 if (found == var_id_to_string_.end()) { | |
| 130 NOTREACHED() << "Requesting to release an unknown string."; | |
| 131 return; | |
| 132 } | |
| 133 found->second->Release(); | |
| 134 // If there is only 1 reference left, it's the map's reference. Erase it | |
| 135 // from the map, which will delete the string. | |
| 136 if (found->second->HasOneRef()) | |
| 137 var_id_to_string_.erase(found); | |
| 138 } else if (var.type == PP_VARTYPE_OBJECT) { | |
| 139 PluginVarInfoMap::iterator found = plugin_var_info_.find(var.value.as_id); | |
| 140 if (found == plugin_var_info_.end()) { | |
| 141 NOTREACHED() << "Requesting to release an unknown object."; | |
| 142 return; | |
| 143 } | |
| 144 | |
| 145 PluginVarInfo& info = found->second; | |
| 146 if (info.ref_count == 0) { | |
| 147 NOTREACHED() << "Releasing an object with zero ref."; | |
| 148 return; | |
| 149 } | |
| 150 | |
| 151 info.ref_count--; | |
| 152 if (info.ref_count == 0) | |
| 153 SendReleaseObjectMsg(info.host_var); | |
| 154 DeletePluginVarInfoIfNecessary(found); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 PP_Var PluginVarTracker::ReceiveObjectPassRef(const PP_Var& var, | |
| 159 PluginDispatcher* dispatcher) { | |
| 160 DCHECK(var.type == PP_VARTYPE_OBJECT); | |
| 161 | |
| 162 // Find the plugin info. | |
| 163 PluginVarInfoMap::iterator found = | |
| 164 FindOrMakePluginVarFromHostVar(var, dispatcher); | |
| 165 if (found == plugin_var_info_.end()) { | |
| 166 // The above code should have always made an entry in the map. | |
| 167 NOTREACHED(); | |
| 168 return PP_MakeUndefined(); | |
| 169 } | |
| 170 | |
| 171 // Fix up the references. The host (renderer) just sent us a ref. The | |
| 172 // renderer has addrefed the var in its tracker for us since it's returning | |
| 173 // it. | |
| 174 PluginVarInfo& info = found->second; | |
| 175 if (info.ref_count == 0) { | |
| 176 // We don't have a reference to this already, then we just add it to our | |
| 177 // tracker and use that one ref. | |
| 178 info.ref_count = 1; | |
| 179 } else { | |
| 180 // We already have a reference to it, that means the renderer now has two | |
| 181 // references on our behalf. We want to transfer that extra reference to | |
| 182 // our list. This means we addref in the plugin, and release the extra one | |
| 183 // in the renderer. | |
| 184 SendReleaseObjectMsg(info.host_var); | |
| 185 info.ref_count++; | |
| 186 } | |
| 187 | |
| 188 PP_Var ret; | |
| 189 ret.type = PP_VARTYPE_OBJECT; | |
| 190 ret.value.as_id = found->first; | |
| 191 return ret; | 62 return ret; |
| 192 } | 63 } |
| 193 | 64 |
| 194 PP_Var PluginVarTracker::TrackObjectWithNoReference( | 65 PP_Var PluginVarTracker::TrackObjectWithNoReference( |
| 195 const PP_Var& host_var, | 66 const PP_Var& host_var, |
| 196 PluginDispatcher* dispatcher) { | 67 PluginDispatcher* dispatcher) { |
| 197 DCHECK(host_var.type == PP_VARTYPE_OBJECT); | 68 DCHECK(host_var.type == PP_VARTYPE_OBJECT); |
| 198 | 69 |
| 199 PluginVarInfoMap::iterator found = | 70 // Get the object. |
| 200 FindOrMakePluginVarFromHostVar(host_var, dispatcher); | 71 scoped_refptr<ProxyObjectVar> object( |
| 201 if (found == plugin_var_info_.end()) { | 72 FindOrMakePluginVarFromHostVar(host_var, dispatcher)); |
| 202 // The above code should have always made an entry in the map. | |
| 203 NOTREACHED(); | |
| 204 return PP_MakeUndefined(); | |
| 205 } | |
| 206 | 73 |
| 207 found->second.track_with_no_reference_count++; | 74 // Actually create the PP_Var, this will add all the tracking info but not |
| 75 // adjust any refcounts. |
| 76 PP_Var ret = GetOrCreateObjectVarID(object.get()); |
| 208 | 77 |
| 209 PP_Var ret; | 78 VarInfo& info = GetLiveVar(ret)->second; |
| 210 ret.type = PP_VARTYPE_OBJECT; | 79 info.track_with_no_reference_count++; |
| 211 ret.value.as_id = found->first; | |
| 212 return ret; | 80 return ret; |
| 213 } | 81 } |
| 214 | 82 |
| 215 void PluginVarTracker::StopTrackingObjectWithNoReference( | 83 void PluginVarTracker::StopTrackingObjectWithNoReference( |
| 216 const PP_Var& plugin_var) { | 84 const PP_Var& plugin_var) { |
| 217 DCHECK(plugin_var.type == PP_VARTYPE_OBJECT); | 85 DCHECK(plugin_var.type == PP_VARTYPE_OBJECT); |
| 218 PluginVarInfoMap::iterator found = plugin_var_info_.find( | 86 VarMap::iterator found = GetLiveVar(plugin_var); |
| 219 plugin_var.value.as_id); | 87 if (found == live_vars_.end()) { |
| 220 if (found == plugin_var_info_.end()) { | |
| 221 NOTREACHED(); | 88 NOTREACHED(); |
| 222 return; | 89 return; |
| 223 } | 90 } |
| 224 | 91 |
| 92 DCHECK(found->second.track_with_no_reference_count > 0); |
| 225 found->second.track_with_no_reference_count--; | 93 found->second.track_with_no_reference_count--; |
| 226 DeletePluginVarInfoIfNecessary(found); | 94 DeleteObjectInfoIfNecessary(found); |
| 227 } | 95 } |
| 228 | 96 |
| 229 PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const { | 97 PP_Var PluginVarTracker::GetHostObject(const PP_Var& plugin_object) const { |
| 230 DCHECK(plugin_object.type == PP_VARTYPE_OBJECT); | 98 if (plugin_object.type != PP_VARTYPE_OBJECT) { |
| 231 PluginVarInfoMap::const_iterator found = plugin_var_info_.find( | |
| 232 plugin_object.value.as_id); | |
| 233 if (found == plugin_var_info_.end()) { | |
| 234 NOTREACHED(); | 99 NOTREACHED(); |
| 235 return PP_MakeUndefined(); | 100 return PP_MakeUndefined(); |
| 236 } | 101 } |
| 102 |
| 103 Var* var = GetVar(plugin_object); |
| 104 ProxyObjectVar* object = var->AsProxyObjectVar(); |
| 105 if (!object) { |
| 106 NOTREACHED(); |
| 107 return PP_MakeUndefined(); |
| 108 } |
| 109 |
| 110 // Make a var with the host ID. |
| 237 PP_Var ret; | 111 PP_Var ret; |
| 238 ret.type = PP_VARTYPE_OBJECT; | 112 ret.type = PP_VARTYPE_OBJECT; |
| 239 ret.value.as_id = found->second.host_var.host_object_id; | 113 ret.value.as_id = object->host_var_id(); |
| 240 return ret; | 114 return ret; |
| 241 } | 115 } |
| 242 | 116 |
| 243 PluginDispatcher* PluginVarTracker::DispatcherForPluginObject( | 117 PluginDispatcher* PluginVarTracker::DispatcherForPluginObject( |
| 244 const PP_Var& plugin_object) const { | 118 const PP_Var& plugin_object) const { |
| 245 DCHECK(plugin_object.type == PP_VARTYPE_OBJECT); | 119 if (plugin_object.type != PP_VARTYPE_OBJECT) |
| 246 PluginVarInfoMap::const_iterator found = plugin_var_info_.find( | 120 return NULL; |
| 247 plugin_object.value.as_id); | 121 |
| 248 if (found != plugin_var_info_.end()) | 122 VarMap::const_iterator found = GetLiveVar(plugin_object); |
| 249 return found->second.host_var.dispatcher; | 123 if (found == live_vars_.end()) |
| 250 return NULL; | 124 return NULL; |
| 125 |
| 126 ProxyObjectVar* object = found->second.var->AsProxyObjectVar(); |
| 127 if (!object) |
| 128 return NULL; |
| 129 return object->dispatcher(); |
| 251 } | 130 } |
| 252 | 131 |
| 253 void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher, | 132 void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher, |
| 254 const PP_Var& host_object) { | 133 const PP_Var& host_object) { |
| 255 // Convert the host object to a normal var valid in the plugin. | 134 // Convert the host object to a normal var valid in the plugin. |
| 256 DCHECK(host_object.type == PP_VARTYPE_OBJECT); | 135 DCHECK(host_object.type == PP_VARTYPE_OBJECT); |
| 257 HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find( | 136 HostVarToPluginVarMap::iterator found = host_var_to_plugin_var_.find( |
| 258 HostVar(dispatcher, host_object.value.as_id)); | 137 HostVar(dispatcher, static_cast<int32>(host_object.value.as_id))); |
| 259 if (found == host_var_to_plugin_var_.end()) { | 138 if (found == host_var_to_plugin_var_.end()) { |
| 260 NOTREACHED(); | 139 NOTREACHED(); |
| 261 return; | 140 return; |
| 262 } | 141 } |
| 263 | 142 |
| 264 // Now just release the object like normal. | 143 // Now just release the object given the plugin var ID. |
| 265 PP_Var plugin_object; | 144 ReleaseVar(found->second); |
| 266 plugin_object.type = PP_VARTYPE_OBJECT; | |
| 267 plugin_object.value.as_id = found->second; | |
| 268 Release(plugin_object); | |
| 269 } | 145 } |
| 270 | 146 |
| 271 int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) { | 147 int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) { |
| 272 PluginVarInfoMap::iterator found = plugin_var_info_.find( | 148 VarMap::iterator found = GetLiveVar(plugin_object); |
| 273 plugin_object.value.as_id); | 149 if (found == live_vars_.end()) |
| 274 if (found == plugin_var_info_.end()) | |
| 275 return -1; | 150 return -1; |
| 276 return found->second.ref_count; | 151 return found->second.ref_count; |
| 277 } | 152 } |
| 278 | 153 |
| 279 int PluginVarTracker::GetTrackedWithNoReferenceCountForObject( | 154 int PluginVarTracker::GetTrackedWithNoReferenceCountForObject( |
| 280 const PP_Var& plugin_object) { | 155 const PP_Var& plugin_object) { |
| 281 PluginVarInfoMap::iterator found = plugin_var_info_.find( | 156 VarMap::iterator found = GetLiveVar(plugin_object); |
| 282 plugin_object.value.as_id); | 157 if (found == live_vars_.end()) |
| 283 if (found == plugin_var_info_.end()) | |
| 284 return -1; | 158 return -1; |
| 285 return found->second.track_with_no_reference_count; | 159 return found->second.track_with_no_reference_count; |
| 286 } | 160 } |
| 287 | 161 |
| 288 void PluginVarTracker::SendAddRefObjectMsg(const HostVar& host_var) { | 162 int32 PluginVarTracker::AddVarInternal(Var* var, bool take_ref) { |
| 289 int unused; | 163 // Normal adding. |
| 290 host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_AddRefObject( | 164 int32 new_id = VarTracker::AddVarInternal(var, take_ref); |
| 291 INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id, &unused)); | 165 |
| 166 // Need to add proxy objects to the host var map. |
| 167 ProxyObjectVar* proxy_object = var->AsProxyObjectVar(); |
| 168 if (proxy_object) { |
| 169 HostVar host_var(proxy_object->dispatcher(), proxy_object->host_var_id()); |
| 170 DCHECK(host_var_to_plugin_var_.find(host_var) == |
| 171 host_var_to_plugin_var_.end()); // Adding an object twice, use |
| 172 // FindOrMakePluginVarFromHostVar. |
| 173 host_var_to_plugin_var_[host_var] = new_id; |
| 174 } |
| 175 return new_id; |
| 292 } | 176 } |
| 293 | 177 |
| 294 void PluginVarTracker::SendReleaseObjectMsg(const HostVar& host_var) { | 178 void PluginVarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator iter) { |
| 295 host_var.dispatcher->Send(new PpapiHostMsg_PPBVar_ReleaseObject( | 179 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
| 296 INTERFACE_ID_PPB_VAR_DEPRECATED, host_var.host_object_id)); | 180 if (!object) { |
| 181 NOTREACHED(); |
| 182 return; |
| 183 } |
| 184 |
| 185 DCHECK(iter->second.ref_count == 0); |
| 186 |
| 187 // Got an AddRef for an object we have no existing reference for. |
| 188 // We need to tell the browser we've taken a ref. This comes up when the |
| 189 // browser passes an object as an input param and holds a ref for us. |
| 190 // This must be a sync message since otherwise the "addref" will actually |
| 191 // occur after the return to the browser of the sync function that |
| 192 // presumably sent the object. |
| 193 SendAddRefObjectMsg(*object); |
| 297 } | 194 } |
| 298 | 195 |
| 299 PluginVarTracker::PluginVarInfoMap::iterator | 196 void PluginVarTracker::ObjectGettingZeroRef(VarMap::iterator iter) { |
| 300 PluginVarTracker::FindOrMakePluginVarFromHostVar(const PP_Var& var, | 197 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
| 301 PluginDispatcher* dispatcher) { | 198 if (!object) { |
| 199 NOTREACHED(); |
| 200 return; |
| 201 } |
| 202 |
| 203 // Notify the host we're no longer holding our ref. |
| 204 DCHECK(iter->second.ref_count == 0); |
| 205 SendReleaseObjectMsg(*object); |
| 206 |
| 207 // This will optionally delete the info from live_vars_. |
| 208 VarTracker::ObjectGettingZeroRef(iter); |
| 209 } |
| 210 |
| 211 bool PluginVarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) { |
| 212 // Get the info before calling the base class's version of this function, |
| 213 // which may delete the object. |
| 214 ProxyObjectVar* object = iter->second.var->AsProxyObjectVar(); |
| 215 HostVar host_var(object->dispatcher(), object->host_var_id()); |
| 216 |
| 217 if (!VarTracker::DeleteObjectInfoIfNecessary(iter)) |
| 218 return false; |
| 219 |
| 220 // Clean up the host var mapping. |
| 221 DCHECK(host_var_to_plugin_var_.find(host_var) != |
| 222 host_var_to_plugin_var_.end()); |
| 223 host_var_to_plugin_var_.erase(host_var); |
| 224 return true; |
| 225 } |
| 226 |
| 227 PP_Var PluginVarTracker::GetOrCreateObjectVarID(ProxyObjectVar* object) { |
| 228 // We can't use object->GetPPVar() because we don't want to affect the |
| 229 // refcount, so we have to add everything manually here. |
| 230 int32 var_id = object->GetExistingVarID(); |
| 231 if (!var_id) { |
| 232 var_id = AddVarInternal(object, false); |
| 233 object->AssignVarID(var_id); |
| 234 } |
| 235 |
| 236 PP_Var ret; |
| 237 ret.type = PP_VARTYPE_OBJECT; |
| 238 ret.value.as_id = var_id; |
| 239 return ret; |
| 240 } |
| 241 |
| 242 void PluginVarTracker::SendAddRefObjectMsg( |
| 243 const ProxyObjectVar& proxy_object) { |
| 244 int unused; |
| 245 proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_AddRefObject( |
| 246 INTERFACE_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id(), &unused)); |
| 247 } |
| 248 |
| 249 void PluginVarTracker::SendReleaseObjectMsg( |
| 250 const ProxyObjectVar& proxy_object) { |
| 251 proxy_object.dispatcher()->Send(new PpapiHostMsg_PPBVar_ReleaseObject( |
| 252 INTERFACE_ID_PPB_VAR_DEPRECATED, proxy_object.host_var_id())); |
| 253 } |
| 254 |
| 255 scoped_refptr<ProxyObjectVar> PluginVarTracker::FindOrMakePluginVarFromHostVar( |
| 256 const PP_Var& var, |
| 257 PluginDispatcher* dispatcher) { |
| 302 DCHECK(var.type == PP_VARTYPE_OBJECT); | 258 DCHECK(var.type == PP_VARTYPE_OBJECT); |
| 303 HostVar host_var(dispatcher, var.value.as_id); | 259 HostVar host_var(dispatcher, var.value.as_id); |
| 304 | 260 |
| 305 HostVarToPluginVarMap::iterator found = | 261 HostVarToPluginVarMap::iterator found = |
| 306 host_var_to_plugin_var_.find(host_var); | 262 host_var_to_plugin_var_.find(host_var); |
| 307 if (found != host_var_to_plugin_var_.end()) { | 263 if (found == host_var_to_plugin_var_.end()) { |
| 308 PluginVarInfoMap::iterator ret = plugin_var_info_.find(found->second); | 264 // Create a new object. |
| 309 DCHECK(ret != plugin_var_info_.end()); | 265 return scoped_refptr<ProxyObjectVar>( |
| 310 return ret; // Already know about this var return the ID. | 266 new ProxyObjectVar(dispatcher, static_cast<int32>(var.value.as_id))); |
| 311 } | 267 } |
| 312 | 268 |
| 313 // Make a new var, adding references to both maps. | 269 // Have this host var, look up the object. |
| 314 VarID new_plugin_var_id = GetNewVarID(); | 270 VarMap::iterator ret = live_vars_.find(found->second); |
| 315 host_var_to_plugin_var_[host_var] = new_plugin_var_id; | 271 DCHECK(ret != live_vars_.end()); |
| 316 return plugin_var_info_.insert( | |
| 317 std::make_pair(new_plugin_var_id, PluginVarInfo(host_var))).first; | |
| 318 } | |
| 319 | 272 |
| 320 void PluginVarTracker::DeletePluginVarInfoIfNecessary( | 273 // All objects should be proxy objects. |
| 321 PluginVarInfoMap::iterator iter) { | 274 DCHECK(ret->second.var->AsProxyObjectVar()); |
| 322 if (iter->second.ref_count != 0 || | 275 return scoped_refptr<ProxyObjectVar>(ret->second.var->AsProxyObjectVar()); |
| 323 iter->second.track_with_no_reference_count != 0) | |
| 324 return; // Object still alive. | |
| 325 | |
| 326 // Object ref counts are all zero, delete from both maps. | |
| 327 DCHECK(host_var_to_plugin_var_.find(iter->second.host_var) != | |
| 328 host_var_to_plugin_var_.end()); | |
| 329 host_var_to_plugin_var_.erase(iter->second.host_var); | |
| 330 plugin_var_info_.erase(iter); | |
| 331 } | |
| 332 | |
| 333 PluginVarTracker::VarID PluginVarTracker::GetNewVarID() { | |
| 334 if (last_plugin_var_id_ == std::numeric_limits<VarID>::max()) | |
| 335 last_plugin_var_id_ = 0; | |
| 336 return ++last_plugin_var_id_; | |
| 337 } | 276 } |
| 338 | 277 |
| 339 } // namesace proxy | 278 } // namesace proxy |
| 340 } // namespace pp | 279 } // namespace pp |
| OLD | NEW |