diff options
Diffstat (limited to 'webkit/plugins/ppapi/resource_tracker.cc')
-rw-r--r-- | webkit/plugins/ppapi/resource_tracker.cc | 145 |
1 files changed, 83 insertions, 62 deletions
diff --git a/webkit/plugins/ppapi/resource_tracker.cc b/webkit/plugins/ppapi/resource_tracker.cc index 6507e2d..4874c79 100644 --- a/webkit/plugins/ppapi/resource_tracker.cc +++ b/webkit/plugins/ppapi/resource_tracker.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/rand_util.h" #include "ppapi/c/pp_resource.h" +#include "ppapi/c/pp_var.h" #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" #include "webkit/plugins/ppapi/resource.h" #include "webkit/plugins/ppapi/var.h" @@ -82,18 +83,31 @@ PP_Resource ResourceTracker::AddResource(Resource* resource) { // Add the resource with plugin use-count 1. PP_Resource new_id = MakeTypedId(++last_resource_id_, PP_ID_TYPE_RESOURCE); live_resources_.insert(std::make_pair(new_id, std::make_pair(resource, 1))); - instance_to_resources_[resource->instance()->pp_instance()].insert(new_id); + + // Track associated with the instance. + PP_Instance pp_instance = resource->instance()->pp_instance(); + DCHECK(instance_map_.find(pp_instance) != instance_map_.end()); + instance_map_[pp_instance].resources.insert(new_id); return new_id; } int32 ResourceTracker::AddVar(Var* var) { // If the plugin manages to create 1B strings... - if (last_var_id_ == std::numeric_limits<int32>::max() >> kPPIdTypeBits) { + if (last_var_id_ == std::numeric_limits<int32>::max() >> kPPIdTypeBits) return 0; - } + // Add the resource with plugin use-count 1. int32 new_id = MakeTypedId(++last_var_id_, PP_ID_TYPE_VAR); live_vars_.insert(std::make_pair(new_id, std::make_pair(var, 1))); + + // Object vars must be associated with the instance. + ObjectVar* object_var = var->AsObjectVar(); + if (object_var) { + PP_Instance instance = object_var->instance()->pp_instance(); + DCHECK(instance_map_.find(instance) != instance_map_.end()); + instance_map_[instance].object_vars.insert(new_id); + } + return new_id; } @@ -119,13 +133,12 @@ bool ResourceTracker::UnrefResource(PP_Resource res) { if (i != live_resources_.end()) { if (!--i->second.second) { Resource* to_release = i->second.first; + // LastPluginRefWasDeleted will clear the instance pointer, so save it + // first. + PP_Instance instance = to_release->instance()->pp_instance(); to_release->LastPluginRefWasDeleted(false); - ResourceSet& instance_resource_set = - instance_to_resources_[to_release->instance()->pp_instance()]; - DCHECK(instance_resource_set.find(res) != instance_resource_set.end()); - instance_resource_set.erase(res); - + instance_map_[instance].resources.erase(res); live_resources_.erase(i); } return true; @@ -134,43 +147,21 @@ bool ResourceTracker::UnrefResource(PP_Resource res) { } } -void ResourceTracker::ForceDeletePluginResourceRefs(PP_Resource res) { - DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) - << res << " is not a PP_Resource."; - ResourceMap::iterator i = live_resources_.find(res); - if (i == live_resources_.end()) - return; // Nothing to do. - - i->second.second = 0; - Resource* resource = i->second.first; - - // Must delete from the resource set first since the resource's instance - // pointer will get zeroed out in LastPluginRefWasDeleted. - ResourceSet& resource_set = instance_to_resources_[ - resource->instance()->pp_instance()]; - DCHECK(resource_set.find(res) != resource_set.end()); - resource_set.erase(res); - - resource->LastPluginRefWasDeleted(true); - live_resources_.erase(i); -} - uint32 ResourceTracker::GetLiveObjectsForInstance( PP_Instance instance) const { - InstanceToResourceMap::const_iterator found = - instance_to_resources_.find(instance); - if (found == instance_to_resources_.end()) + InstanceMap::const_iterator found = instance_map_.find(instance); + if (found == instance_map_.end()) return 0; - return static_cast<uint32>(found->second.size()); + return static_cast<uint32>(found->second.resources.size() + + found->second.object_vars.size()); } scoped_refptr<Var> ResourceTracker::GetVar(int32 var_id) const { DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR)) << var_id << " is not a PP_Var ID."; VarMap::const_iterator result = live_vars_.find(var_id); - if (result == live_vars_.end()) { + if (result == live_vars_.end()) return scoped_refptr<Var>(); - } return result->second.first; } @@ -193,26 +184,24 @@ bool ResourceTracker::UnrefVar(int32 var_id) { << var_id << " is not a PP_Var ID."; VarMap::iterator i = live_vars_.find(var_id); if (i != live_vars_.end()) { - if (!--i->second.second) + if (!--i->second.second) { + ObjectVar* object_var = i->second.first->AsObjectVar(); + if (object_var) { + instance_map_[object_var->instance()->pp_instance()].object_vars.erase( + var_id); + } live_vars_.erase(i); + } return true; } return false; } PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) { -#ifndef NDEBUG - // Make sure we're not adding one more than once. - for (InstanceMap::const_iterator i = instance_map_.begin(); - i != instance_map_.end(); ++i) - DCHECK(i->second != instance); -#endif + DCHECK(instance_map_.find(instance->pp_instance()) == instance_map_.end()); - // Use a random 64-bit number for the instance ID. This helps prevent some - // mischeif where you could misallocate resources if you gave a different - // instance ID. - // - // See also AddModule below. + // Use a random number for the instance ID. This helps prevent some + // accidents. See also AddModule below. // // Need to make sure the random number isn't a duplicate or 0. PP_Instance new_instance; @@ -221,32 +210,64 @@ PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) { PP_ID_TYPE_INSTANCE); } while (!new_instance || instance_map_.find(new_instance) != instance_map_.end()); - instance_map_[new_instance] = instance; + + instance_map_[new_instance].instance = instance; return new_instance; } void ResourceTracker::InstanceDeleted(PP_Instance instance) { DLOG_IF(ERROR, !CheckIdType(instance, PP_ID_TYPE_INSTANCE)) << instance << " is not a PP_Instance."; + InstanceMap::iterator found = instance_map_.find(instance); + if (found == instance_map_.end()) { + NOTREACHED(); + return; + } + InstanceData& data = found->second; + // Force release all plugin references to resources associated with the // deleted instance. - ResourceSet& resource_set = instance_to_resources_[instance]; - ResourceSet::iterator i = resource_set.begin(); - while (i != resource_set.end()) { + ResourceSet::iterator cur_res = data.resources.begin(); + while (cur_res != data.resources.end()) { + ResourceMap::iterator found_resource = live_resources_.find(*cur_res); + if (found_resource == live_resources_.end()) { + NOTREACHED(); + } else { + Resource* resource = found_resource->second.first; + + // Must delete from the resource set first since the resource's instance + // pointer will get zeroed out in LastPluginRefWasDeleted. + resource->LastPluginRefWasDeleted(true); + live_resources_.erase(*cur_res); + } + // Iterators to a set are stable so we can iterate the set while the items // are being deleted as long as we're careful not to delete the item we're // holding an iterator to. - ResourceSet::iterator current = i++; - ForceDeletePluginResourceRefs(*current); + ResourceSet::iterator current = cur_res++; + data.resources.erase(current); } - DCHECK(resource_set.empty()); - instance_to_resources_.erase(instance); - - InstanceMap::iterator found = instance_map_.find(instance); - if (found == instance_map_.end()) { - NOTREACHED(); - return; + DCHECK(data.resources.empty()); + + // Force delete all var references. + VarSet::iterator cur_var = data.object_vars.begin(); + while (cur_var != data.object_vars.end()) { + VarSet::iterator current = cur_var++; + + // Tell the corresponding ObjectVar that the instance is gone. + PP_Var object_pp_var; + object_pp_var.type = PP_VARTYPE_OBJECT; + object_pp_var.value.as_id = *current; + scoped_refptr<ObjectVar> object_var(ObjectVar::FromPPVar(object_pp_var)); + if (object_var.get()) + object_var->InstanceDeleted(); + + // Clear the object from the var mapping and the live instance object list. + live_vars_.erase(*current); + data.object_vars.erase(*current); } + DCHECK(data.object_vars.empty()); + instance_map_.erase(found); } @@ -256,7 +277,7 @@ PluginInstance* ResourceTracker::GetInstance(PP_Instance instance) { InstanceMap::iterator found = instance_map_.find(instance); if (found == instance_map_.end()) return NULL; - return found->second; + return found->second.instance; } PP_Module ResourceTracker::AddModule(PluginModule* module) { |