Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/shared_impl/resource_tracker.h" | 5 #include "ppapi/shared_impl/resource_tracker.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "ppapi/shared_impl/callback_tracker.h" | 10 #include "ppapi/shared_impl/callback_tracker.h" |
| 11 #include "ppapi/shared_impl/id_assignment.h" | 11 #include "ppapi/shared_impl/id_assignment.h" |
| 12 #include "ppapi/shared_impl/ppapi_globals.h" | 12 #include "ppapi/shared_impl/ppapi_globals.h" |
| 13 #include "ppapi/shared_impl/resource.h" | 13 #include "ppapi/shared_impl/resource.h" |
| 14 | 14 |
| 15 namespace ppapi { | 15 namespace ppapi { |
| 16 | 16 |
| 17 ResourceTracker::ResourceTracker() | 17 ResourceTracker::ResourceTracker() |
| 18 : last_resource_value_(0), | 18 : last_resource_value_(0), |
| 19 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 19 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 20 } | 20 } |
| 21 | 21 |
| 22 ResourceTracker::~ResourceTracker() { | 22 ResourceTracker::~ResourceTracker() { |
| 23 } | 23 } |
| 24 | 24 |
| 25 Resource* ResourceTracker::GetResource(PP_Resource res) const { | 25 Resource* ResourceTracker::GetResource(PP_Resource res) const { |
| 26 CHECK(thread_checker_.CalledOnValidThread()); | |
| 26 ResourceMap::const_iterator i = live_resources_.find(res); | 27 ResourceMap::const_iterator i = live_resources_.find(res); |
| 27 if (i == live_resources_.end()) | 28 if (i == live_resources_.end()) |
| 28 return NULL; | 29 return NULL; |
| 29 return i->second.first; | 30 return i->second.first; |
| 30 } | 31 } |
| 31 | 32 |
| 32 void ResourceTracker::AddRefResource(PP_Resource res) { | 33 void ResourceTracker::AddRefResource(PP_Resource res) { |
| 34 CHECK(thread_checker_.CalledOnValidThread()); | |
| 33 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) | 35 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
| 34 << res << " is not a PP_Resource."; | 36 << res << " is not a PP_Resource."; |
| 35 ResourceMap::iterator i = live_resources_.find(res); | 37 ResourceMap::iterator i = live_resources_.find(res); |
| 36 if (i == live_resources_.end()) | 38 if (i == live_resources_.end()) |
| 37 return; | 39 return; |
| 38 | 40 |
| 39 // Prevent overflow of refcount. | 41 // Prevent overflow of refcount. |
| 40 if (i->second.second == | 42 if (i->second.second == |
| 41 std::numeric_limits<ResourceAndRefCount::second_type>::max()) | 43 std::numeric_limits<ResourceAndRefCount::second_type>::max()) |
| 42 return; | 44 return; |
| 43 | 45 |
| 44 // When we go from 0 to 1 plugin ref count, keep an additional "real" ref | 46 // When we go from 0 to 1 plugin ref count, keep an additional "real" ref |
| 45 // on its behalf. | 47 // on its behalf. |
| 46 if (i->second.second == 0) | 48 if (i->second.second == 0) |
| 47 i->second.first->AddRef(); | 49 i->second.first->AddRef(); |
| 48 | 50 |
| 49 i->second.second++; | 51 i->second.second++; |
| 50 return; | 52 return; |
| 51 } | 53 } |
| 52 | 54 |
| 53 void ResourceTracker::ReleaseResource(PP_Resource res) { | 55 void ResourceTracker::ReleaseResource(PP_Resource res) { |
| 56 CHECK(thread_checker_.CalledOnValidThread()); | |
| 54 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) | 57 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
| 55 << res << " is not a PP_Resource."; | 58 << res << " is not a PP_Resource."; |
| 56 ResourceMap::iterator i = live_resources_.find(res); | 59 ResourceMap::iterator i = live_resources_.find(res); |
| 57 if (i == live_resources_.end()) | 60 if (i == live_resources_.end()) |
| 58 return; | 61 return; |
| 59 | 62 |
| 60 // Prevent underflow of refcount. | 63 // Prevent underflow of refcount. |
| 61 if (i->second.second == 0) | 64 if (i->second.second == 0) |
| 62 return; | 65 return; |
| 63 | 66 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 74 | 77 |
| 75 void ResourceTracker::ReleaseResourceSoon(PP_Resource res) { | 78 void ResourceTracker::ReleaseResourceSoon(PP_Resource res) { |
| 76 MessageLoop::current()->PostNonNestableTask( | 79 MessageLoop::current()->PostNonNestableTask( |
| 77 FROM_HERE, | 80 FROM_HERE, |
| 78 base::Bind(&ResourceTracker::ReleaseResource, | 81 base::Bind(&ResourceTracker::ReleaseResource, |
| 79 weak_ptr_factory_.GetWeakPtr(), | 82 weak_ptr_factory_.GetWeakPtr(), |
| 80 res)); | 83 res)); |
| 81 } | 84 } |
| 82 | 85 |
| 83 void ResourceTracker::DidCreateInstance(PP_Instance instance) { | 86 void ResourceTracker::DidCreateInstance(PP_Instance instance) { |
| 87 CHECK(thread_checker_.CalledOnValidThread()); | |
| 84 // Due to the infrastructure of some tests, the instance is registered | 88 // Due to the infrastructure of some tests, the instance is registered |
| 85 // twice in a few cases. It would be nice not to do that and assert here | 89 // twice in a few cases. It would be nice not to do that and assert here |
| 86 // instead. | 90 // instead. |
| 87 if (instance_map_.find(instance) != instance_map_.end()) | 91 if (instance_map_.find(instance) != instance_map_.end()) |
| 88 return; | 92 return; |
| 89 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); | 93 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); |
| 90 } | 94 } |
| 91 | 95 |
| 92 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { | 96 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { |
| 97 CHECK(thread_checker_.CalledOnValidThread()); | |
| 93 InstanceMap::iterator found_instance = instance_map_.find(instance); | 98 InstanceMap::iterator found_instance = instance_map_.find(instance); |
| 94 | 99 |
| 95 // Due to the infrastructure of some tests, the instance is unregistered | 100 // Due to the infrastructure of some tests, the instance is unregistered |
| 96 // twice in a few cases. It would be nice not to do that and assert here | 101 // twice in a few cases. It would be nice not to do that and assert here |
| 97 // instead. | 102 // instead. |
| 98 if (found_instance == instance_map_.end()) | 103 if (found_instance == instance_map_.end()) |
| 99 return; | 104 return; |
| 100 | 105 |
| 101 InstanceData& data = *found_instance->second; | 106 InstanceData& data = *found_instance->second; |
| 102 | 107 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 ResourceMap::iterator found_resource = live_resources_.find(*cur); | 142 ResourceMap::iterator found_resource = live_resources_.find(*cur); |
| 138 if (found_resource != live_resources_.end()) | 143 if (found_resource != live_resources_.end()) |
| 139 found_resource->second.first->InstanceWasDeleted(); | 144 found_resource->second.first->InstanceWasDeleted(); |
| 140 cur++; | 145 cur++; |
| 141 } | 146 } |
| 142 | 147 |
| 143 instance_map_.erase(instance); | 148 instance_map_.erase(instance); |
| 144 } | 149 } |
| 145 | 150 |
| 146 int ResourceTracker::GetLiveObjectsForInstance(PP_Instance instance) const { | 151 int ResourceTracker::GetLiveObjectsForInstance(PP_Instance instance) const { |
| 152 CHECK(thread_checker_.CalledOnValidThread()); | |
| 147 InstanceMap::const_iterator found = instance_map_.find(instance); | 153 InstanceMap::const_iterator found = instance_map_.find(instance); |
| 148 if (found == instance_map_.end()) | 154 if (found == instance_map_.end()) |
| 149 return 0; | 155 return 0; |
| 150 return static_cast<int>(found->second->resources.size()); | 156 return static_cast<int>(found->second->resources.size()); |
| 151 } | 157 } |
| 152 | 158 |
| 153 PP_Resource ResourceTracker::AddResource(Resource* object) { | 159 PP_Resource ResourceTracker::AddResource(Resource* object) { |
| 160 CHECK(thread_checker_.CalledOnValidThread()); | |
| 154 // If the plugin manages to create too many resources, don't do crazy stuff. | 161 // If the plugin manages to create too many resources, don't do crazy stuff. |
| 155 if (last_resource_value_ == kMaxPPId) | 162 if (last_resource_value_ == kMaxPPId) |
| 156 return 0; | 163 return 0; |
| 157 | 164 |
| 158 // Allocate an ID. Note there's a rare error condition below that means we | 165 // Allocate an ID. Note there's a rare error condition below that means we |
| 159 // could end up not using |new_id|, but that's harmless. | 166 // could end up not using |new_id|, but that's harmless. |
| 160 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); | 167 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); |
| 161 | 168 |
| 162 // Some objects have a 0 instance, meaning they aren't associated with any | 169 // Some objects have a 0 instance, meaning they aren't associated with any |
| 163 // instance, so they won't be in |instance_map_|. This is (as of this writing) | 170 // instance, so they won't be in |instance_map_|. This is (as of this writing) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 175 return 0; | 182 return 0; |
| 176 } | 183 } |
| 177 found->second->resources.insert(new_id); | 184 found->second->resources.insert(new_id); |
| 178 } | 185 } |
| 179 | 186 |
| 180 live_resources_[new_id] = ResourceAndRefCount(object, 0); | 187 live_resources_[new_id] = ResourceAndRefCount(object, 0); |
| 181 return new_id; | 188 return new_id; |
| 182 } | 189 } |
| 183 | 190 |
| 184 void ResourceTracker::RemoveResource(Resource* object) { | 191 void ResourceTracker::RemoveResource(Resource* object) { |
| 192 CHECK(thread_checker_.CalledOnValidThread()); | |
| 185 PP_Resource pp_resource = object->pp_resource(); | 193 PP_Resource pp_resource = object->pp_resource(); |
| 186 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); | 194 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); |
| 187 if (found != instance_map_.end()) | 195 if (found != instance_map_.end()) |
| 188 found->second->resources.erase(pp_resource); | 196 found->second->resources.erase(pp_resource); |
| 189 live_resources_.erase(pp_resource); | 197 live_resources_.erase(pp_resource); |
| 190 } | 198 } |
| 191 | 199 |
| 192 void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { | 200 void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { |
|
dmichael (off chromium)
2012/09/06 02:57:26
Is there any reason not to check here too? Poking
raymes
2012/09/06 16:23:59
Done.
| |
| 193 // Bug http://crbug.com/134611 indicates that sometimes the resource tracker | 201 // Bug http://crbug.com/134611 indicates that sometimes the resource tracker |
| 194 // is null here. This should never be the case since if we have a resource in | 202 // is null here. This should never be the case since if we have a resource in |
| 195 // the tracker, it should always have a valid instance associated with it | 203 // the tracker, it should always have a valid instance associated with it |
| 196 // (except for the resource for the main thread's message loop, which has | 204 // (except for the resource for the main thread's message loop, which has |
| 197 // instance set to 0). | 205 // instance set to 0). |
| 198 // As a result, we do some CHECKs here to see what types of problems the | 206 // As a result, we do some CHECKs here to see what types of problems the |
| 199 // instance might have before dispatching. | 207 // instance might have before dispatching. |
| 200 // | 208 // |
| 201 // TODO(brettw) remove these checks when this bug is no longer relevant. | 209 // TODO(brettw) remove these checks when this bug is no longer relevant. |
| 202 // Note, we do an imperfect check here; this might be a loop that's not the | 210 // Note, we do an imperfect check here; this might be a loop that's not the |
| 203 // main one. | 211 // main one. |
| 204 const bool is_message_loop = (object->AsPPB_MessageLoop_API() != NULL); | 212 const bool is_message_loop = (object->AsPPB_MessageLoop_API() != NULL); |
| 205 CHECK(object->pp_instance() || is_message_loop); | 213 CHECK(object->pp_instance() || is_message_loop); |
| 206 CallbackTracker* callback_tracker = | 214 CallbackTracker* callback_tracker = |
| 207 PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); | 215 PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); |
| 208 CHECK(callback_tracker || is_message_loop); | 216 CHECK(callback_tracker || is_message_loop); |
| 209 if (callback_tracker) | 217 if (callback_tracker) |
| 210 callback_tracker->PostAbortForResource(object->pp_resource()); | 218 callback_tracker->PostAbortForResource(object->pp_resource()); |
| 211 object->LastPluginRefWasDeleted(); | 219 object->LastPluginRefWasDeleted(); |
| 212 } | 220 } |
| 213 | 221 |
| 214 } // namespace ppapi | 222 } // namespace ppapi |
| OLD | NEW |