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/thunk/enter.h" | 5 #include "ppapi/thunk/enter.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
12 #include "ppapi/c/pp_errors.h" | 12 #include "ppapi/c/pp_errors.h" |
13 #include "ppapi/shared_impl/ppapi_globals.h" | 13 #include "ppapi/shared_impl/ppapi_globals.h" |
14 #include "ppapi/shared_impl/tracked_callback.h" | 14 #include "ppapi/shared_impl/tracked_callback.h" |
15 #include "ppapi/thunk/ppb_instance_api.h" | 15 #include "ppapi/thunk/ppb_instance_api.h" |
16 #include "ppapi/thunk/resource_creation_api.h" | 16 #include "ppapi/thunk/resource_creation_api.h" |
17 | 17 |
18 namespace ppapi { | 18 namespace ppapi { |
19 namespace { | 19 namespace { |
20 | 20 |
21 bool IsMainThread() { | 21 bool IsMainThread() { |
22 return | 22 return PpapiGlobals::Get() |
23 PpapiGlobals::Get()->GetMainThreadMessageLoop()->BelongsToCurrentThread(); | 23 ->GetMainThreadMessageLoop() |
| 24 ->BelongsToCurrentThread(); |
24 } | 25 } |
25 | 26 |
26 } // namespace | 27 } // namespace |
27 | 28 |
28 namespace thunk { | 29 namespace thunk { |
29 | 30 |
30 namespace subtle { | 31 namespace subtle { |
31 | 32 |
32 EnterBase::EnterBase() | 33 EnterBase::EnterBase() : resource_(NULL), retval_(PP_OK) { |
33 : resource_(NULL), | |
34 retval_(PP_OK) { | |
35 PpapiGlobals::Get()->MarkPluginIsActive(); | 34 PpapiGlobals::Get()->MarkPluginIsActive(); |
36 } | 35 } |
37 | 36 |
38 EnterBase::EnterBase(PP_Resource resource) | 37 EnterBase::EnterBase(PP_Resource resource) |
39 : resource_(GetResource(resource)), | 38 : resource_(GetResource(resource)), retval_(PP_OK) { |
40 retval_(PP_OK) { | |
41 PpapiGlobals::Get()->MarkPluginIsActive(); | 39 PpapiGlobals::Get()->MarkPluginIsActive(); |
42 } | 40 } |
43 | 41 |
44 EnterBase::EnterBase(PP_Instance instance, SingletonResourceID resource_id) | 42 EnterBase::EnterBase(PP_Instance instance, SingletonResourceID resource_id) |
45 : resource_(GetSingletonResource(instance, resource_id)), | 43 : resource_(GetSingletonResource(instance, resource_id)), retval_(PP_OK) { |
46 retval_(PP_OK) { | |
47 PpapiGlobals::Get()->MarkPluginIsActive(); | 44 PpapiGlobals::Get()->MarkPluginIsActive(); |
48 } | 45 } |
49 | 46 |
50 EnterBase::EnterBase(PP_Resource resource, | 47 EnterBase::EnterBase(PP_Resource resource, |
51 const PP_CompletionCallback& callback) | 48 const PP_CompletionCallback& callback) |
52 : resource_(GetResource(resource)), | 49 : resource_(GetResource(resource)), retval_(PP_OK) { |
53 retval_(PP_OK) { | |
54 callback_ = new TrackedCallback(resource_, callback); | 50 callback_ = new TrackedCallback(resource_, callback); |
55 PpapiGlobals::Get()->MarkPluginIsActive(); | 51 PpapiGlobals::Get()->MarkPluginIsActive(); |
56 } | 52 } |
57 | 53 |
58 EnterBase::EnterBase(PP_Instance instance, SingletonResourceID resource_id, | 54 EnterBase::EnterBase(PP_Instance instance, |
| 55 SingletonResourceID resource_id, |
59 const PP_CompletionCallback& callback) | 56 const PP_CompletionCallback& callback) |
60 : resource_(GetSingletonResource(instance, resource_id)), | 57 : resource_(GetSingletonResource(instance, resource_id)), retval_(PP_OK) { |
61 retval_(PP_OK) { | |
62 if (!resource_) | 58 if (!resource_) |
63 retval_ = PP_ERROR_BADARGUMENT; | 59 retval_ = PP_ERROR_BADARGUMENT; |
64 callback_ = new TrackedCallback(resource_, callback); | 60 callback_ = new TrackedCallback(resource_, callback); |
65 PpapiGlobals::Get()->MarkPluginIsActive(); | 61 PpapiGlobals::Get()->MarkPluginIsActive(); |
66 } | 62 } |
67 | 63 |
68 EnterBase::~EnterBase() { | 64 EnterBase::~EnterBase() { |
69 // callback_ is cleared any time it is run, scheduled to be run, or once we | 65 // callback_ is cleared any time it is run, scheduled to be run, or once we |
70 // know it will be completed asynchronously. So by this point it should be | 66 // know it will be completed asynchronously. So by this point it should be |
71 // NULL. | 67 // NULL. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 } | 127 } |
132 if (callback_.get()) { | 128 if (callback_.get()) { |
133 if (callback_->is_blocking() && IsMainThread()) { | 129 if (callback_->is_blocking() && IsMainThread()) { |
134 // Blocking callbacks are never allowed on the main thread. | 130 // Blocking callbacks are never allowed on the main thread. |
135 callback_->MarkAsCompleted(); | 131 callback_->MarkAsCompleted(); |
136 callback_ = NULL; | 132 callback_ = NULL; |
137 retval_ = PP_ERROR_BLOCKS_MAIN_THREAD; | 133 retval_ = PP_ERROR_BLOCKS_MAIN_THREAD; |
138 if (report_error) { | 134 if (report_error) { |
139 std::string message( | 135 std::string message( |
140 "Blocking callbacks are not allowed on the main thread."); | 136 "Blocking callbacks are not allowed on the main thread."); |
141 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, | 137 PpapiGlobals::Get()->BroadcastLogWithSource( |
142 std::string(), message); | 138 0, PP_LOGLEVEL_ERROR, std::string(), message); |
143 } | 139 } |
144 } else if (!IsMainThread() && | 140 } else if (!IsMainThread() && callback_->has_null_target_loop() && |
145 callback_->has_null_target_loop() && | |
146 !callback_->is_blocking()) { | 141 !callback_->is_blocking()) { |
147 // On a non-main thread, there must be a valid target loop for non- | 142 // On a non-main thread, there must be a valid target loop for non- |
148 // blocking callbacks, or we will have no place to run them. | 143 // blocking callbacks, or we will have no place to run them. |
149 | 144 |
150 // If the callback is required, there's no nice way to tell the plugin. | 145 // If the callback is required, there's no nice way to tell the plugin. |
151 // We can't run their callback asynchronously without a message loop, and | 146 // We can't run their callback asynchronously without a message loop, and |
152 // the plugin won't expect any return code other than | 147 // the plugin won't expect any return code other than |
153 // PP_OK_COMPLETIONPENDING. So we crash to make the problem more obvious. | 148 // PP_OK_COMPLETIONPENDING. So we crash to make the problem more obvious. |
154 if (callback_->is_required()) { | 149 if (callback_->is_required()) { |
155 std::string message("Attempted to use a required callback, but there " | 150 std::string message( |
156 "is no attached message loop on which to run the " | 151 "Attempted to use a required callback, but there " |
157 "callback."); | 152 "is no attached message loop on which to run the " |
158 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, | 153 "callback."); |
159 std::string(), message); | 154 PpapiGlobals::Get()->BroadcastLogWithSource( |
| 155 0, PP_LOGLEVEL_ERROR, std::string(), message); |
160 LOG(FATAL) << message; | 156 LOG(FATAL) << message; |
161 } | 157 } |
162 | 158 |
163 callback_->MarkAsCompleted(); | 159 callback_->MarkAsCompleted(); |
164 callback_ = NULL; | 160 callback_ = NULL; |
165 retval_ = PP_ERROR_NO_MESSAGE_LOOP; | 161 retval_ = PP_ERROR_NO_MESSAGE_LOOP; |
166 if (report_error) { | 162 if (report_error) { |
167 std::string message( | 163 std::string message( |
168 "The calling thread must have a message loop attached."); | 164 "The calling thread must have a message loop attached."); |
169 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, | 165 PpapiGlobals::Get()->BroadcastLogWithSource( |
170 std::string(), message); | 166 0, PP_LOGLEVEL_ERROR, std::string(), message); |
171 } | 167 } |
172 } | 168 } |
173 } | 169 } |
174 } | 170 } |
175 | 171 |
176 void EnterBase::ClearCallback() { | 172 void EnterBase::ClearCallback() { callback_ = NULL; } |
177 callback_ = NULL; | |
178 } | |
179 | 173 |
180 void EnterBase::SetStateForResourceError(PP_Resource pp_resource, | 174 void EnterBase::SetStateForResourceError(PP_Resource pp_resource, |
181 Resource* resource_base, | 175 Resource* resource_base, |
182 void* object, | 176 void* object, |
183 bool report_error) { | 177 bool report_error) { |
184 // Check for callback errors. If we get any, SetStateForCallbackError will | 178 // Check for callback errors. If we get any, SetStateForCallbackError will |
185 // emit a log message. But we also want to check for resource errors. If there | 179 // emit a log message. But we also want to check for resource errors. If there |
186 // are both kinds of errors, we'll emit two log messages and return | 180 // are both kinds of errors, we'll emit two log messages and return |
187 // PP_ERROR_BADRESOURCE. | 181 // PP_ERROR_BADRESOURCE. |
188 SetStateForCallbackError(report_error); | 182 SetStateForCallbackError(report_error); |
(...skipping 12 matching lines...) Expand all Loading... |
201 retval_ = PP_ERROR_BADRESOURCE; | 195 retval_ = PP_ERROR_BADRESOURCE; |
202 } | 196 } |
203 | 197 |
204 // We choose to silently ignore the error when the pp_resource is null | 198 // We choose to silently ignore the error when the pp_resource is null |
205 // because this is a pretty common case and we don't want to have lots | 199 // because this is a pretty common case and we don't want to have lots |
206 // of errors in the log. This should be an obvious case to debug. | 200 // of errors in the log. This should be an obvious case to debug. |
207 if (report_error && pp_resource) { | 201 if (report_error && pp_resource) { |
208 std::string message; | 202 std::string message; |
209 if (resource_base) { | 203 if (resource_base) { |
210 message = base::StringPrintf( | 204 message = base::StringPrintf( |
211 "0x%X is not the correct type for this function.", | 205 "0x%X is not the correct type for this function.", pp_resource); |
212 pp_resource); | |
213 } else { | 206 } else { |
214 message = base::StringPrintf( | 207 message = |
215 "0x%X is not a valid resource ID.", | 208 base::StringPrintf("0x%X is not a valid resource ID.", pp_resource); |
216 pp_resource); | |
217 } | 209 } |
218 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, | 210 PpapiGlobals::Get()->BroadcastLogWithSource( |
219 std::string(), message); | 211 0, PP_LOGLEVEL_ERROR, std::string(), message); |
220 } | 212 } |
221 } | 213 } |
222 | 214 |
223 void EnterBase::SetStateForFunctionError(PP_Instance pp_instance, | 215 void EnterBase::SetStateForFunctionError(PP_Instance pp_instance, |
224 void* object, | 216 void* object, |
225 bool report_error) { | 217 bool report_error) { |
226 // Check for callback errors. If we get any, SetStateForCallbackError will | 218 // Check for callback errors. If we get any, SetStateForCallbackError will |
227 // emit a log message. But we also want to check for instance errors. If there | 219 // emit a log message. But we also want to check for instance errors. If there |
228 // are both kinds of errors, we'll emit two log messages and return | 220 // are both kinds of errors, we'll emit two log messages and return |
229 // PP_ERROR_BADARGUMENT. | 221 // PP_ERROR_BADARGUMENT. |
(...skipping 10 matching lines...) Expand all Loading... |
240 if (callback_.get()) | 232 if (callback_.get()) |
241 callback_->MarkAsCompleted(); | 233 callback_->MarkAsCompleted(); |
242 callback_ = NULL; | 234 callback_ = NULL; |
243 retval_ = PP_ERROR_BADARGUMENT; | 235 retval_ = PP_ERROR_BADARGUMENT; |
244 } | 236 } |
245 | 237 |
246 // We choose to silently ignore the error when the pp_instance is null as | 238 // We choose to silently ignore the error when the pp_instance is null as |
247 // for PP_Resources above. | 239 // for PP_Resources above. |
248 if (report_error && pp_instance) { | 240 if (report_error && pp_instance) { |
249 std::string message; | 241 std::string message; |
250 message = base::StringPrintf( | 242 message = |
251 "0x%X is not a valid instance ID.", | 243 base::StringPrintf("0x%X is not a valid instance ID.", pp_instance); |
252 pp_instance); | 244 PpapiGlobals::Get()->BroadcastLogWithSource( |
253 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, | 245 0, PP_LOGLEVEL_ERROR, std::string(), message); |
254 std::string(), message); | |
255 } | 246 } |
256 } | 247 } |
257 | 248 |
258 } // namespace subtle | 249 } // namespace subtle |
259 | 250 |
260 EnterInstance::EnterInstance(PP_Instance instance) | 251 EnterInstance::EnterInstance(PP_Instance instance) |
261 : EnterBase(), | 252 : EnterBase(), functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { |
262 functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { | |
263 SetStateForFunctionError(instance, functions_, true); | 253 SetStateForFunctionError(instance, functions_, true); |
264 } | 254 } |
265 | 255 |
266 EnterInstance::EnterInstance(PP_Instance instance, | 256 EnterInstance::EnterInstance(PP_Instance instance, |
267 const PP_CompletionCallback& callback) | 257 const PP_CompletionCallback& callback) |
268 : EnterBase(0 /* resource */, callback), | 258 : EnterBase(0 /* resource */, callback), |
269 // TODO(dmichael): This means that the callback_ we get is not associated | 259 // TODO(dmichael): This means that the callback_ we get is not associated |
270 // even with the instance, but we should handle that for | 260 // even with the instance, but we should handle that for |
271 // MouseLock (maybe others?). | 261 // MouseLock (maybe others?). |
272 functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { | 262 functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { |
273 SetStateForFunctionError(instance, functions_, true); | 263 SetStateForFunctionError(instance, functions_, true); |
274 } | 264 } |
275 | 265 |
276 EnterInstance::~EnterInstance() { | 266 EnterInstance::~EnterInstance() {} |
277 } | |
278 | 267 |
279 EnterInstanceNoLock::EnterInstanceNoLock(PP_Instance instance) | 268 EnterInstanceNoLock::EnterInstanceNoLock(PP_Instance instance) |
280 : EnterBase(), | 269 : EnterBase(), functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { |
281 functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { | |
282 SetStateForFunctionError(instance, functions_, true); | 270 SetStateForFunctionError(instance, functions_, true); |
283 } | 271 } |
284 | 272 |
285 EnterInstanceNoLock::EnterInstanceNoLock( | 273 EnterInstanceNoLock::EnterInstanceNoLock(PP_Instance instance, |
286 PP_Instance instance, | 274 const PP_CompletionCallback& callback) |
287 const PP_CompletionCallback& callback) | |
288 : EnterBase(0 /* resource */, callback), | 275 : EnterBase(0 /* resource */, callback), |
289 // TODO(dmichael): This means that the callback_ we get is not associated | 276 // TODO(dmichael): This means that the callback_ we get is not associated |
290 // even with the instance, but we should handle that for | 277 // even with the instance, but we should handle that for |
291 // MouseLock (maybe others?). | 278 // MouseLock (maybe others?). |
292 functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { | 279 functions_(PpapiGlobals::Get()->GetInstanceAPI(instance)) { |
293 SetStateForFunctionError(instance, functions_, true); | 280 SetStateForFunctionError(instance, functions_, true); |
294 } | 281 } |
295 | 282 |
296 EnterInstanceNoLock::~EnterInstanceNoLock() { | 283 EnterInstanceNoLock::~EnterInstanceNoLock() {} |
297 } | |
298 | 284 |
299 EnterResourceCreation::EnterResourceCreation(PP_Instance instance) | 285 EnterResourceCreation::EnterResourceCreation(PP_Instance instance) |
300 : EnterBase(), | 286 : EnterBase(), |
301 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { | 287 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { |
302 SetStateForFunctionError(instance, functions_, true); | 288 SetStateForFunctionError(instance, functions_, true); |
303 } | 289 } |
304 | 290 |
305 EnterResourceCreation::~EnterResourceCreation() { | 291 EnterResourceCreation::~EnterResourceCreation() {} |
306 } | |
307 | 292 |
308 EnterResourceCreationNoLock::EnterResourceCreationNoLock(PP_Instance instance) | 293 EnterResourceCreationNoLock::EnterResourceCreationNoLock(PP_Instance instance) |
309 : EnterBase(), | 294 : EnterBase(), |
310 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { | 295 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { |
311 SetStateForFunctionError(instance, functions_, true); | 296 SetStateForFunctionError(instance, functions_, true); |
312 } | 297 } |
313 | 298 |
314 EnterResourceCreationNoLock::~EnterResourceCreationNoLock() { | 299 EnterResourceCreationNoLock::~EnterResourceCreationNoLock() {} |
315 } | |
316 | 300 |
317 } // namespace thunk | 301 } // namespace thunk |
318 } // namespace ppapi | 302 } // namespace ppapi |
OLD | NEW |