Whitelist window states to persist on ASH app windows.
[chromium-blink-merge.git] / ppapi / thunk / enter.h
bloba5a00720fe0fd4feebe84a8f379a3c77098a68e3
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_
8 #include <string>
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"
24 namespace ppapi {
25 namespace thunk {
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.
44 namespace subtle {
46 // Assert that we are holding the proxy lock.
47 PPAPI_THUNK_EXPORT void AssertLockHeld();
49 // This helps us define our RAII Enter classes easily. To make an RAII class
50 // which locks the proxy lock on construction and unlocks on destruction,
51 // inherit from |LockOnEntry<true>| before all other base classes. This ensures
52 // that the lock is acquired before any other base class's constructor can run,
53 // and that the lock is only released after all other destructors have run.
54 // (This order of initialization is guaranteed by C++98/C++11 12.6.2.10).
56 // For cases where you don't want to lock, inherit from |LockOnEntry<false>|.
57 // This allows us to share more code between Enter* and Enter*NoLock classes.
58 template <bool lock_on_entry>
59 struct LockOnEntry;
61 template <>
62 struct LockOnEntry<false> {
63 #if (!NDEBUG)
64 LockOnEntry() {
65 // You must already hold the lock to use Enter*NoLock.
66 AssertLockHeld();
68 ~LockOnEntry() {
69 // You must not release the lock before leaving the scope of the
70 // Enter*NoLock.
71 AssertLockHeld();
73 #endif
76 template <>
77 struct LockOnEntry<true> {
78 LockOnEntry() {
79 ppapi::ProxyLock::Acquire();
81 ~LockOnEntry() {
82 ppapi::ProxyLock::Release();
86 // Keep non-templatized since we need non-inline functions here.
87 class PPAPI_THUNK_EXPORT EnterBase {
88 public:
89 EnterBase();
90 explicit EnterBase(PP_Resource resource);
91 EnterBase(PP_Instance instance, SingletonResourceID resource_id);
92 EnterBase(PP_Resource resource, const PP_CompletionCallback& callback);
93 EnterBase(PP_Instance instance, SingletonResourceID resource_id,
94 const PP_CompletionCallback& callback);
95 virtual ~EnterBase();
97 // Sets the result for calls that use a completion callback. It handles making
98 // sure that "Required" callbacks are scheduled to run asynchronously and
99 // "Blocking" callbacks cause the caller to block. (Interface implementations,
100 // therefore, should not do any special casing based on the type of the
101 // callback.)
103 // Returns the "retval()". This is to support the typical usage of
104 // return enter.SetResult(...);
105 // without having to write a separate "return enter.retval();" line.
106 int32_t SetResult(int32_t result);
108 // Use this value as the return value for the function.
109 int32_t retval() const { return retval_; }
111 // All failure conditions cause retval_ to be set to an appropriate error
112 // code.
113 bool succeeded() const { return retval_ == PP_OK; }
114 bool failed() const { return !succeeded(); }
116 const scoped_refptr<TrackedCallback>& callback() { return callback_; }
118 protected:
119 // Helper function to return a Resource from a PP_Resource. Having this
120 // code be in the non-templatized base keeps us from having to instantiate
121 // it in every template.
122 static Resource* GetResource(PP_Resource resource);
124 // Helper function to return a Resource from a PP_Instance and singleton
125 // resource identifier.
126 static Resource* GetSingletonResource(PP_Instance instance,
127 SingletonResourceID resource_id);
129 void ClearCallback();
131 // Does error handling associated with entering a resource. The resource_base
132 // is the result of looking up the given pp_resource. The object is the
133 // result of converting the base to the desired object (converted to a void*
134 // so this function doesn't have to be templatized). The reason for passing
135 // both resource_base and object is that we can differentiate "bad resource
136 // ID" from "valid resource ID not of the correct type."
138 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and
139 // if report_error is set, log a message to the programmer.
140 void SetStateForResourceError(PP_Resource pp_resource,
141 Resource* resource_base,
142 void* object,
143 bool report_error);
145 // Same as SetStateForResourceError except for function API.
146 void SetStateForFunctionError(PP_Instance pp_instance,
147 void* object,
148 bool report_error);
150 // For Enter objects that need a resource, we'll store a pointer to the
151 // Resource object so that we don't need to look it up more than once. For
152 // Enter objects with no resource, this will be NULL.
153 Resource* resource_;
155 private:
156 bool CallbackIsValid() const;
158 // Checks whether the callback is valid (i.e., if it is either non-blocking,
159 // or blocking and we're on a background thread). If the callback is invalid,
160 // this will set retval_ = PP_ERROR_BLOCKS_MAIN_THREAD, and if report_error is
161 // set, it will log a message to the programmer.
162 void SetStateForCallbackError(bool report_error);
164 // Holds the callback. For Enter objects that aren't given a callback, this
165 // will be NULL.
166 scoped_refptr<TrackedCallback> callback_;
168 int32_t retval_;
171 } // namespace subtle
173 // EnterResource ---------------------------------------------------------------
175 template<typename ResourceT, bool lock_on_entry = true>
176 class EnterResource
177 : public subtle::LockOnEntry<lock_on_entry>, // Must be first; see above.
178 public subtle::EnterBase {
179 public:
180 EnterResource(PP_Resource resource, bool report_error)
181 : EnterBase(resource) {
182 Init(resource, report_error);
184 EnterResource(PP_Resource resource, const PP_CompletionCallback& callback,
185 bool report_error)
186 : EnterBase(resource, callback) {
187 Init(resource, report_error);
189 ~EnterResource() {}
191 ResourceT* object() { return object_; }
192 Resource* resource() { return resource_; }
194 private:
195 void Init(PP_Resource resource, bool report_error) {
196 if (resource_)
197 object_ = resource_->GetAs<ResourceT>();
198 else
199 object_ = NULL;
200 // Validate the resource (note, if both are wrong, we will return
201 // PP_ERROR_BADRESOURCE; last in wins).
202 SetStateForResourceError(resource, resource_, object_, report_error);
205 ResourceT* object_;
207 DISALLOW_COPY_AND_ASSIGN(EnterResource);
210 // ----------------------------------------------------------------------------
212 // Like EnterResource but assumes the lock is already held.
213 template<typename ResourceT>
214 class EnterResourceNoLock : public EnterResource<ResourceT, false> {
215 public:
216 EnterResourceNoLock(PP_Resource resource, bool report_error)
217 : EnterResource<ResourceT, false>(resource, report_error) {
219 EnterResourceNoLock(PP_Resource resource,
220 const PP_CompletionCallback& callback,
221 bool report_error)
222 : EnterResource<ResourceT, false>(resource, callback, report_error) {
226 // EnterInstance ---------------------------------------------------------------
228 class PPAPI_THUNK_EXPORT EnterInstance
229 : public subtle::LockOnEntry<true>, // Must be first; see above.
230 public subtle::EnterBase {
231 public:
232 explicit EnterInstance(PP_Instance instance);
233 EnterInstance(PP_Instance instance,
234 const PP_CompletionCallback& callback);
235 ~EnterInstance();
237 bool succeeded() const { return !!functions_; }
238 bool failed() const { return !functions_; }
240 PPB_Instance_API* functions() const { return functions_; }
242 private:
243 PPB_Instance_API* functions_;
246 class PPAPI_THUNK_EXPORT EnterInstanceNoLock
247 : public subtle::LockOnEntry<false>, // Must be first; see above.
248 public subtle::EnterBase {
249 public:
250 explicit EnterInstanceNoLock(PP_Instance instance);
251 EnterInstanceNoLock(PP_Instance instance,
252 const PP_CompletionCallback& callback);
253 ~EnterInstanceNoLock();
255 PPB_Instance_API* functions() { return functions_; }
257 private:
258 PPB_Instance_API* functions_;
261 // EnterInstanceAPI ------------------------------------------------------------
263 template<typename ApiT, bool lock_on_entry = true>
264 class EnterInstanceAPI
265 : public subtle::LockOnEntry<lock_on_entry>, // Must be first; see above
266 public subtle::EnterBase {
267 public:
268 explicit EnterInstanceAPI(PP_Instance instance)
269 : EnterBase(instance, ApiT::kSingletonResourceID),
270 functions_(NULL) {
271 if (resource_)
272 functions_ = resource_->GetAs<ApiT>();
273 SetStateForFunctionError(instance, functions_, true);
275 EnterInstanceAPI(PP_Instance instance,
276 const PP_CompletionCallback& callback)
277 : EnterBase(instance, ApiT::kSingletonResourceID, callback),
278 functions_(NULL) {
279 if (resource_)
280 functions_ = resource_->GetAs<ApiT>();
281 SetStateForFunctionError(instance, functions_, true);
283 ~EnterInstanceAPI() {}
285 bool succeeded() const { return !!functions_; }
286 bool failed() const { return !functions_; }
288 ApiT* functions() const { return functions_; }
290 private:
291 ApiT* functions_;
294 template<typename ApiT>
295 class EnterInstanceAPINoLock : public EnterInstanceAPI<ApiT, false> {
296 public:
297 explicit EnterInstanceAPINoLock(PP_Instance instance)
298 : EnterInstanceAPI<ApiT, false>(instance) {
302 // EnterResourceCreation -------------------------------------------------------
304 class PPAPI_THUNK_EXPORT EnterResourceCreation
305 : public subtle::LockOnEntry<true>, // Must be first; see above.
306 public subtle::EnterBase {
307 public:
308 explicit EnterResourceCreation(PP_Instance instance);
309 ~EnterResourceCreation();
311 ResourceCreationAPI* functions() { return functions_; }
313 private:
314 ResourceCreationAPI* functions_;
317 class PPAPI_THUNK_EXPORT EnterResourceCreationNoLock
318 : public subtle::LockOnEntry<false>, // Must be first; see above.
319 public subtle::EnterBase {
320 public:
321 explicit EnterResourceCreationNoLock(PP_Instance instance);
322 ~EnterResourceCreationNoLock();
324 ResourceCreationAPI* functions() { return functions_; }
326 private:
327 ResourceCreationAPI* functions_;
330 } // namespace thunk
331 } // namespace ppapi
333 #endif // PPAPI_THUNK_ENTER_H_