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 "base/synchronization/lock.h" | |
13 #include "ppapi/c/pp_errors.h" | |
9 #include "ppapi/c/pp_resource.h" | 14 #include "ppapi/c/pp_resource.h" |
10 #include "ppapi/shared_impl/api_id.h" | 15 #include "ppapi/shared_impl/api_id.h" |
11 #include "ppapi/shared_impl/function_group_base.h" | 16 #include "ppapi/shared_impl/function_group_base.h" |
12 #include "ppapi/shared_impl/ppapi_globals.h" | 17 #include "ppapi/shared_impl/ppapi_globals.h" |
13 #include "ppapi/shared_impl/proxy_lock.h" | 18 #include "ppapi/shared_impl/proxy_lock.h" |
14 #include "ppapi/shared_impl/resource.h" | 19 #include "ppapi/shared_impl/resource.h" |
15 #include "ppapi/shared_impl/resource_tracker.h" | 20 #include "ppapi/shared_impl/resource_tracker.h" |
16 #include "ppapi/thunk/ppapi_thunk_export.h" | 21 #include "ppapi/thunk/ppapi_thunk_export.h" |
17 #include "ppapi/thunk/ppb_instance_api.h" | 22 #include "ppapi/thunk/ppb_instance_api.h" |
18 #include "ppapi/thunk/resource_creation_api.h" | 23 #include "ppapi/thunk/resource_creation_api.h" |
19 | 24 |
20 namespace ppapi { | 25 namespace ppapi { |
26 class TrackedCallback; | |
27 | |
21 namespace thunk { | 28 namespace thunk { |
22 | 29 |
23 // Enter* helper objects: These objects wrap a call from the C PPAPI into | 30 // Enter* helper objects: These objects wrap a call from the C PPAPI into |
24 // the internal implementation. They make sure the lock is acquired and will | 31 // the internal implementation. They make sure the lock is acquired and will |
25 // automatically set up some stuff for you. | 32 // automatically set up some stuff for you. |
26 // | 33 // |
27 // You should always check whether the enter succeeded before using the object. | 34 // You should always check whether the enter succeeded before using the object. |
28 // If this fails, then the instance or resource ID supplied was invalid. | 35 // If this fails, then the instance or resource ID supplied was invalid. |
29 // | 36 // |
30 // The |report_error| arguments to the constructor should indicate if errors | 37 // The |report_error| arguments to the constructor should indicate if errors |
(...skipping 15 matching lines...) Expand all Loading... | |
46 // This helps us define our RAII Enter classes easily. To make an RAII class | 53 // 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, | 54 // which locks the proxy lock on construction and unlocks on destruction, |
48 // inherit from |LockOnEntry<true>|. For cases where you don't want to lock, | 55 // inherit from |LockOnEntry<true>|. For cases where you don't want to lock, |
49 // inherit from |LockOnEntry<false>|. This allows us to share more code between | 56 // inherit from |LockOnEntry<false>|. This allows us to share more code between |
50 // Enter* and Enter*NoLock classes. | 57 // Enter* and Enter*NoLock classes. |
51 template <bool lock_on_entry> | 58 template <bool lock_on_entry> |
52 struct LockOnEntry; | 59 struct LockOnEntry; |
53 | 60 |
54 template <> | 61 template <> |
55 struct LockOnEntry<false> { | 62 struct LockOnEntry<false> { |
56 // TODO(dmichael) assert the lock is held. | 63 #if (!NDEBUG) |
64 LockOnEntry() { | |
65 // You must already hold the lock to use Enter*NoLock. | |
66 AssertLockHeld(); | |
67 } | |
68 ~LockOnEntry() { | |
69 // You must not release the lock before leaving the scope of the | |
70 // Enter*NoLock. | |
71 AssertLockHeld(); | |
72 } | |
73 private: | |
74 static void AssertLockHeld() { | |
75 base::Lock* proxy_lock = PpapiGlobals::Get()->GetProxyLock(); | |
76 if (proxy_lock) | |
77 proxy_lock->AssertAcquired(); | |
78 } | |
79 #endif | |
57 }; | 80 }; |
58 | 81 |
59 template <> | 82 template <> |
60 struct LockOnEntry<true> { | 83 struct LockOnEntry<true> { |
61 LockOnEntry() { | 84 LockOnEntry() { |
62 ppapi::ProxyLock::Acquire(); | 85 ppapi::ProxyLock::Acquire(); |
63 } | 86 } |
64 ~LockOnEntry() { | 87 ~LockOnEntry() { |
65 ppapi::ProxyLock::Release(); | 88 ppapi::ProxyLock::Release(); |
66 } | 89 } |
67 }; | 90 }; |
68 | 91 |
69 // Keep non-templatized since we need non-inline functions here. | 92 // Keep non-templatized since we need non-inline functions here. |
70 class PPAPI_THUNK_EXPORT EnterBase { | 93 class PPAPI_THUNK_EXPORT EnterBase { |
71 public: | 94 public: |
72 EnterBase(); | 95 EnterBase(); |
73 explicit EnterBase(const PP_CompletionCallback& callback); | 96 explicit EnterBase(PP_Resource resource); |
97 EnterBase(PP_Resource resource, const PP_CompletionCallback& callback); | |
74 virtual ~EnterBase(); | 98 virtual ~EnterBase(); |
75 | 99 |
76 // Sets the result. | 100 // Sets the result for calls that use a completion callback. It handles making |
101 // sure that "Required" callbacks are scheduled to run asynchronously and | |
102 // "Blocking" callbacks cause the caller to block. (Interface implementations, | |
103 // therefore, should not do any special casing based on the type of the | |
104 // callback.) | |
77 // | 105 // |
78 // Returns the "retval()". This is to support the typical usage of | 106 // Returns the "retval()". This is to support the typical usage of |
79 // return enter.SetResult(...); | 107 // return enter.SetResult(...); |
80 // without having to write a separate "return enter.retval();" line. | 108 // without having to write a separate "return enter.retval();" line. |
81 int32_t SetResult(int32_t result); | 109 int32_t SetResult(int32_t result); |
82 | 110 |
83 // Use this value as the return value for the function. | 111 // Use this value as the return value for the function. |
84 int32_t retval() const { return retval_; } | 112 int32_t retval() const { return retval_; } |
85 | 113 |
114 // All failure conditions cause retval_ to be set to an appropriate error | |
115 // code. | |
116 bool succeeded() const { return retval_ == PP_OK; } | |
117 bool failed() const { return !succeeded(); } | |
118 | |
119 const scoped_refptr<TrackedCallback>& callback() { return callback_; } | |
120 | |
86 protected: | 121 protected: |
87 // Helper function to return a function group from a PP_Instance. Having this | 122 // Helper function to return a function group from a PP_Instance. Having this |
88 // code be in the non-templatized base keeps us from having to instantiate | 123 // code be in the non-templatized base keeps us from having to instantiate |
89 // it in every template. | 124 // it in every template. |
90 FunctionGroupBase* GetFunctions(PP_Instance instance, ApiID id) const; | 125 FunctionGroupBase* GetFunctions(PP_Instance instance, ApiID id) const; |
91 | 126 |
92 // Helper function to return a Resource from a PP_Resource. Having this | 127 // Helper function to return a Resource from a PP_Resource. Having this |
93 // code be in the non-templatized base keeps us from having to instantiate | 128 // code be in the non-templatized base keeps us from having to instantiate |
94 // it in every template. | 129 // it in every template. |
95 Resource* GetResource(PP_Resource resource) const; | 130 static Resource* GetResource(PP_Resource resource); |
131 | |
132 // Checks whether the callback is valid (i.e., if it is either non-blocking, | |
133 // or blocking and we're on a background thread). If the callback is invalid, | |
134 // this will set retval_ = PP_ERROR_BLOCKS_MAIN_THREAD, and if report_error is | |
135 // set, it will log a message to the programmer. | |
136 void SetStateForCallbackError(bool report_error); | |
137 bool CallbackIsValid() const; | |
138 void ClearCallback(); | |
96 | 139 |
97 // Does error handling associated with entering a resource. The resource_base | 140 // Does error handling associated with entering a resource. The resource_base |
98 // is the result of looking up the given pp_resource. The object is the | 141 // is the result of looking up the given pp_resource. The object is the |
99 // result of converting the base to the desired object (converted back to a | 142 // result of converting the base to the desired object (converted to a void* |
100 // Resource* so this function doesn't have to be templatized). The reason for | 143 // so this function doesn't have to be templatized). The reason for passing |
101 // passing both resource_base and object is that we can differentiate "bad | 144 // both resource_base and object is that we can differentiate "bad resource |
102 // resource ID" from "valid resource ID not of the currect type." | 145 // ID" from "valid resource ID not of the correct type." |
103 // | 146 // |
104 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and | 147 // This will set retval_ = PP_ERROR_BADRESOURCE if the object is invalid, and |
105 // if report_error is set, log a message to the programmer. | 148 // if report_error is set, log a message to the programmer. |
106 void SetStateForResourceError(PP_Resource pp_resource, | 149 void SetStateForResourceError(PP_Resource pp_resource, |
107 Resource* resource_base, | 150 Resource* resource_base, |
108 void* object, | 151 void* object, |
109 bool report_error); | 152 bool report_error); |
110 | 153 |
111 // Same as SetStateForResourceError except for function API. | 154 // Same as SetStateForResourceError except for function API. |
112 void SetStateForFunctionError(PP_Instance pp_instance, | 155 void SetStateForFunctionError(PP_Instance pp_instance, |
113 void* object, | 156 void* object, |
114 bool report_error); | 157 bool report_error); |
115 | 158 |
159 // For Enter objects that need a resource, we'll store a pointer to the | |
160 // Resource object so that we don't need to look it up more than once. For | |
161 // Enter objects with no resource, this will be NULL. | |
162 Resource* resource_; | |
brettw
2012/04/20 18:24:29
I'm worried about this. We do a bunch of stuff on
dmichael (off chromium)
2012/05/16 22:18:34
Note that EnterResource already stores it and expo
brettw
2012/05/20 17:46:46
Can you put a big scary warning here not to use it
dmichael (off chromium)
2012/05/22 18:08:38
Will do.
| |
163 | |
116 private: | 164 private: |
117 // Holds the callback. The function will only be non-NULL when the | 165 // Holds the callback. For Enter objects that aren't given a callback, this |
118 // callback is requried. Optional callbacks don't require any special | 166 // will be NULL. |
119 // handling from us at this layer. | 167 scoped_refptr<TrackedCallback> callback_; |
120 PP_CompletionCallback callback_; | |
121 | 168 |
122 int32_t retval_; | 169 int32_t retval_; |
123 }; | 170 }; |
124 | 171 |
125 } // namespace subtle | 172 } // namespace subtle |
126 | 173 |
127 // EnterFunction -------------------------------------------------------------- | 174 // EnterFunction -------------------------------------------------------------- |
128 | 175 |
129 template<typename FunctionsT, bool lock_on_entry = true> | 176 template<typename FunctionsT, bool lock_on_entry = true> |
130 class EnterFunction : public subtle::EnterBase, | 177 class EnterFunction : public subtle::EnterBase, |
131 public subtle::LockOnEntry<lock_on_entry> { | 178 public subtle::LockOnEntry<lock_on_entry> { |
132 public: | 179 public: |
133 EnterFunction(PP_Instance instance, bool report_error) | 180 EnterFunction(PP_Instance instance, bool report_error) |
134 : EnterBase() { | 181 : EnterBase(instance) { |
135 Init(instance, report_error); | 182 Init(instance, report_error); |
136 } | 183 } |
137 EnterFunction(PP_Instance instance, | 184 EnterFunction(PP_Instance instance, |
138 const PP_CompletionCallback& callback, | 185 const PP_CompletionCallback& callback, |
139 bool report_error) | 186 bool report_error) |
140 : EnterBase(callback) { | 187 : EnterBase(0 /* resource */, callback) { |
188 // TODO(dmichael): This means that the callback_ we get is not associated | |
189 // even with the instance, but we should handle that for | |
190 // MouseLock (maybe others?). | |
141 Init(instance, report_error); | 191 Init(instance, report_error); |
142 } | 192 } |
143 | 193 |
144 ~EnterFunction() {} | 194 ~EnterFunction() {} |
145 | 195 |
146 bool succeeded() const { return !!functions_; } | |
147 bool failed() const { return !functions_; } | |
148 | |
149 FunctionsT* functions() { return functions_; } | 196 FunctionsT* functions() { return functions_; } |
150 | 197 |
151 private: | 198 private: |
152 void Init(PP_Instance instance, bool report_error) { | 199 void Init(PP_Instance instance, bool report_error) { |
153 FunctionGroupBase* base = GetFunctions(instance, FunctionsT::kApiID); | 200 FunctionGroupBase* base = GetFunctions(instance, FunctionsT::kApiID); |
154 if (base) | 201 if (base) |
155 functions_ = base->GetAs<FunctionsT>(); | 202 functions_ = base->GetAs<FunctionsT>(); |
156 else | 203 else |
157 functions_ = NULL; | 204 functions_ = NULL; |
205 // Validate the callback. | |
206 SetStateForCallbackError(report_error); | |
brettw
2012/04/20 18:24:29
I think you should just call this from the beginni
dmichael (off chromium)
2012/05/16 22:18:34
Done.
| |
207 // Validate the resource (note, if both are wrong, we will return | |
208 // PP_ERROR_BADARGUMENT; last in wins). | |
158 SetStateForFunctionError(instance, functions_, report_error); | 209 SetStateForFunctionError(instance, functions_, report_error); |
159 } | 210 } |
160 | 211 |
161 FunctionsT* functions_; | 212 FunctionsT* functions_; |
162 | 213 |
163 DISALLOW_COPY_AND_ASSIGN(EnterFunction); | 214 DISALLOW_COPY_AND_ASSIGN(EnterFunction); |
164 }; | 215 }; |
165 | 216 |
166 // Like EnterFunction but assumes the lock is already held. | 217 // Like EnterFunction but assumes the lock is already held. |
167 template<typename FunctionsT> | 218 template<typename FunctionsT> |
168 class EnterFunctionNoLock : public EnterFunction<FunctionsT, false> { | 219 class EnterFunctionNoLock : public EnterFunction<FunctionsT, false> { |
169 public: | 220 public: |
170 EnterFunctionNoLock(PP_Instance instance, bool report_error) | 221 EnterFunctionNoLock(PP_Instance instance, bool report_error) |
171 : EnterFunction<FunctionsT, false>(instance, report_error) { | 222 : EnterFunction<FunctionsT, false>(instance, report_error) { |
172 } | 223 } |
173 }; | 224 }; |
174 | 225 |
175 // Used when a caller has a resource, and wants to do EnterFunction for the | 226 // Used when a caller has a resource, and wants to do EnterFunction for the |
176 // instance corresponding to that resource. | 227 // instance corresponding to that resource. |
177 template<typename FunctionsT> | 228 template<typename FunctionsT> |
178 class EnterFunctionGivenResource : public EnterFunction<FunctionsT> { | 229 class EnterFunctionGivenResource : public EnterFunction<FunctionsT> { |
179 public: | 230 public: |
180 EnterFunctionGivenResource(PP_Resource resource, bool report_error) | 231 EnterFunctionGivenResource(PP_Resource resource, bool report_error) |
181 : EnterFunction<FunctionsT>(GetInstanceForResource(resource), | 232 : EnterFunction<FunctionsT>(GetInstanceForResource(resource), |
182 report_error) { | 233 report_error) { |
183 } | 234 } |
184 | 235 |
185 private: | 236 private: |
186 static PP_Instance GetInstanceForResource(PP_Resource resource) { | 237 static PP_Instance GetInstanceForResource(PP_Resource resource) { |
187 Resource* object = | 238 Resource* object = subtle::EnterBase::GetResource(resource); |
188 PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource); | |
189 return object ? object->pp_instance() : 0; | 239 return object ? object->pp_instance() : 0; |
190 } | 240 } |
191 }; | 241 }; |
192 | 242 |
193 // EnterResource --------------------------------------------------------------- | 243 // EnterResource --------------------------------------------------------------- |
194 | 244 |
195 template<typename ResourceT, bool lock_on_entry = true> | 245 template<typename ResourceT, bool lock_on_entry = true> |
196 class EnterResource : public subtle::EnterBase, | 246 class EnterResource : public subtle::EnterBase, |
197 public subtle::LockOnEntry<lock_on_entry> { | 247 public subtle::LockOnEntry<lock_on_entry> { |
198 public: | 248 public: |
199 EnterResource(PP_Resource resource, bool report_error) | 249 EnterResource(PP_Resource resource, bool report_error) |
200 : EnterBase() { | 250 : EnterBase(resource) { |
201 Init(resource, report_error); | 251 Init(resource, report_error); |
202 } | 252 } |
203 EnterResource(PP_Resource resource, | 253 EnterResource(PP_Resource resource, const PP_CompletionCallback& callback, |
204 const PP_CompletionCallback& callback, | |
205 bool report_error) | 254 bool report_error) |
206 : EnterBase(callback) { | 255 : EnterBase(resource, callback) { |
207 Init(resource, report_error); | 256 Init(resource, report_error); |
208 } | 257 } |
209 ~EnterResource() {} | 258 ~EnterResource() {} |
210 | 259 |
211 bool succeeded() const { return !!object_; } | |
212 bool failed() const { return !object_; } | |
213 | |
214 ResourceT* object() { return object_; } | 260 ResourceT* object() { return object_; } |
215 Resource* resource() { return resource_; } | 261 Resource* resource() { return resource_; } |
216 | 262 |
217 private: | 263 private: |
218 void Init(PP_Resource resource, bool report_error) { | 264 void Init(PP_Resource resource, bool report_error) { |
219 resource_ = GetResource(resource); | |
220 if (resource_) | 265 if (resource_) |
221 object_ = resource_->GetAs<ResourceT>(); | 266 object_ = resource_->GetAs<ResourceT>(); |
222 else | 267 else |
223 object_ = NULL; | 268 object_ = NULL; |
269 // Validate the callback. | |
270 SetStateForCallbackError(report_error); | |
271 // Validate the resource (note, if both are wrong, we will return | |
272 // PP_ERROR_BADRESOURCE; last in wins). | |
224 SetStateForResourceError(resource, resource_, object_, report_error); | 273 SetStateForResourceError(resource, resource_, object_, report_error); |
225 } | 274 } |
226 | 275 |
227 Resource* resource_; | |
228 ResourceT* object_; | 276 ResourceT* object_; |
229 | 277 |
230 DISALLOW_COPY_AND_ASSIGN(EnterResource); | 278 DISALLOW_COPY_AND_ASSIGN(EnterResource); |
231 }; | 279 }; |
232 | 280 |
233 // ---------------------------------------------------------------------------- | 281 // ---------------------------------------------------------------------------- |
234 | 282 |
235 // Like EnterResource but assumes the lock is already held. | 283 // Like EnterResource but assumes the lock is already held. |
236 template<typename ResourceT> | 284 template<typename ResourceT> |
237 class EnterResourceNoLock : public EnterResource<ResourceT, false> { | 285 class EnterResourceNoLock : public EnterResource<ResourceT, false> { |
238 public: | 286 public: |
239 EnterResourceNoLock(PP_Resource resource, bool report_error) | 287 EnterResourceNoLock(PP_Resource resource, bool report_error) |
240 : EnterResource<ResourceT, false>(resource, report_error) { | 288 : EnterResource<ResourceT, false>(resource, report_error) { |
241 } | 289 } |
290 EnterResourceNoLock(PP_Resource resource, PP_CompletionCallback callback, | |
291 bool report_error) | |
292 : EnterResource<ResourceT, false>(resource, callback, report_error) { | |
293 } | |
242 }; | 294 }; |
243 | 295 |
244 // Simpler wrapper to enter the resource creation API. This is used for every | 296 // Simpler wrapper to enter the resource creation API. This is used for every |
245 // class so we have this helper function to save template instantiations and | 297 // class so we have this helper function to save template instantiations and |
246 // typing. | 298 // typing. |
247 class PPAPI_THUNK_EXPORT EnterResourceCreation | 299 class PPAPI_THUNK_EXPORT EnterResourceCreation |
248 : public EnterFunction<ResourceCreationAPI> { | 300 : public EnterFunction<ResourceCreationAPI> { |
249 public: | 301 public: |
250 EnterResourceCreation(PP_Instance instance); | 302 EnterResourceCreation(PP_Instance instance); |
251 ~EnterResourceCreation(); | 303 ~EnterResourceCreation(); |
252 }; | 304 }; |
253 | 305 |
254 // Simpler wrapper to enter the instance API from proxy code. This is used for | 306 // Simpler wrapper to enter the instance API from proxy code. This is used for |
255 // many interfaces so we have this helper function to save template | 307 // many interfaces so we have this helper function to save template |
256 // instantiations and typing. | 308 // instantiations and typing. |
257 class PPAPI_THUNK_EXPORT EnterInstance | 309 class PPAPI_THUNK_EXPORT EnterInstance |
258 : public EnterFunction<PPB_Instance_FunctionAPI> { | 310 : public EnterFunction<PPB_Instance_FunctionAPI> { |
259 public: | 311 public: |
260 EnterInstance(PP_Instance instance); | 312 EnterInstance(PP_Instance instance); |
261 EnterInstance(PP_Instance instance, const PP_CompletionCallback& callback); | 313 EnterInstance(PP_Instance instance, const PP_CompletionCallback& callback); |
262 ~EnterInstance(); | 314 ~EnterInstance(); |
263 }; | 315 }; |
264 | 316 |
317 class PPAPI_THUNK_EXPORT EnterInstanceNoLock | |
318 : public EnterFunctionNoLock<PPB_Instance_FunctionAPI> { | |
319 public: | |
320 EnterInstanceNoLock(PP_Instance instance); | |
321 EnterInstanceNoLock(PP_Instance instance, | |
322 const PP_CompletionCallback& callback); | |
323 ~EnterInstanceNoLock(); | |
324 }; | |
325 | |
326 | |
265 } // namespace thunk | 327 } // namespace thunk |
266 } // namespace ppapi | 328 } // namespace ppapi |
267 | 329 |
268 #endif // PPAPI_THUNK_ENTER_H_ | 330 #endif // PPAPI_THUNK_ENTER_H_ |
OLD | NEW |