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
3 // found in the LICENSE file.
5 #ifndef PPAPI_THUNK_ENTER_H_
6 #define PPAPI_THUNK_ENTER_H_
10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/pp_resource.h"
14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/shared_impl/proxy_lock.h"
16 #include "ppapi/shared_impl/resource.h"
17 #include "ppapi/shared_impl/resource_tracker.h"
18 #include "ppapi/shared_impl/singleton_resource_id.h"
19 #include "ppapi/shared_impl/tracked_callback.h"
20 #include "ppapi/thunk/ppapi_thunk_export.h"
21 #include "ppapi/thunk/ppb_instance_api.h"
22 #include "ppapi/thunk/resource_creation_api.h"
27 // Enter* helper objects: These objects wrap a call from the C PPAPI into
28 // the internal implementation. They make sure the lock is acquired and will
29 // automatically set up some stuff for you.
31 // You should always check whether the enter succeeded before using the object.
32 // If this fails, then the instance or resource ID supplied was invalid.
34 // The |report_error| arguments to the constructor should indicate if errors
35 // should be logged to the console. If the calling function expects that the
36 // input values are correct (the normal case), this should be set to true. In
37 // some case like |IsFoo(PP_Resource)| the caller is questioning whether their
38 // handle is this type, and we don't want to report an error if it's not.
40 // Resource member functions: EnterResource
41 // Automatically interprets the given PP_Resource as a resource ID and sets
42 // up the resource object for you.
46 // This helps us define our RAII Enter classes easily. To make an RAII class
47 // which locks the proxy lock on construction and unlocks on destruction,
48 // inherit from |LockOnEntry<true>| before all other base classes. This ensures
49 // that the lock is acquired before any other base class's constructor can run,
50 // and that the lock is only released after all other destructors have run.
51 // (This order of initialization is guaranteed by C++98/C++11 12.6.2.10).
53 // For cases where you don't want to lock, inherit from |LockOnEntry<false>|.
54 // This allows us to share more code between Enter* and Enter*NoLock classes.
55 template <bool lock_on_entry
>
59 struct LockOnEntry
<false> {
62 // You must already hold the lock to use Enter*NoLock.
63 ProxyLock::AssertAcquired();
66 // You must not release the lock before leaving the scope of the
68 ProxyLock::AssertAcquired();
74 struct LockOnEntry
<true> {
76 ppapi::ProxyLock::Acquire();
79 ppapi::ProxyLock::Release();
83 // Keep non-templatized since we need non-inline functions here.
84 class PPAPI_THUNK_EXPORT EnterBase
{
87 explicit EnterBase(PP_Resource resource
);
88 EnterBase(PP_Instance instance
, SingletonResourceID resource_id
);
89 EnterBase(PP_Resource resource
, const PP_CompletionCallback
& callback
);
90 EnterBase(PP_Instance instance
, SingletonResourceID resource_id
,
91 const PP_CompletionCallback
& callback
);
94 // Sets the result for calls that use a completion callback. It handles making
95 // sure that "Required" callbacks are scheduled to run asynchronously and
96 // "Blocking" callbacks cause the caller to block. (Interface implementations,
97 // therefore, should not do any special casing based on the type of the
100 // Returns the "retval()". This is to support the typical usage of
101 // return enter.SetResult(...);
102 // without having to write a separate "return enter.retval();" line.
103 int32_t SetResult(int32_t result
);
105 // Use this value as the return value for the function.
106 int32_t retval() const { return retval_
; }
108 // All failure conditions cause retval_ to be set to an appropriate error
110 bool succeeded() const { return retval_
== PP_OK
; }
111 bool failed() const { return !succeeded(); }
113 const scoped_refptr
<TrackedCallback
>& callback() { return callback_
; }
116 // Helper function to return a Resource from a PP_Resource. Having this
117 // code be in the non-templatized base keeps us from having to instantiate
118 // it in every template.
119 static Resource
* GetResource(PP_Resource resource
);
121 // Helper function to return a Resource from a PP_Instance and singleton
122 // resource identifier.
123 static Resource
* GetSingletonResource(PP_Instance instance
,
124 SingletonResourceID resource_id
);
126 void ClearCallback();
128 // Does error handling associated with entering a resource. The resource_base
129 // is the result of looking up the given pp_resource. The object is the
130 // result of converting the base to the desired object (converted to a void*
131 // so this function doesn't have to be templatized). The reason for passing
132 // both resource_base and object is that we can differentiate "bad resource
133 // ID" from "valid resource ID not of the correct type."
135 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and
136 // if report_error is set, log a message to the programmer.
137 void SetStateForResourceError(PP_Resource pp_resource
,
138 Resource
* resource_base
,
142 // Same as SetStateForResourceError except for function API.
143 void SetStateForFunctionError(PP_Instance pp_instance
,
147 // For Enter objects that need a resource, we'll store a pointer to the
148 // Resource object so that we don't need to look it up more than once. For
149 // Enter objects with no resource, this will be NULL.
153 bool CallbackIsValid() const;
155 // Checks whether the callback is valid (i.e., if it is either non-blocking,
156 // or blocking and we're on a background thread). If the callback is invalid,
157 // this will set retval_ = PP_ERROR_BLOCKS_MAIN_THREAD, and if report_error is
158 // set, it will log a message to the programmer.
159 void SetStateForCallbackError(bool report_error
);
161 // Holds the callback. For Enter objects that aren't given a callback, this
163 scoped_refptr
<TrackedCallback
> callback_
;
168 } // namespace subtle
170 // EnterResource ---------------------------------------------------------------
172 template<typename ResourceT
, bool lock_on_entry
= true>
174 : public subtle::LockOnEntry
<lock_on_entry
>, // Must be first; see above.
175 public subtle::EnterBase
{
177 EnterResource(PP_Resource resource
, bool report_error
)
178 : EnterBase(resource
) {
179 Init(resource
, report_error
);
181 EnterResource(PP_Resource resource
, const PP_CompletionCallback
& callback
,
183 : EnterBase(resource
, callback
) {
184 Init(resource
, report_error
);
188 ResourceT
* object() { return object_
; }
189 Resource
* resource() { return resource_
; }
192 void Init(PP_Resource resource
, bool report_error
) {
194 object_
= resource_
->GetAs
<ResourceT
>();
197 // Validate the resource (note, if both are wrong, we will return
198 // PP_ERROR_BADRESOURCE; last in wins).
199 SetStateForResourceError(resource
, resource_
, object_
, report_error
);
204 DISALLOW_COPY_AND_ASSIGN(EnterResource
);
207 // ----------------------------------------------------------------------------
209 // Like EnterResource but assumes the lock is already held.
210 template<typename ResourceT
>
211 class EnterResourceNoLock
: public EnterResource
<ResourceT
, false> {
213 EnterResourceNoLock(PP_Resource resource
, bool report_error
)
214 : EnterResource
<ResourceT
, false>(resource
, report_error
) {
216 EnterResourceNoLock(PP_Resource resource
,
217 const PP_CompletionCallback
& callback
,
219 : EnterResource
<ResourceT
, false>(resource
, callback
, report_error
) {
223 // EnterInstance ---------------------------------------------------------------
225 class PPAPI_THUNK_EXPORT EnterInstance
226 : public subtle::LockOnEntry
<true>, // Must be first; see above.
227 public subtle::EnterBase
{
229 explicit EnterInstance(PP_Instance instance
);
230 EnterInstance(PP_Instance instance
,
231 const PP_CompletionCallback
& callback
);
234 bool succeeded() const { return !!functions_
; }
235 bool failed() const { return !functions_
; }
237 PPB_Instance_API
* functions() const { return functions_
; }
240 PPB_Instance_API
* functions_
;
243 class PPAPI_THUNK_EXPORT EnterInstanceNoLock
244 : public subtle::LockOnEntry
<false>, // Must be first; see above.
245 public subtle::EnterBase
{
247 explicit EnterInstanceNoLock(PP_Instance instance
);
248 EnterInstanceNoLock(PP_Instance instance
,
249 const PP_CompletionCallback
& callback
);
250 ~EnterInstanceNoLock();
252 PPB_Instance_API
* functions() { return functions_
; }
255 PPB_Instance_API
* functions_
;
258 // EnterInstanceAPI ------------------------------------------------------------
260 template<typename ApiT
, bool lock_on_entry
= true>
261 class EnterInstanceAPI
262 : public subtle::LockOnEntry
<lock_on_entry
>, // Must be first; see above
263 public subtle::EnterBase
{
265 explicit EnterInstanceAPI(PP_Instance instance
)
266 : EnterBase(instance
, ApiT::kSingletonResourceID
),
269 functions_
= resource_
->GetAs
<ApiT
>();
270 SetStateForFunctionError(instance
, functions_
, true);
272 EnterInstanceAPI(PP_Instance instance
,
273 const PP_CompletionCallback
& callback
)
274 : EnterBase(instance
, ApiT::kSingletonResourceID
, callback
),
277 functions_
= resource_
->GetAs
<ApiT
>();
278 SetStateForFunctionError(instance
, functions_
, true);
280 ~EnterInstanceAPI() {}
282 bool succeeded() const { return !!functions_
; }
283 bool failed() const { return !functions_
; }
285 ApiT
* functions() const { return functions_
; }
291 template<typename ApiT
>
292 class EnterInstanceAPINoLock
: public EnterInstanceAPI
<ApiT
, false> {
294 explicit EnterInstanceAPINoLock(PP_Instance instance
)
295 : EnterInstanceAPI
<ApiT
, false>(instance
) {
299 // EnterResourceCreation -------------------------------------------------------
301 class PPAPI_THUNK_EXPORT EnterResourceCreation
302 : public subtle::LockOnEntry
<true>, // Must be first; see above.
303 public subtle::EnterBase
{
305 explicit EnterResourceCreation(PP_Instance instance
);
306 ~EnterResourceCreation();
308 ResourceCreationAPI
* functions() { return functions_
; }
311 ResourceCreationAPI
* functions_
;
314 class PPAPI_THUNK_EXPORT EnterResourceCreationNoLock
315 : public subtle::LockOnEntry
<false>, // Must be first; see above.
316 public subtle::EnterBase
{
318 explicit EnterResourceCreationNoLock(PP_Instance instance
);
319 ~EnterResourceCreationNoLock();
321 ResourceCreationAPI
* functions() { return functions_
; }
324 ResourceCreationAPI
* functions_
;
330 #endif // PPAPI_THUNK_ENTER_H_