OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "webkit/plugins/ppapi/var.h" | 5 #include "webkit/plugins/ppapi/var.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/scoped_ptr.h" | 10 #include "base/scoped_ptr.h" |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 } | 155 } |
156 | 156 |
157 NPIdentifier identifier() const { return identifier_; } | 157 NPIdentifier identifier() const { return identifier_; } |
158 | 158 |
159 private: | 159 private: |
160 NPIdentifier identifier_; | 160 NPIdentifier identifier_; |
161 | 161 |
162 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); | 162 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); |
163 }; | 163 }; |
164 | 164 |
165 PP_Var RunJSFunction(PP_Var scope_var, | |
166 const char* function_script, | |
167 PP_Var* argv, | |
168 unsigned argc, | |
169 PP_Var* exception) { | |
170 TryCatch try_catch(NULL, exception); | |
171 if (try_catch.has_exception()) | |
172 return PP_MakeUndefined(); | |
173 | |
174 scoped_refptr<ObjectVar> obj = ObjectVar::FromPPVar(scope_var); | |
175 if (!obj) { | |
176 try_catch.SetInvalidObjectException(); | |
177 return PP_MakeUndefined(); | |
178 } | |
179 | |
180 try_catch.set_module(obj->module()); | |
181 | |
182 scoped_array<NPVariant> args; | |
183 if (argc) { | |
184 args.reset(new NPVariant[argc]); | |
185 for (uint32_t i = 0; i < argc; ++i) { | |
186 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) { | |
187 // This argument was invalid, throw an exception & give up. | |
188 try_catch.SetException(kInvalidValueException); | |
189 return PP_MakeUndefined(); | |
190 } | |
191 } | |
192 } | |
193 | |
194 NPVariant function_var; | |
195 VOID_TO_NPVARIANT(function_var); | |
196 NPString function_string = { function_script, strlen(function_script) }; | |
197 if (!WebBindings::evaluate(NULL, obj->np_object(), &function_string, | |
198 &function_var)) { | |
199 try_catch.SetException(kInvalidValueException); | |
200 return PP_MakeUndefined(); | |
201 } | |
202 DCHECK(NPVARIANT_IS_OBJECT(function_var)); | |
203 DCHECK(!try_catch.has_exception()); | |
204 | |
205 NPVariant result_var; | |
206 VOID_TO_NPVARIANT(result_var); | |
207 PP_Var result; | |
208 | |
209 if (WebBindings::invokeDefault(NULL, NPVARIANT_TO_OBJECT(function_var), | |
210 args.get(), argc, &result_var)) { | |
211 result = Var::NPVariantToPPVar(obj->instance(), &result_var); | |
212 } else { | |
213 DCHECK(try_catch.has_exception()); | |
214 result = PP_MakeUndefined(); | |
215 } | |
216 | |
217 WebBindings::releaseVariantValue(&function_var); | |
218 WebBindings::releaseVariantValue(&result_var); | |
219 return result; | |
220 } | |
221 | |
222 // PPB_Var methods ------------------------------------------------------------- | 165 // PPB_Var methods ------------------------------------------------------------- |
223 | 166 |
224 PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) { | 167 PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) { |
225 PluginModule* module = ResourceTracker::Get()->GetModule(module_id); | 168 PluginModule* module = ResourceTracker::Get()->GetModule(module_id); |
226 if (!module) | 169 if (!module) |
227 return PP_MakeNull(); | 170 return PP_MakeNull(); |
228 return StringVar::StringToPPVar(module, data, len); | 171 return StringVar::StringToPPVar(module, data, len); |
229 } | 172 } |
230 | 173 |
231 const char* VarToUtf8(PP_Var var, uint32_t* len) { | 174 const char* VarToUtf8(PP_Var var, uint32_t* len) { |
232 scoped_refptr<StringVar> str(StringVar::FromPPVar(var)); | 175 scoped_refptr<StringVar> str(StringVar::FromPPVar(var)); |
233 if (!str) { | 176 if (!str) { |
234 *len = 0; | 177 *len = 0; |
235 return NULL; | 178 return NULL; |
236 } | 179 } |
237 *len = static_cast<uint32_t>(str->value().size()); | 180 *len = static_cast<uint32_t>(str->value().size()); |
238 if (str->value().empty()) | 181 if (str->value().empty()) |
239 return ""; // Don't return NULL on success. | 182 return ""; // Don't return NULL on success. |
240 return str->value().data(); | 183 return str->value().data(); |
241 } | 184 } |
242 | 185 |
243 PP_Var ConvertType(PP_Instance instance, | |
244 struct PP_Var var, | |
245 PP_VarType new_type, | |
246 PP_Var* exception) { | |
247 TryCatch try_catch(NULL, exception); | |
248 if (try_catch.has_exception()) | |
249 return PP_MakeUndefined(); | |
250 | |
251 if (var.type == new_type) | |
252 return var; | |
253 | |
254 PluginInstance* plugin_instance = | |
255 ResourceTracker::Get()->GetInstance(instance); | |
256 if (!plugin_instance) { | |
257 try_catch.SetInvalidObjectException(); | |
258 return PP_MakeUndefined(); | |
259 } | |
260 | |
261 try_catch.set_module(plugin_instance->module()); | |
262 PP_Var object = plugin_instance->GetWindowObject(); | |
263 | |
264 PP_Var params[] = { | |
265 var, | |
266 PP_MakeInt32(new_type), | |
267 PP_MakeInt32(PP_VARTYPE_NULL), | |
268 PP_MakeInt32(PP_VARTYPE_BOOL), | |
269 PP_MakeInt32(PP_VARTYPE_INT32), | |
270 PP_MakeInt32(PP_VARTYPE_DOUBLE), | |
271 PP_MakeInt32(PP_VARTYPE_STRING), | |
272 PP_MakeInt32(PP_VARTYPE_OBJECT) | |
273 }; | |
274 PP_Var result = RunJSFunction(object, | |
275 "(function(v, new_type, type_null, type_bool, type_int32, type_double," | |
276 " type_string, type_object) {" | |
277 " switch(new_type) {" | |
278 " case type_null: return null;" | |
279 " case type_bool: return Boolean(v);" | |
280 " case type_int32: case type_double: return Number(v);" | |
281 " case type_string: return String(v);" | |
282 " case type_object: return Object(v);" | |
283 " default: return undefined;" | |
284 " }})", | |
285 params, sizeof(params) / sizeof(PP_Var), exception); | |
286 | |
287 // Massage Number into the correct type. | |
288 if (new_type == PP_VARTYPE_INT32 && result.type == PP_VARTYPE_DOUBLE) { | |
289 double value = result.value.as_double; | |
290 // Exclusive test wouldn't deal with NaNs correctly. | |
291 if (value >= std::numeric_limits<int32_t>::max() | |
292 && value <= std::numeric_limits<int32_t>::min()) | |
293 result = PP_MakeInt32(static_cast<int32_t>(value)); | |
294 else | |
295 result = PP_MakeInt32(0); | |
296 } else if (new_type == PP_VARTYPE_DOUBLE && result.type == PP_VARTYPE_INT32) { | |
297 result = PP_MakeDouble(result.value.as_int); | |
298 } | |
299 | |
300 Var::PluginReleasePPVar(object); | |
301 return result; | |
302 } | |
303 | |
304 PP_Var BoolToPPVar(bool value) { | 186 PP_Var BoolToPPVar(bool value) { |
305 return PP_MakeBool(BoolToPPBool(value)); | 187 return PP_MakeBool(BoolToPPBool(value)); |
306 } | 188 } |
307 | 189 |
308 void DefineProperty(struct PP_Var object, | |
309 struct PP_ObjectProperty property, | |
310 PP_Var* exception) { | |
311 PP_Var params[] = { | |
312 object, property.name, | |
313 BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_HASVALUE)), | |
314 property.value, | |
315 BoolToPPVar(property.getter.type == PP_VARTYPE_OBJECT), | |
316 property.getter, | |
317 BoolToPPVar(property.setter.type == PP_VARTYPE_OBJECT), | |
318 property.setter, | |
319 BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)), | |
320 BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTDELETE)), | |
321 BoolToPPVar(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) | |
322 }; | |
323 | |
324 RunJSFunction(object, | |
325 "(function(o, name," | |
326 " has_value, value," | |
327 " has_getter, getter," | |
328 " has_setter, setter," | |
329 " modifier_readonly, modifier_dontdelete, modifier_dontenum) {" | |
330 " prop = { 'enumerable': !modifier_dontenum," | |
331 " 'configurable': !modifier_dontdelete };" | |
332 " if (has_value && !modifier_readonly) prop.writable = true;" | |
333 " if (has_value) prop.value = value;" | |
334 " if (has_getter) prop.get = getter;" | |
335 " if (has_setter) prop.set = setter;" | |
336 " return Object.defineProperty(o, name, prop); })", | |
337 params, sizeof(params) / sizeof(PP_Var), exception); | |
338 } | |
339 | |
340 PP_Bool HasProperty(PP_Var var, | 190 PP_Bool HasProperty(PP_Var var, |
341 PP_Var name, | 191 PP_Var name, |
342 PP_Var* exception) { | 192 PP_Var* exception) { |
343 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | 193 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); |
344 if (accessor.has_exception()) | 194 if (accessor.has_exception()) |
345 return PP_FALSE; | 195 return PP_FALSE; |
346 return BoolToPPBool(WebBindings::hasProperty(NULL, | 196 return BoolToPPBool(WebBindings::hasProperty(NULL, |
347 accessor.object()->np_object(), | 197 accessor.object()->np_object(), |
348 accessor.identifier())); | 198 accessor.identifier())); |
349 } | 199 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 NPVariant variant; | 277 NPVariant variant; |
428 if (!PPVarToNPVariantNoCopy(value, &variant)) { | 278 if (!PPVarToNPVariantNoCopy(value, &variant)) { |
429 accessor.SetException(kInvalidValueException); | 279 accessor.SetException(kInvalidValueException); |
430 return; | 280 return; |
431 } | 281 } |
432 if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), | 282 if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), |
433 accessor.identifier(), &variant)) | 283 accessor.identifier(), &variant)) |
434 accessor.SetException(kUnableToSetPropertyException); | 284 accessor.SetException(kUnableToSetPropertyException); |
435 } | 285 } |
436 | 286 |
437 PP_Bool DeleteProperty(PP_Var var, | |
438 PP_Var name, | |
439 PP_Var* exception) { | |
440 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | |
441 if (accessor.has_exception()) | |
442 return PP_FALSE; | |
443 | |
444 return BoolToPPBool( | |
445 WebBindings::removeProperty(NULL, | |
446 accessor.object()->np_object(), | |
447 accessor.identifier())); | |
448 } | |
449 | |
450 void DeletePropertyDeprecated(PP_Var var, | 287 void DeletePropertyDeprecated(PP_Var var, |
451 PP_Var name, | 288 PP_Var name, |
452 PP_Var* exception) { | 289 PP_Var* exception) { |
453 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | 290 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); |
454 if (accessor.has_exception()) | 291 if (accessor.has_exception()) |
455 return; | 292 return; |
456 | 293 |
457 if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), | 294 if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), |
458 accessor.identifier())) | 295 accessor.identifier())) |
459 accessor.SetException(kUnableToRemovePropertyException); | 296 accessor.SetException(kUnableToRemovePropertyException); |
460 } | 297 } |
461 | 298 |
462 PP_Bool IsCallable(struct PP_Var object) { | |
463 PP_Var result = RunJSFunction(object, | |
464 "(function() { return typeof(this) == 'function' })", NULL, 0, NULL); | |
465 if (result.type == PP_VARTYPE_BOOL) | |
466 return result.value.as_bool; | |
467 return PP_FALSE; | |
468 } | |
469 | |
470 struct PP_Var Call(struct PP_Var object, | |
471 struct PP_Var this_object, | |
472 uint32_t argc, | |
473 struct PP_Var* argv, | |
474 struct PP_Var* exception) { | |
475 ObjectAccessorTryCatch accessor(object, exception); | |
476 if (accessor.has_exception()) | |
477 return PP_MakeUndefined(); | |
478 | |
479 scoped_array<NPVariant> args; | |
480 if (argc) { | |
481 args.reset(new NPVariant[argc]); | |
482 for (uint32_t i = 0; i < argc; ++i) { | |
483 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) { | |
484 // This argument was invalid, throw an exception & give up. | |
485 accessor.SetException(kInvalidValueException); | |
486 return PP_MakeUndefined(); | |
487 } | |
488 } | |
489 } | |
490 | |
491 NPVariant result; | |
492 if (!WebBindings::invokeDefault(NULL, accessor.object()->np_object(), | |
493 args.get(), argc, &result)) { | |
494 // An exception may have been raised. | |
495 accessor.SetException(kUnableToCallMethodException); | |
496 return PP_MakeUndefined(); | |
497 } | |
498 | |
499 PP_Var ret = Var::NPVariantToPPVar(accessor.object()->instance(), &result); | |
500 WebBindings::releaseVariantValue(&result); | |
501 return ret; | |
502 } | |
503 | |
504 PP_Var CallDeprecated(PP_Var var, | 299 PP_Var CallDeprecated(PP_Var var, |
505 PP_Var method_name, | 300 PP_Var method_name, |
506 uint32_t argc, | 301 uint32_t argc, |
507 PP_Var* argv, | 302 PP_Var* argv, |
508 PP_Var* exception) { | 303 PP_Var* exception) { |
509 ObjectAccessorTryCatch accessor(var, exception); | 304 ObjectAccessorTryCatch accessor(var, exception); |
510 if (accessor.has_exception()) | 305 if (accessor.has_exception()) |
511 return PP_MakeUndefined(); | 306 return PP_MakeUndefined(); |
512 | 307 |
513 NPIdentifier identifier; | 308 NPIdentifier identifier; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 &Construct, | 434 &Construct, |
640 &IsInstanceOfDeprecated, | 435 &IsInstanceOfDeprecated, |
641 &CreateObjectDeprecated, | 436 &CreateObjectDeprecated, |
642 &CreateObjectWithModuleDeprecated, | 437 &CreateObjectWithModuleDeprecated, |
643 }; | 438 }; |
644 | 439 |
645 const PPB_Var var_interface = { | 440 const PPB_Var var_interface = { |
646 &Var::PluginAddRefPPVar, | 441 &Var::PluginAddRefPPVar, |
647 &Var::PluginReleasePPVar, | 442 &Var::PluginReleasePPVar, |
648 &VarFromUtf8, | 443 &VarFromUtf8, |
649 &VarToUtf8, | 444 &VarToUtf8 |
650 &ConvertType, | |
651 &DefineProperty, | |
652 &HasProperty, | |
653 &GetProperty, | |
654 &DeleteProperty, | |
655 &EnumerateProperties, | |
656 &IsCallable, | |
657 &Call, | |
658 &Construct, | |
659 }; | 445 }; |
660 | 446 |
661 | 447 |
662 } // namespace | 448 } // namespace |
663 | 449 |
664 // Var ------------------------------------------------------------------------- | 450 // Var ------------------------------------------------------------------------- |
665 | 451 |
666 Var::Var(PluginModule* module) : module_(module), var_id_(0) { | 452 Var::Var(PluginModule* module) : module_(module), var_id_(0) { |
667 } | 453 } |
668 | 454 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 } | 724 } |
939 | 725 |
940 // static | 726 // static |
941 void TryCatch::Catch(void* self, const char* message) { | 727 void TryCatch::Catch(void* self, const char* message) { |
942 static_cast<TryCatch*>(self)->SetException(message); | 728 static_cast<TryCatch*>(self)->SetException(message); |
943 } | 729 } |
944 | 730 |
945 } // namespace ppapi | 731 } // namespace ppapi |
946 } // namespace webkit | 732 } // namespace webkit |
947 | 733 |
OLD | NEW |