| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "webkit/glue/plugins/pepper_resource_tracker.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 #include <set> | |
| 9 | |
| 10 #include "base/lazy_instance.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "base/rand_util.h" | |
| 13 #include "ppapi/c/pp_resource.h" | |
| 14 #include "webkit/glue/plugins/pepper_resource.h" | |
| 15 | |
| 16 static base::LazyInstance<pepper::ResourceTracker> g_resource_tracker( | |
| 17 base::LINKER_INITIALIZED); | |
| 18 | |
| 19 namespace pepper { | |
| 20 | |
| 21 scoped_refptr<Resource> ResourceTracker::GetResource(PP_Resource res) const { | |
| 22 ResourceMap::const_iterator result = live_resources_.find(res); | |
| 23 if (result == live_resources_.end()) { | |
| 24 return scoped_refptr<Resource>(); | |
| 25 } | |
| 26 return result->second.first; | |
| 27 } | |
| 28 | |
| 29 // static | |
| 30 ResourceTracker* ResourceTracker::singleton_override_ = NULL; | |
| 31 | |
| 32 ResourceTracker::ResourceTracker() | |
| 33 : last_id_(0) { | |
| 34 } | |
| 35 | |
| 36 ResourceTracker::~ResourceTracker() { | |
| 37 } | |
| 38 | |
| 39 // static | |
| 40 ResourceTracker* ResourceTracker::Get() { | |
| 41 if (singleton_override_) | |
| 42 return singleton_override_; | |
| 43 return g_resource_tracker.Pointer(); | |
| 44 } | |
| 45 | |
| 46 PP_Resource ResourceTracker::AddResource(Resource* resource) { | |
| 47 // If the plugin manages to create 4B resources... | |
| 48 if (last_id_ == std::numeric_limits<PP_Resource>::max()) { | |
| 49 return 0; | |
| 50 } | |
| 51 // Add the resource with plugin use-count 1. | |
| 52 ++last_id_; | |
| 53 live_resources_.insert(std::make_pair(last_id_, std::make_pair(resource, 1))); | |
| 54 return last_id_; | |
| 55 } | |
| 56 | |
| 57 bool ResourceTracker::AddRefResource(PP_Resource res) { | |
| 58 ResourceMap::iterator i = live_resources_.find(res); | |
| 59 if (i != live_resources_.end()) { | |
| 60 // We don't protect against overflow, since a plugin as malicious as to ref | |
| 61 // once per every byte in the address space could have just as well unrefed | |
| 62 // one time too many. | |
| 63 ++i->second.second; | |
| 64 return true; | |
| 65 } else { | |
| 66 return false; | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 bool ResourceTracker::UnrefResource(PP_Resource res) { | |
| 71 ResourceMap::iterator i = live_resources_.find(res); | |
| 72 if (i != live_resources_.end()) { | |
| 73 if (!--i->second.second) { | |
| 74 i->second.first->StoppedTracking(); | |
| 75 live_resources_.erase(i); | |
| 76 } | |
| 77 return true; | |
| 78 } else { | |
| 79 return false; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 void ResourceTracker::ForceDeletePluginResourceRefs(PP_Resource res) { | |
| 84 ResourceMap::iterator i = live_resources_.find(res); | |
| 85 if (i == live_resources_.end()) | |
| 86 return; // Nothing to do. | |
| 87 | |
| 88 i->second.second = 0; | |
| 89 i->second.first->StoppedTracking(); | |
| 90 live_resources_.erase(i); | |
| 91 } | |
| 92 | |
| 93 uint32 ResourceTracker::GetLiveObjectsForModule(PluginModule* module) const { | |
| 94 // Since this is for testing only, we'll just go through all of them and | |
| 95 // count. | |
| 96 // | |
| 97 // TODO(brettw) we will eventually need to implement more efficient | |
| 98 // module->resource lookup to free resources when a module is unloaded. In | |
| 99 // this case, this function can be implemented using that system. | |
| 100 uint32 count = 0; | |
| 101 for (ResourceMap::const_iterator i = live_resources_.begin(); | |
| 102 i != live_resources_.end(); ++i) | |
| 103 count++; | |
| 104 return count; | |
| 105 } | |
| 106 | |
| 107 PP_Instance ResourceTracker::AddInstance(PluginInstance* instance) { | |
| 108 #ifndef NDEBUG | |
| 109 // Make sure we're not adding one more than once. | |
| 110 for (InstanceMap::const_iterator i = instance_map_.begin(); | |
| 111 i != instance_map_.end(); ++i) | |
| 112 DCHECK(i->second != instance); | |
| 113 #endif | |
| 114 | |
| 115 // Use a random 64-bit number for the instance ID. This helps prevent some | |
| 116 // mischeif where you could misallocate resources if you gave a different | |
| 117 // instance ID. | |
| 118 // | |
| 119 // See also AddModule below. | |
| 120 // | |
| 121 // Need to make sure the random number isn't a duplicate or 0. | |
| 122 PP_Instance new_instance; | |
| 123 do { | |
| 124 new_instance = static_cast<PP_Instance>(base::RandUint64()); | |
| 125 } while (!new_instance || | |
| 126 instance_map_.find(new_instance) != instance_map_.end()); | |
| 127 instance_map_[new_instance] = instance; | |
| 128 return new_instance; | |
| 129 } | |
| 130 | |
| 131 void ResourceTracker::InstanceDeleted(PP_Instance instance) { | |
| 132 InstanceMap::iterator found = instance_map_.find(instance); | |
| 133 if (found == instance_map_.end()) { | |
| 134 NOTREACHED(); | |
| 135 return; | |
| 136 } | |
| 137 instance_map_.erase(found); | |
| 138 } | |
| 139 | |
| 140 PluginInstance* ResourceTracker::GetInstance(PP_Instance instance) { | |
| 141 InstanceMap::iterator found = instance_map_.find(instance); | |
| 142 if (found == instance_map_.end()) | |
| 143 return NULL; | |
| 144 return found->second; | |
| 145 } | |
| 146 | |
| 147 PP_Module ResourceTracker::AddModule(PluginModule* module) { | |
| 148 #ifndef NDEBUG | |
| 149 // Make sure we're not adding one more than once. | |
| 150 for (ModuleMap::const_iterator i = module_map_.begin(); | |
| 151 i != module_map_.end(); ++i) | |
| 152 DCHECK(i->second != module); | |
| 153 #endif | |
| 154 | |
| 155 // See AddInstance above. | |
| 156 PP_Module new_module; | |
| 157 do { | |
| 158 new_module = static_cast<PP_Module>(base::RandUint64()); | |
| 159 } while (!new_module || | |
| 160 module_map_.find(new_module) != module_map_.end()); | |
| 161 module_map_[new_module] = module; | |
| 162 return new_module; | |
| 163 } | |
| 164 | |
| 165 void ResourceTracker::ModuleDeleted(PP_Module module) { | |
| 166 ModuleMap::iterator found = module_map_.find(module); | |
| 167 if (found == module_map_.end()) { | |
| 168 NOTREACHED(); | |
| 169 return; | |
| 170 } | |
| 171 module_map_.erase(found); | |
| 172 } | |
| 173 | |
| 174 PluginModule* ResourceTracker::GetModule(PP_Module module) { | |
| 175 ModuleMap::iterator found = module_map_.find(module); | |
| 176 if (found == module_map_.end()) | |
| 177 return NULL; | |
| 178 return found->second; | |
| 179 } | |
| 180 | |
| 181 // static | |
| 182 void ResourceTracker::SetSingletonOverride(ResourceTracker* tracker) { | |
| 183 DCHECK(!singleton_override_); | |
| 184 singleton_override_ = tracker; | |
| 185 } | |
| 186 | |
| 187 // static | |
| 188 void ResourceTracker::ClearSingletonOverride() { | |
| 189 DCHECK(singleton_override_); | |
| 190 singleton_override_ = NULL; | |
| 191 } | |
| 192 | |
| 193 } // namespace pepper | |
| OLD | NEW |