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 #ifndef PPAPI_THUNK_ENTER_H_ | 5 #ifndef PPAPI_THUNK_ENTER_H_ |
6 #define PPAPI_THUNK_ENTER_H_ | 6 #define PPAPI_THUNK_ENTER_H_ |
7 | 7 |
| 8 #include <string> |
| 9 |
8 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/memory/ref_counted.h" |
| 12 #include "ppapi/c/pp_errors.h" |
9 #include "ppapi/c/pp_resource.h" | 13 #include "ppapi/c/pp_resource.h" |
10 #include "ppapi/shared_impl/api_id.h" | 14 #include "ppapi/shared_impl/api_id.h" |
11 #include "ppapi/shared_impl/ppapi_globals.h" | 15 #include "ppapi/shared_impl/ppapi_globals.h" |
12 #include "ppapi/shared_impl/proxy_lock.h" | 16 #include "ppapi/shared_impl/proxy_lock.h" |
13 #include "ppapi/shared_impl/resource.h" | 17 #include "ppapi/shared_impl/resource.h" |
14 #include "ppapi/shared_impl/resource_tracker.h" | 18 #include "ppapi/shared_impl/resource_tracker.h" |
| 19 #include "ppapi/shared_impl/tracked_callback.h" |
15 #include "ppapi/thunk/ppapi_thunk_export.h" | 20 #include "ppapi/thunk/ppapi_thunk_export.h" |
16 #include "ppapi/thunk/ppb_instance_api.h" | 21 #include "ppapi/thunk/ppb_instance_api.h" |
17 #include "ppapi/thunk/resource_creation_api.h" | 22 #include "ppapi/thunk/resource_creation_api.h" |
18 | 23 |
19 namespace ppapi { | 24 namespace ppapi { |
20 namespace thunk { | 25 namespace thunk { |
21 | 26 |
22 // Enter* helper objects: These objects wrap a call from the C PPAPI into | 27 // Enter* helper objects: These objects wrap a call from the C PPAPI into |
23 // the internal implementation. They make sure the lock is acquired and will | 28 // the internal implementation. They make sure the lock is acquired and will |
24 // automatically set up some stuff for you. | 29 // automatically set up some stuff for you. |
25 // | 30 // |
26 // You should always check whether the enter succeeded before using the object. | 31 // You should always check whether the enter succeeded before using the object. |
27 // If this fails, then the instance or resource ID supplied was invalid. | 32 // If this fails, then the instance or resource ID supplied was invalid. |
28 // | 33 // |
29 // The |report_error| arguments to the constructor should indicate if errors | 34 // The |report_error| arguments to the constructor should indicate if errors |
30 // should be logged to the console. If the calling function expects that the | 35 // should be logged to the console. If the calling function expects that the |
31 // input values are correct (the normal case), this should be set to true. In | 36 // input values are correct (the normal case), this should be set to true. In |
32 // some case like |IsFoo(PP_Resource)| the caller is questioning whether their | 37 // some case like |IsFoo(PP_Resource)| the caller is questioning whether their |
33 // handle is this type, and we don't want to report an error if it's not. | 38 // handle is this type, and we don't want to report an error if it's not. |
34 // | 39 // |
35 // Resource member functions: EnterResource | 40 // Resource member functions: EnterResource |
36 // Automatically interprets the given PP_Resource as a resource ID and sets | 41 // Automatically interprets the given PP_Resource as a resource ID and sets |
37 // up the resource object for you. | 42 // up the resource object for you. |
38 | 43 |
39 namespace subtle { | 44 namespace subtle { |
40 | 45 |
| 46 // Assert that we are holding the proxy lock. |
| 47 PPAPI_THUNK_EXPORT void AssertLockHeld(); |
| 48 |
41 // This helps us define our RAII Enter classes easily. To make an RAII class | 49 // This helps us define our RAII Enter classes easily. To make an RAII class |
42 // which locks the proxy lock on construction and unlocks on destruction, | 50 // which locks the proxy lock on construction and unlocks on destruction, |
43 // inherit from |LockOnEntry<true>|. For cases where you don't want to lock, | 51 // inherit from |LockOnEntry<true>|. For cases where you don't want to lock, |
44 // inherit from |LockOnEntry<false>|. This allows us to share more code between | 52 // inherit from |LockOnEntry<false>|. This allows us to share more code between |
45 // Enter* and Enter*NoLock classes. | 53 // Enter* and Enter*NoLock classes. |
46 template <bool lock_on_entry> | 54 template <bool lock_on_entry> |
47 struct LockOnEntry; | 55 struct LockOnEntry; |
48 | 56 |
49 template <> | 57 template <> |
50 struct LockOnEntry<false> { | 58 struct LockOnEntry<false> { |
51 // TODO(dmichael) assert the lock is held. | 59 #if (!NDEBUG) |
| 60 LockOnEntry() { |
| 61 // You must already hold the lock to use Enter*NoLock. |
| 62 AssertLockHeld(); |
| 63 } |
| 64 ~LockOnEntry() { |
| 65 // You must not release the lock before leaving the scope of the |
| 66 // Enter*NoLock. |
| 67 AssertLockHeld(); |
| 68 } |
| 69 #endif |
52 }; | 70 }; |
53 | 71 |
54 template <> | 72 template <> |
55 struct LockOnEntry<true> { | 73 struct LockOnEntry<true> { |
56 LockOnEntry() { | 74 LockOnEntry() { |
57 ppapi::ProxyLock::Acquire(); | 75 ppapi::ProxyLock::Acquire(); |
58 } | 76 } |
59 ~LockOnEntry() { | 77 ~LockOnEntry() { |
60 ppapi::ProxyLock::Release(); | 78 ppapi::ProxyLock::Release(); |
61 } | 79 } |
62 }; | 80 }; |
63 | 81 |
64 // Keep non-templatized since we need non-inline functions here. | 82 // Keep non-templatized since we need non-inline functions here. |
65 class PPAPI_THUNK_EXPORT EnterBase { | 83 class PPAPI_THUNK_EXPORT EnterBase { |
66 public: | 84 public: |
67 EnterBase(); | 85 EnterBase(); |
68 explicit EnterBase(const PP_CompletionCallback& callback); | 86 explicit EnterBase(PP_Resource resource); |
| 87 EnterBase(PP_Resource resource, const PP_CompletionCallback& callback); |
69 virtual ~EnterBase(); | 88 virtual ~EnterBase(); |
70 | 89 |
71 // Sets the result. | 90 // Sets the result for calls that use a completion callback. It handles making |
| 91 // sure that "Required" callbacks are scheduled to run asynchronously and |
| 92 // "Blocking" callbacks cause the caller to block. (Interface implementations, |
| 93 // therefore, should not do any special casing based on the type of the |
| 94 // callback.) |
72 // | 95 // |
73 // Returns the "retval()". This is to support the typical usage of | 96 // Returns the "retval()". This is to support the typical usage of |
74 // return enter.SetResult(...); | 97 // return enter.SetResult(...); |
75 // without having to write a separate "return enter.retval();" line. | 98 // without having to write a separate "return enter.retval();" line. |
76 int32_t SetResult(int32_t result); | 99 int32_t SetResult(int32_t result); |
77 | 100 |
78 // Use this value as the return value for the function. | 101 // Use this value as the return value for the function. |
79 int32_t retval() const { return retval_; } | 102 int32_t retval() const { return retval_; } |
80 | 103 |
| 104 // All failure conditions cause retval_ to be set to an appropriate error |
| 105 // code. |
| 106 bool succeeded() const { return retval_ == PP_OK; } |
| 107 bool failed() const { return !succeeded(); } |
| 108 |
| 109 const scoped_refptr<TrackedCallback>& callback() { return callback_; } |
| 110 |
81 protected: | 111 protected: |
82 // Helper function to return a Resource from a PP_Resource. Having this | 112 // Helper function to return a Resource from a PP_Resource. Having this |
83 // code be in the non-templatized base keeps us from having to instantiate | 113 // code be in the non-templatized base keeps us from having to instantiate |
84 // it in every template. | 114 // it in every template. |
85 Resource* GetResource(PP_Resource resource) const; | 115 static Resource* GetResource(PP_Resource resource); |
| 116 |
| 117 void ClearCallback(); |
86 | 118 |
87 // Does error handling associated with entering a resource. The resource_base | 119 // Does error handling associated with entering a resource. The resource_base |
88 // is the result of looking up the given pp_resource. The object is the | 120 // is the result of looking up the given pp_resource. The object is the |
89 // result of converting the base to the desired object (converted back to a | 121 // result of converting the base to the desired object (converted to a void* |
90 // Resource* so this function doesn't have to be templatized). The reason for | 122 // so this function doesn't have to be templatized). The reason for passing |
91 // passing both resource_base and object is that we can differentiate "bad | 123 // both resource_base and object is that we can differentiate "bad resource |
92 // resource ID" from "valid resource ID not of the currect type." | 124 // ID" from "valid resource ID not of the correct type." |
93 // | 125 // |
94 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and | 126 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and |
95 // if report_error is set, log a message to the programmer. | 127 // if report_error is set, log a message to the programmer. |
96 void SetStateForResourceError(PP_Resource pp_resource, | 128 void SetStateForResourceError(PP_Resource pp_resource, |
97 Resource* resource_base, | 129 Resource* resource_base, |
98 void* object, | 130 void* object, |
99 bool report_error); | 131 bool report_error); |
100 | 132 |
101 // Same as SetStateForResourceError except for function API. | 133 // Same as SetStateForResourceError except for function API. |
102 void SetStateForFunctionError(PP_Instance pp_instance, | 134 void SetStateForFunctionError(PP_Instance pp_instance, |
103 void* object, | 135 void* object, |
104 bool report_error); | 136 bool report_error); |
105 | 137 |
| 138 // For Enter objects that need a resource, we'll store a pointer to the |
| 139 // Resource object so that we don't need to look it up more than once. For |
| 140 // Enter objects with no resource, this will be NULL. |
| 141 Resource* resource_; |
| 142 |
106 private: | 143 private: |
107 // Holds the callback. The function will only be non-NULL when the | 144 bool CallbackIsValid() const; |
108 // callback is requried. Optional callbacks don't require any special | 145 |
109 // handling from us at this layer. | 146 // Checks whether the callback is valid (i.e., if it is either non-blocking, |
110 PP_CompletionCallback callback_; | 147 // or blocking and we're on a background thread). If the callback is invalid, |
| 148 // this will set retval_ = PP_ERROR_BLOCKS_MAIN_THREAD, and if report_error is |
| 149 // set, it will log a message to the programmer. |
| 150 void SetStateForCallbackError(bool report_error); |
| 151 |
| 152 // Holds the callback. For Enter objects that aren't given a callback, this |
| 153 // will be NULL. |
| 154 scoped_refptr<TrackedCallback> callback_; |
111 | 155 |
112 int32_t retval_; | 156 int32_t retval_; |
113 }; | 157 }; |
114 | 158 |
115 } // namespace subtle | 159 } // namespace subtle |
116 | 160 |
117 // EnterResource --------------------------------------------------------------- | 161 // EnterResource --------------------------------------------------------------- |
118 | 162 |
119 template<typename ResourceT, bool lock_on_entry = true> | 163 template<typename ResourceT, bool lock_on_entry = true> |
120 class EnterResource : public subtle::EnterBase, | 164 class EnterResource : public subtle::EnterBase, |
121 public subtle::LockOnEntry<lock_on_entry> { | 165 public subtle::LockOnEntry<lock_on_entry> { |
122 public: | 166 public: |
123 EnterResource(PP_Resource resource, bool report_error) | 167 EnterResource(PP_Resource resource, bool report_error) |
124 : EnterBase() { | 168 : EnterBase(resource) { |
125 Init(resource, report_error); | 169 Init(resource, report_error); |
126 } | 170 } |
127 EnterResource(PP_Resource resource, | 171 EnterResource(PP_Resource resource, const PP_CompletionCallback& callback, |
128 const PP_CompletionCallback& callback, | |
129 bool report_error) | 172 bool report_error) |
130 : EnterBase(callback) { | 173 : EnterBase(resource, callback) { |
131 Init(resource, report_error); | 174 Init(resource, report_error); |
132 } | 175 } |
133 ~EnterResource() {} | 176 ~EnterResource() {} |
134 | 177 |
135 bool succeeded() const { return !!object_; } | |
136 bool failed() const { return !object_; } | |
137 | |
138 ResourceT* object() { return object_; } | 178 ResourceT* object() { return object_; } |
139 Resource* resource() { return resource_; } | 179 Resource* resource() { return resource_; } |
140 | 180 |
141 private: | 181 private: |
142 void Init(PP_Resource resource, bool report_error) { | 182 void Init(PP_Resource resource, bool report_error) { |
143 resource_ = GetResource(resource); | |
144 if (resource_) | 183 if (resource_) |
145 object_ = resource_->GetAs<ResourceT>(); | 184 object_ = resource_->GetAs<ResourceT>(); |
146 else | 185 else |
147 object_ = NULL; | 186 object_ = NULL; |
| 187 // Validate the resource (note, if both are wrong, we will return |
| 188 // PP_ERROR_BADRESOURCE; last in wins). |
148 SetStateForResourceError(resource, resource_, object_, report_error); | 189 SetStateForResourceError(resource, resource_, object_, report_error); |
149 } | 190 } |
150 | 191 |
151 Resource* resource_; | |
152 ResourceT* object_; | 192 ResourceT* object_; |
153 | 193 |
154 DISALLOW_COPY_AND_ASSIGN(EnterResource); | 194 DISALLOW_COPY_AND_ASSIGN(EnterResource); |
155 }; | 195 }; |
156 | 196 |
157 // ---------------------------------------------------------------------------- | 197 // ---------------------------------------------------------------------------- |
158 | 198 |
159 // Like EnterResource but assumes the lock is already held. | 199 // Like EnterResource but assumes the lock is already held. |
160 template<typename ResourceT> | 200 template<typename ResourceT> |
161 class EnterResourceNoLock : public EnterResource<ResourceT, false> { | 201 class EnterResourceNoLock : public EnterResource<ResourceT, false> { |
162 public: | 202 public: |
163 EnterResourceNoLock(PP_Resource resource, bool report_error) | 203 EnterResourceNoLock(PP_Resource resource, bool report_error) |
164 : EnterResource<ResourceT, false>(resource, report_error) { | 204 : EnterResource<ResourceT, false>(resource, report_error) { |
165 } | 205 } |
| 206 EnterResourceNoLock(PP_Resource resource, PP_CompletionCallback callback, |
| 207 bool report_error) |
| 208 : EnterResource<ResourceT, false>(resource, callback, report_error) { |
| 209 } |
166 }; | 210 }; |
167 | 211 |
168 // EnterInstance --------------------------------------------------------------- | 212 // EnterInstance --------------------------------------------------------------- |
169 | 213 |
170 class PPAPI_THUNK_EXPORT EnterInstance | 214 class PPAPI_THUNK_EXPORT EnterInstance |
171 : public subtle::EnterBase, | 215 : public subtle::EnterBase, |
172 public subtle::LockOnEntry<true> { | 216 public subtle::LockOnEntry<true> { |
173 public: | 217 public: |
174 EnterInstance(PP_Instance instance); | 218 EnterInstance(PP_Instance instance); |
175 EnterInstance(PP_Instance instance, | 219 EnterInstance(PP_Instance instance, |
176 const PP_CompletionCallback& callback); | 220 const PP_CompletionCallback& callback); |
177 ~EnterInstance(); | 221 ~EnterInstance(); |
178 | 222 |
179 bool succeeded() const { return !!functions_; } | 223 bool succeeded() const { return !!functions_; } |
180 bool failed() const { return !functions_; } | 224 bool failed() const { return !functions_; } |
181 | 225 |
182 PPB_Instance_API* functions() { return functions_; } | 226 PPB_Instance_API* functions() { return functions_; } |
183 | 227 |
184 private: | 228 private: |
185 PPB_Instance_API* functions_; | 229 PPB_Instance_API* functions_; |
186 }; | 230 }; |
187 | 231 |
188 class PPAPI_THUNK_EXPORT EnterInstanceNoLock | 232 class PPAPI_THUNK_EXPORT EnterInstanceNoLock |
189 : public subtle::EnterBase, | 233 : public subtle::EnterBase, |
190 public subtle::LockOnEntry<false> { | 234 public subtle::LockOnEntry<false> { |
191 public: | 235 public: |
192 EnterInstanceNoLock(PP_Instance instance); | 236 EnterInstanceNoLock(PP_Instance instance); |
193 //EnterInstanceNoLock(PP_Instance instance, | 237 EnterInstanceNoLock(PP_Instance instance, |
194 // const PP_CompletionCallback& callback); | 238 const PP_CompletionCallback& callback); |
195 ~EnterInstanceNoLock(); | 239 ~EnterInstanceNoLock(); |
196 | 240 |
197 bool succeeded() const { return !!functions_; } | |
198 bool failed() const { return !functions_; } | |
199 | |
200 PPB_Instance_API* functions() { return functions_; } | 241 PPB_Instance_API* functions() { return functions_; } |
201 | 242 |
202 private: | 243 private: |
203 PPB_Instance_API* functions_; | 244 PPB_Instance_API* functions_; |
204 }; | 245 }; |
205 | 246 |
206 // EnterResourceCreation ------------------------------------------------------- | 247 // EnterResourceCreation ------------------------------------------------------- |
207 | 248 |
208 class PPAPI_THUNK_EXPORT EnterResourceCreation | 249 class PPAPI_THUNK_EXPORT EnterResourceCreation |
209 : public subtle::EnterBase, | 250 : public subtle::EnterBase, |
210 public subtle::LockOnEntry<true> { | 251 public subtle::LockOnEntry<true> { |
211 public: | 252 public: |
212 EnterResourceCreation(PP_Instance instance); | 253 EnterResourceCreation(PP_Instance instance); |
213 ~EnterResourceCreation(); | 254 ~EnterResourceCreation(); |
214 | 255 |
215 bool succeeded() const { return !!functions_; } | |
216 bool failed() const { return !functions_; } | |
217 | |
218 ResourceCreationAPI* functions() { return functions_; } | 256 ResourceCreationAPI* functions() { return functions_; } |
219 | 257 |
220 private: | 258 private: |
221 ResourceCreationAPI* functions_; | 259 ResourceCreationAPI* functions_; |
222 }; | 260 }; |
223 | 261 |
224 class PPAPI_THUNK_EXPORT EnterResourceCreationNoLock | 262 class PPAPI_THUNK_EXPORT EnterResourceCreationNoLock |
225 : public subtle::EnterBase, | 263 : public subtle::EnterBase, |
226 public subtle::LockOnEntry<false> { | 264 public subtle::LockOnEntry<false> { |
227 public: | 265 public: |
228 EnterResourceCreationNoLock(PP_Instance instance); | 266 EnterResourceCreationNoLock(PP_Instance instance); |
229 ~EnterResourceCreationNoLock(); | 267 ~EnterResourceCreationNoLock(); |
230 | 268 |
231 bool succeeded() const { return !!functions_; } | |
232 bool failed() const { return !functions_; } | |
233 | |
234 ResourceCreationAPI* functions() { return functions_; } | 269 ResourceCreationAPI* functions() { return functions_; } |
235 | 270 |
236 private: | 271 private: |
237 ResourceCreationAPI* functions_; | 272 ResourceCreationAPI* functions_; |
238 }; | 273 }; |
239 | 274 |
240 } // namespace thunk | 275 } // namespace thunk |
241 } // namespace ppapi | 276 } // namespace ppapi |
242 | 277 |
243 #endif // PPAPI_THUNK_ENTER_H_ | 278 #endif // PPAPI_THUNK_ENTER_H_ |
OLD | NEW |