| 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 |