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" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 // twice in a few cases. It would be nice not to do that and assert here | 85 // twice in a few cases. It would be nice not to do that and assert here |
86 // instead. | 86 // instead. |
87 if (instance_map_.find(instance) != instance_map_.end()) | 87 if (instance_map_.find(instance) != instance_map_.end()) |
88 return; | 88 return; |
89 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); | 89 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); |
90 } | 90 } |
91 | 91 |
92 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { | 92 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { |
93 InstanceMap::iterator found_instance = instance_map_.find(instance); | 93 InstanceMap::iterator found_instance = instance_map_.find(instance); |
94 | 94 |
95 // Due to the infrastructure of some tests, the instance is uyregistered | 95 // 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 | 96 // twice in a few cases. It would be nice not to do that and assert here |
97 // instead. | 97 // instead. |
98 if (found_instance == instance_map_.end()) | 98 if (found_instance == instance_map_.end()) |
99 return; | 99 return; |
100 | 100 |
101 InstanceData& data = *found_instance->second; | 101 InstanceData& data = *found_instance->second; |
102 | 102 |
103 // Force release all plugin references to resources associated with the | 103 // Force release all plugin references to resources associated with the |
104 // deleted instance. Make a copy since as we iterate through them, each one | 104 // deleted instance. Make a copy since as we iterate through them, each one |
105 // will remove itself from the tracking info individually. | 105 // will remove itself from the tracking info individually. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 if (found == instance_map_.end()) | 148 if (found == instance_map_.end()) |
149 return 0; | 149 return 0; |
150 return static_cast<int>(found->second->resources.size()); | 150 return static_cast<int>(found->second->resources.size()); |
151 } | 151 } |
152 | 152 |
153 PP_Resource ResourceTracker::AddResource(Resource* object) { | 153 PP_Resource ResourceTracker::AddResource(Resource* object) { |
154 // If the plugin manages to create too many resources, don't do crazy stuff. | 154 // If the plugin manages to create too many resources, don't do crazy stuff. |
155 if (last_resource_value_ == kMaxPPId) | 155 if (last_resource_value_ == kMaxPPId) |
156 return 0; | 156 return 0; |
157 | 157 |
158 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); | 158 // Allocate an ID. Note there's a rare error condition below that means we |
159 if (found == instance_map_.end()) { | 159 // could end up not using |new_id|, but that's harmless. |
160 // If you hit this, it's likely somebody forgot to call DidCreateInstance, | 160 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); |
161 // the resource was created with an invalid PP_Instance, or the renderer | 161 |
162 // side tried to create a resource for a plugin that crashed/exited. This | 162 // Some objects have a 0 instance, meaning they aren't associated with any |
163 // could happen for OOP plugins where due to reentrancies in context of | 163 // instance, so they won't be in |instance_map_|. This is (as of this writing) |
164 // outgoing sync calls the renderer can send events after a plugin has | 164 // only true of the PPB_MessageLoop resource for the main thread. |
165 // exited. | 165 if (object->pp_instance()) { |
166 DLOG(INFO) << "Failed to find plugin instance in instance map"; | 166 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); |
167 return 0; | 167 if (found == instance_map_.end()) { |
| 168 // If you hit this, it's likely somebody forgot to call DidCreateInstance, |
| 169 // the resource was created with an invalid PP_Instance, or the renderer |
| 170 // side tried to create a resource for a plugin that crashed/exited. This |
| 171 // could happen for OOP plugins where due to reentrancies in context of |
| 172 // outgoing sync calls the renderer can send events after a plugin has |
| 173 // exited. |
| 174 DLOG(INFO) << "Failed to find plugin instance in instance map"; |
| 175 return 0; |
| 176 } |
| 177 found->second->resources.insert(new_id); |
168 } | 178 } |
169 | 179 |
170 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); | |
171 found->second->resources.insert(new_id); | |
172 | |
173 live_resources_[new_id] = ResourceAndRefCount(object, 0); | 180 live_resources_[new_id] = ResourceAndRefCount(object, 0); |
174 return new_id; | 181 return new_id; |
175 } | 182 } |
176 | 183 |
177 void ResourceTracker::RemoveResource(Resource* object) { | 184 void ResourceTracker::RemoveResource(Resource* object) { |
178 PP_Resource pp_resource = object->pp_resource(); | 185 PP_Resource pp_resource = object->pp_resource(); |
179 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); | 186 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); |
180 if (found != instance_map_.end()) | 187 if (found != instance_map_.end()) |
181 found->second->resources.erase(pp_resource); | 188 found->second->resources.erase(pp_resource); |
182 live_resources_.erase(pp_resource); | 189 live_resources_.erase(pp_resource); |
183 } | 190 } |
184 | 191 |
185 void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { | 192 void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { |
186 // Bug http://crbug.com/134611 indicates that sometimes the resource tracker | 193 // Bug http://crbug.com/134611 indicates that sometimes the resource tracker |
187 // is null here. This should never be the case since if we have a resource in | 194 // is null here. This should never be the case since if we have a resource in |
188 // the tracker, it should always have a valid instance associated with it. | 195 // 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 |
| 197 // instance set to 0). |
189 // As a result, we do some CHECKs here to see what types of problems the | 198 // As a result, we do some CHECKs here to see what types of problems the |
190 // instance might have before dispatching. | 199 // instance might have before dispatching. |
191 // | 200 // |
192 // TODO(brettw) remove these checks when this bug is no longer relevant. | 201 // TODO(brettw) remove these checks when this bug is no longer relevant. |
193 CHECK(object->pp_instance()); | 202 // Note, we do an imperfect check here; this might be a loop that's not the |
| 203 // main one. |
| 204 const bool is_message_loop = (object->AsPPB_MessageLoop_API() != NULL); |
| 205 CHECK(object->pp_instance() || is_message_loop); |
194 CallbackTracker* callback_tracker = | 206 CallbackTracker* callback_tracker = |
195 PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); | 207 PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); |
196 CHECK(callback_tracker); | 208 CHECK(callback_tracker || is_message_loop); |
197 callback_tracker->PostAbortForResource(object->pp_resource()); | 209 if (callback_tracker) |
| 210 callback_tracker->PostAbortForResource(object->pp_resource()); |
198 object->LastPluginRefWasDeleted(); | 211 object->LastPluginRefWasDeleted(); |
199 } | 212 } |
200 | 213 |
201 } // namespace ppapi | 214 } // namespace ppapi |
OLD | NEW |