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 |