Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(436)

Side by Side Diff: src/trusted/plugin/var_utils.cc

Issue 7799028: Remove src/trusted/plugin (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: fix gyp file for necessary -I Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/trusted/plugin/var_utils.h ('k') | src/trusted/plugin/win/nacl_plugin.rc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Native Client 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.
4
5 #include <assert.h>
6
7 #include "native_client/src/trusted/plugin/var_utils.h"
8
9 #include "native_client/src/include/nacl_macros.h"
10 #include "native_client/src/include/nacl_string.h"
11 #include "native_client/src/include/portability_io.h"
12 #include "native_client/src/shared/platform/nacl_check.h"
13 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
14 #include "native_client/src/trusted/plugin/array_ppapi.h"
15 #include "native_client/src/trusted/plugin/desc_based_handle.h"
16 #include "native_client/src/trusted/plugin/scriptable_handle.h"
17 #include "native_client/src/trusted/plugin/utility.h"
18
19 #include "ppapi/cpp/dev/scriptable_object_deprecated.h"
20
21 namespace plugin {
22
23
24 // In JavaScript, foo[1] is equivalent to foo["1"], so map both indexed and
25 // string names to a string.
26 nacl::string NameAsString(const pp::Var& name) {
27 if (name.is_string())
28 return name.AsString();
29 assert(name.is_int());
30 nacl::stringstream namestream;
31 namestream << name.AsInt();
32 return namestream.str();
33 }
34
35
36 //-----------------------------------------------------------------------------
37 // Translation from pp::Var to NaClSrpcArg
38 //-----------------------------------------------------------------------------
39
40 namespace {
41
42 // Sets |array_length| and allocate |array_data| based on the length
43 // represented by |var|. Sets |exception| on error.
44 template<typename T> void PPVarToAllocateArray(const pp::Var& var,
45 nacl_abi_size_t* array_length,
46 T** array_data,
47 pp::Var* exception) {
48 // Initialize result values for error cases.
49 *array_length = 0;
50 *array_data = NULL;
51
52 if (!var.is_number()) {
53 *exception = "incompatible argument: unable to get array length";
54 return;
55 }
56 // AsInt will work if var is int or double.
57 size_t length = var.AsInt();
58
59 // Check for overflow on size multiplication and IMC array size limit.
60 if ((length > SIZE_T_MAX / sizeof(T)) ||
61 (length * sizeof(T) > NACL_ABI_IMC_USER_BYTES_MAX)) {
62 *exception = "incompatible argument: array length is too long";
63 return;
64 }
65
66 *array_length = static_cast<nacl_abi_size_t>(length);
67 *array_data = reinterpret_cast<T*>(malloc(sizeof(T) * length));
68 if (array_data == NULL) {
69 *exception = "incompatible argument: internal error";
70 }
71 }
72
73
74 // Translates |var| into |array_length| and |array_data| for type |type|.
75 // Sets |exception| on error.
76 template<typename T> void PPVarToArray(const pp::Var& var,
77 nacl_abi_size_t* array_length,
78 T** array_data,
79 pp::Var* exception) {
80 if (!var.is_object()) {
81 *exception = "incompatible argument: type is not array";
82 return;
83 }
84 pp::VarPrivate var_private(var);
85
86 pp::Var length_var = var_private.GetProperty(pp::Var("length"), exception);
87 PLUGIN_PRINTF((" PPVarToArray (length=%s)\n",
88 length_var.DebugString().c_str()));
89 PPVarToAllocateArray(length_var, array_length, array_data, exception);
90 if (!exception->is_undefined()) {
91 return;
92 }
93
94 for (size_t i = 0; i < *array_length; ++i) {
95 int32_t index = nacl::assert_cast<int32_t>(i);
96 pp::Var element = var_private.GetProperty(pp::Var(index), exception);
97 PLUGIN_PRINTF((" PPVarToArray (array[%d]=%s)\n",
98 index, element.DebugString().c_str()));
99 if (!exception->is_undefined()) {
100 break;
101 }
102 if (!element.is_number()) {
103 *exception = "incompatible argument: non-numeric element type";
104 break;
105 }
106 if (element.is_int()) {
107 (*array_data)[i] = static_cast<T>(element.AsInt());
108 } else if (element.is_double()) {
109 (*array_data)[i] = static_cast<T>(element.AsDouble());
110 } else {
111 NACL_NOTREACHED();
112 }
113 }
114 if (!exception->is_undefined()) {
115 free(array_data);
116 *array_length = 0;
117 *array_data = NULL;
118 }
119 }
120
121
122 // Returns the address of |var| if var is an object. Sets |exception| on error.
123 // |var| was passed in from SRPC input marshalling. It is guaranteed to be
124 // alive until the SRPC method is dispatched to.
125 pp::Var* PPVarToObjectVar(const pp::Var& var, pp::Var* exception) {
126 if (!var.is_object()) {
127 *exception = "incompatible argument: type is not object";
128 return NULL;
129 }
130 return const_cast<pp::Var*>(&var);
131 }
132
133
134 // Returns NaClDesc* corresponding to |var|. Sets |exception| on error.
135 NaClDesc* PPVarToNaClDesc(const pp::Var& var, pp::Var* exception) {
136 if (!var.is_object()) {
137 *exception = "incompatible argument: type is not object";
138 return NULL;
139 }
140 pp::VarPrivate var_private(var);
141 pp::deprecated::ScriptableObject* scriptable_object =
142 var_private.AsScriptableObject();
143 if (scriptable_object == NULL) {
144 *exception = "incompatible argument: type is not scriptable object";
145 return NULL;
146 }
147 ScriptableHandle* scriptable_handle =
148 static_cast<ScriptableHandle*>(scriptable_object);
149 if (!ScriptableHandle::is_valid(scriptable_handle)) {
150 *exception = "incompatible argument: not a valid scriptable handle";
151 return NULL;
152 }
153 NaClDesc* nacl_desc = scriptable_handle->desc_handle()->desc();
154 if (nacl_desc == NULL) {
155 *exception = "incompatible argument: not a handle object";
156 return NULL;
157 }
158 return nacl_desc;
159 }
160
161
162 // Allocates and returns a pointer to string corresponding to |var|.
163 // Sets |exception| on error.
164 char* PPVarToString(const pp::Var& var, pp::Var* exception) {
165 if (!var.is_string()) {
166 *exception = "incompatible argument: type is not string";
167 return NULL;
168 }
169
170 nacl::string var_as_string = var.AsString();
171 size_t size = var_as_string.size() + 1; // + \0
172 char* string_as_chars = reinterpret_cast<char*>(malloc(size));
173 if (string_as_chars == NULL) {
174 *exception = "incompatible argument: internal error";
175 return NULL;
176 }
177
178 memcpy(string_as_chars, var_as_string.c_str(), size);
179 return string_as_chars;
180 }
181
182
183 // Returns a number corresponding to |var|. JavaScript might mix int and
184 // double types, so use them interchangeably. Sets |exception| on error.
185 template<typename T> T PPVarToNumber(const pp::Var& var, pp::Var* exception) {
186 T result = 0;
187 if (!var.is_number())
188 *exception = "incompatible argument: type is not numeric";
189 else if (var.is_double())
190 result = static_cast<T>(var.AsDouble());
191 else if (var.is_int())
192 result = static_cast<T>(var.AsInt());
193 return result;
194 }
195
196 } // namespace
197
198
199 // Allocates |arg| of the array length represented by |var|. No-op for scalars.
200 // Sets |exception| and returns false on error.
201 bool PPVarToAllocateNaClSrpcArg(const pp::Var& var,
202 NaClSrpcArg* arg, pp::Var* exception) {
203 PLUGIN_PRINTF((" PPVarToAllocateNaClSrpcArg (var=%s, arg->tag='%c')\n",
204 var.DebugString().c_str(), arg->tag));
205 switch (arg->tag) {
206 case NACL_SRPC_ARG_TYPE_BOOL:
207 case NACL_SRPC_ARG_TYPE_DOUBLE:
208 case NACL_SRPC_ARG_TYPE_INT:
209 case NACL_SRPC_ARG_TYPE_LONG:
210 case NACL_SRPC_ARG_TYPE_STRING:
211 case NACL_SRPC_ARG_TYPE_HANDLE:
212 case NACL_SRPC_ARG_TYPE_OBJECT:
213 break; // nothing to do
214 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
215 PPVarToAllocateArray(var, &arg->u.count, &arg->arrays.carr, exception);
216 break;
217 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
218 PPVarToAllocateArray(var, &arg->u.count, &arg->arrays.darr, exception);
219 break;
220 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
221 PPVarToAllocateArray(var, &arg->u.count, &arg->arrays.iarr, exception);
222 break;
223 case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
224 PPVarToAllocateArray(var, &arg->u.count, &arg->arrays.larr, exception);
225 break;
226 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
227 case NACL_SRPC_ARG_TYPE_INVALID:
228 default:
229 *exception = "variant array and invalid type arguments are not supported";
230 }
231 PLUGIN_PRINTF((" PPVarToAllocateNaClSrpcArg (return exception=%s)\n",
232 exception->DebugString().c_str()));
233 return exception->is_undefined();
234 }
235
236
237 // Translates |var| into |arg|. Returns false and sets exception on error.
238 bool PPVarToNaClSrpcArg(const pp::Var& var,
239 NaClSrpcArg* arg, pp::Var* exception) {
240 PLUGIN_PRINTF((" PPVarToNaClSrpcArg (var=%s, arg->tag='%c')\n",
241 var.DebugString().c_str(), arg->tag));
242 switch (arg->tag) {
243 case NACL_SRPC_ARG_TYPE_BOOL:
244 if (!var.is_bool())
245 *exception = "incompatible argument: type is not bool";
246 else
247 arg->u.bval = var.AsBool();
248 break;
249 case NACL_SRPC_ARG_TYPE_DOUBLE:
250 arg->u.dval = PPVarToNumber<double>(var, exception);
251 break;
252 case NACL_SRPC_ARG_TYPE_INT:
253 arg->u.ival = PPVarToNumber<int32_t>(var, exception);
254 break;
255 case NACL_SRPC_ARG_TYPE_LONG:
256 arg->u.lval = PPVarToNumber<int64_t>(var, exception);
257 break;
258 case NACL_SRPC_ARG_TYPE_STRING:
259 arg->arrays.str = PPVarToString(var, exception);
260 break;
261 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
262 PPVarToArray(var, &arg->u.count, &arg->arrays.carr, exception);
263 break;
264 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
265 PPVarToArray(var, &arg->u.count, &arg->arrays.darr, exception);
266 break;
267 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
268 PPVarToArray(var, &arg->u.count, &arg->arrays.iarr, exception);
269 break;
270 case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
271 PPVarToArray(var, &arg->u.count, &arg->arrays.larr, exception);
272 break;
273 case NACL_SRPC_ARG_TYPE_HANDLE:
274 arg->u.hval = reinterpret_cast<NaClSrpcImcDescType>(
275 PPVarToNaClDesc(var, exception));
276 break;
277 case NACL_SRPC_ARG_TYPE_OBJECT:
278 arg->arrays.oval = reinterpret_cast<void*>(
279 PPVarToObjectVar(var, exception));
280 break;
281 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
282 case NACL_SRPC_ARG_TYPE_INVALID:
283 default:
284 *exception = "variant array and invalid type arguments are not supported";
285 }
286 PLUGIN_PRINTF((" PPVarToNaClSrpcArg (return exception=%s)\n",
287 exception->DebugString().c_str()));
288 return exception->is_undefined();
289 }
290
291
292 //-----------------------------------------------------------------------------
293 // Translation NaClSrpcArg to pp::Var
294 //-----------------------------------------------------------------------------
295
296 namespace {
297
298 // PPAPI does not have a 64-bit integer Var type.
299 // To make the array construction below work, we define a set of overloaded
300 // functions to convert an array element to a pp::Var.
301 template<typename T> pp::Var ArrayElementToPPVar(T array_element) {
302 return pp::Var(array_element);
303 }
304
305 // One overload is specialized, and it truncates, losing precision of course.
306 pp::Var ArrayElementToPPVar(int64_t array_element) {
307 return pp::Var(static_cast<int32_t>(array_element));
308 }
309
310 // Return a pp::Var constructed from |array_data|. Sets |exception| on error.
311 template<typename T> pp::Var ArrayToPPVar(T* array_data,
312 nacl_abi_size_t array_length,
313 Plugin* plugin,
314 pp::Var* exception) {
315 ArrayPpapi* array = new(std::nothrow) ArrayPpapi(plugin);
316 if (array == NULL) {
317 *exception = "incompatible argument: internal error";
318 return pp::Var();
319 }
320
321 for (size_t i = 0; i < array_length; ++i) {
322 int32_t index = static_cast<int32_t>(i);
323 array->SetProperty(pp::Var(index),
324 ArrayElementToPPVar(array_data[i]),
325 exception);
326 }
327 return pp::VarPrivate(plugin, array);
328 }
329
330
331 // Returns a pp::Var corresponding to |desc| or void. Sets |exception| on error.
332 pp::Var NaClDescToPPVar(NaClDesc* desc, Plugin* plugin, pp::Var* exception) {
333 nacl::DescWrapper* wrapper = plugin->wrapper_factory()->MakeGeneric(desc);
334
335 DescBasedHandle* desc_handle = DescBasedHandle::New(wrapper);
336
337 pp::deprecated::ScriptableObject* object =
338 ScriptableHandle::NewDescHandle(desc_handle);
339 if (object == NULL) {
340 *exception = "incompatible argument: failed to create handle var";
341 return pp::Var();
342 }
343 return pp::VarPrivate(plugin, object);
344 }
345
346
347 // Returns a pp::Var corresponding to |obj|. Only predeclared plugin methods
348 // can return objects and they only return a ScriptableHandle that is actually
349 // a ScriptableHandle.
350 pp::Var ObjectToPPVar(void* obj) {
351 ScriptableHandle* handle = reinterpret_cast<ScriptableHandle*>(obj);
352 // This confirms that this this is indeed a valid SriptableHandle that was
353 // created by us. In theory, a predeclared method could receive and return
354 // an opaque JavaScript object that is not a ScriptableHandle. But we don't
355 // have methods like this at the time. If one ever creates such a method,
356 // this CHECK will fail and remind the author to update this code to handle
357 // arbitrary objects.
358 CHECK(ScriptableHandle::is_valid(handle));
359 if (handle->var() != NULL)
360 return *handle->var(); // make a copy
361
362 return pp::VarPrivate(handle->plugin(), handle);
363 }
364
365 } // namespace
366
367 // Returns a pp::Var corresponding to |arg| or void. Sets |exception| on error.
368 pp::Var NaClSrpcArgToPPVar(const NaClSrpcArg* arg, Plugin* plugin,
369 pp::Var* exception) {
370 PLUGIN_PRINTF((" NaClSrpcArgToPPVar (arg->tag='%c')\n", arg->tag));
371 pp::Var var;
372 switch (arg->tag) {
373 case NACL_SRPC_ARG_TYPE_BOOL:
374 var = pp::Var(arg->u.bval != 0);
375 break;
376 case NACL_SRPC_ARG_TYPE_DOUBLE:
377 var = pp::Var(arg->u.dval);
378 break;
379 case NACL_SRPC_ARG_TYPE_INT:
380 var = pp::Var(arg->u.ival);
381 break;
382 case NACL_SRPC_ARG_TYPE_LONG:
383 // PPAPI does not have a 64-bit integral type. Downcast.
384 var = pp::Var(static_cast<int32_t>(arg->u.lval));
385 break;
386 case NACL_SRPC_ARG_TYPE_STRING:
387 var = pp::Var(arg->arrays.str);
388 break;
389 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY:
390 var = ArrayToPPVar(arg->arrays.carr, arg->u.count, plugin, exception);
391 break;
392 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY:
393 var = ArrayToPPVar(arg->arrays.darr, arg->u.count, plugin, exception);
394 break;
395 case NACL_SRPC_ARG_TYPE_INT_ARRAY:
396 var = ArrayToPPVar(arg->arrays.iarr, arg->u.count, plugin, exception);
397 break;
398 case NACL_SRPC_ARG_TYPE_LONG_ARRAY:
399 var = ArrayToPPVar(arg->arrays.larr, arg->u.count, plugin, exception);
400 break;
401 case NACL_SRPC_ARG_TYPE_HANDLE:
402 var = NaClDescToPPVar(arg->u.hval, plugin, exception);
403 break;
404 case NACL_SRPC_ARG_TYPE_OBJECT:
405 var = ObjectToPPVar(arg->arrays.oval);
406 break;
407 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY:
408 case NACL_SRPC_ARG_TYPE_INVALID:
409 default:
410 *exception = "variant array and invalid argument types are not supproted";
411 }
412 PLUGIN_PRINTF((" NaClSrpcArgToPPVar (return var=%s, exception=%s)\n",
413 var.DebugString().c_str(), exception->DebugString().c_str()));
414 return var;
415 }
416
417 } // namespace plugin
OLDNEW
« no previous file with comments | « src/trusted/plugin/var_utils.h ('k') | src/trusted/plugin/win/nacl_plugin.rc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698