| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium 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 "webkit/plugins/ppapi/ppb_var_impl.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 | |
| 9 #include "ppapi/c/dev/ppb_var_deprecated.h" | |
| 10 #include "ppapi/c/ppb_var.h" | |
| 11 #include "ppapi/c/pp_var.h" | |
| 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | |
| 13 #include "webkit/plugins/ppapi/common.h" | |
| 14 #include "webkit/plugins/ppapi/host_globals.h" | |
| 15 #include "webkit/plugins/ppapi/npapi_glue.h" | |
| 16 #include "webkit/plugins/ppapi/npobject_var.h" | |
| 17 #include "webkit/plugins/ppapi/plugin_module.h" | |
| 18 #include "webkit/plugins/ppapi/plugin_object.h" | |
| 19 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | |
| 20 #include "v8/include/v8.h" | |
| 21 | |
| 22 using ppapi::NPObjectVar; | |
| 23 using ppapi::PpapiGlobals; | |
| 24 using ppapi::StringVar; | |
| 25 using ppapi::Var; | |
| 26 using WebKit::WebBindings; | |
| 27 | |
| 28 namespace webkit { | |
| 29 namespace ppapi { | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 const char kInvalidObjectException[] = "Error: Invalid object"; | |
| 34 const char kInvalidPropertyException[] = "Error: Invalid property"; | |
| 35 const char kInvalidValueException[] = "Error: Invalid value"; | |
| 36 const char kUnableToGetPropertyException[] = "Error: Unable to get property"; | |
| 37 const char kUnableToSetPropertyException[] = "Error: Unable to set property"; | |
| 38 const char kUnableToRemovePropertyException[] = | |
| 39 "Error: Unable to remove property"; | |
| 40 const char kUnableToGetAllPropertiesException[] = | |
| 41 "Error: Unable to get all properties"; | |
| 42 const char kUnableToCallMethodException[] = "Error: Unable to call method"; | |
| 43 const char kUnableToConstructException[] = "Error: Unable to construct"; | |
| 44 | |
| 45 // --------------------------------------------------------------------------- | |
| 46 // Utilities | |
| 47 | |
| 48 // Converts the given PP_Var to an NPVariant, returning true on success. | |
| 49 // False means that the given variant is invalid. In this case, the result | |
| 50 // NPVariant will be set to a void one. | |
| 51 // | |
| 52 // The contents of the PP_Var will NOT be copied, so you need to ensure that | |
| 53 // the PP_Var remains valid while the resultant NPVariant is in use. | |
| 54 bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) { | |
| 55 switch (var.type) { | |
| 56 case PP_VARTYPE_UNDEFINED: | |
| 57 VOID_TO_NPVARIANT(*result); | |
| 58 break; | |
| 59 case PP_VARTYPE_NULL: | |
| 60 NULL_TO_NPVARIANT(*result); | |
| 61 break; | |
| 62 case PP_VARTYPE_BOOL: | |
| 63 BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result); | |
| 64 break; | |
| 65 case PP_VARTYPE_INT32: | |
| 66 INT32_TO_NPVARIANT(var.value.as_int, *result); | |
| 67 break; | |
| 68 case PP_VARTYPE_DOUBLE: | |
| 69 DOUBLE_TO_NPVARIANT(var.value.as_double, *result); | |
| 70 break; | |
| 71 case PP_VARTYPE_STRING: { | |
| 72 StringVar* string = StringVar::FromPPVar(var); | |
| 73 if (!string) { | |
| 74 VOID_TO_NPVARIANT(*result); | |
| 75 return false; | |
| 76 } | |
| 77 const std::string& value = string->value(); | |
| 78 STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result); | |
| 79 break; | |
| 80 } | |
| 81 case PP_VARTYPE_OBJECT: { | |
| 82 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var)); | |
| 83 if (!object) { | |
| 84 VOID_TO_NPVARIANT(*result); | |
| 85 return false; | |
| 86 } | |
| 87 OBJECT_TO_NPVARIANT(object->np_object(), *result); | |
| 88 break; | |
| 89 } | |
| 90 default: | |
| 91 VOID_TO_NPVARIANT(*result); | |
| 92 return false; | |
| 93 } | |
| 94 return true; | |
| 95 } | |
| 96 | |
| 97 // ObjectAccessorTryCatch ------------------------------------------------------ | |
| 98 | |
| 99 // Automatically sets up a TryCatch for accessing the object identified by the | |
| 100 // given PP_Var. The module from the object will be used for the exception | |
| 101 // strings generated by the TryCatch. | |
| 102 // | |
| 103 // This will automatically retrieve the ObjectVar from the object and throw | |
| 104 // an exception if it's invalid. At the end of construction, if there is no | |
| 105 // exception, you know that there is no previously set exception, that the | |
| 106 // object passed in is valid and ready to use (via the object() getter), and | |
| 107 // that the TryCatch's pp_module() getter is also set up properly and ready to | |
| 108 // use. | |
| 109 class ObjectAccessorTryCatch : public TryCatch { | |
| 110 public: | |
| 111 ObjectAccessorTryCatch(PP_Var object, PP_Var* exception) | |
| 112 : TryCatch(0, exception), | |
| 113 object_(NPObjectVar::FromPPVar(object)) { | |
| 114 if (!object_) { | |
| 115 // No object or an invalid object was given. This means we have no module | |
| 116 // to associated with the exception text, so use the magic invalid object | |
| 117 // exception. | |
| 118 SetInvalidObjectException(); | |
| 119 } else { | |
| 120 // When the object is valid, we have a valid module to associate | |
| 121 set_pp_module(object_->pp_module()); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 NPObjectVar* object() { return object_.get(); } | |
| 126 | |
| 127 PluginInstance* GetPluginInstance() { | |
| 128 return HostGlobals::Get()->GetInstance(object()->pp_instance()); | |
| 129 } | |
| 130 | |
| 131 protected: | |
| 132 scoped_refptr<NPObjectVar> object_; | |
| 133 | |
| 134 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch); | |
| 135 }; | |
| 136 | |
| 137 // ObjectAccessiorWithIdentifierTryCatch --------------------------------------- | |
| 138 | |
| 139 // Automatically sets up a TryCatch for accessing the identifier on the given | |
| 140 // object. This just extends ObjectAccessorTryCatch to additionally convert | |
| 141 // the given identifier to an NPIdentifier and validate it, throwing an | |
| 142 // exception if it's invalid. | |
| 143 // | |
| 144 // At the end of construction, if there is no exception, you know that there is | |
| 145 // no previously set exception, that the object passed in is valid and ready to | |
| 146 // use (via the object() getter), that the identifier is valid and ready to | |
| 147 // use (via the identifier() getter), and that the TryCatch's pp_module() getter | |
| 148 // is also set up properly and ready to use. | |
| 149 class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch { | |
| 150 public: | |
| 151 ObjectAccessorWithIdentifierTryCatch(PP_Var object, | |
| 152 PP_Var identifier, | |
| 153 PP_Var* exception) | |
| 154 : ObjectAccessorTryCatch(object, exception), | |
| 155 identifier_(0) { | |
| 156 if (!has_exception()) { | |
| 157 identifier_ = PPVarToNPIdentifier(identifier); | |
| 158 if (!identifier_) | |
| 159 SetException(kInvalidPropertyException); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 NPIdentifier identifier() const { return identifier_; } | |
| 164 | |
| 165 private: | |
| 166 NPIdentifier identifier_; | |
| 167 | |
| 168 DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); | |
| 169 }; | |
| 170 | |
| 171 // PPB_Var methods ------------------------------------------------------------- | |
| 172 | |
| 173 void AddRefVar(PP_Var var) { | |
| 174 PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var); | |
| 175 } | |
| 176 | |
| 177 void ReleaseVar(PP_Var var) { | |
| 178 PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var); | |
| 179 } | |
| 180 | |
| 181 PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) { | |
| 182 return StringVar::StringToPPVar(module, data, len); | |
| 183 } | |
| 184 | |
| 185 const char* VarToUtf8(PP_Var var, uint32_t* len) { | |
| 186 StringVar* str = StringVar::FromPPVar(var); | |
| 187 if (!str) { | |
| 188 *len = 0; | |
| 189 return NULL; | |
| 190 } | |
| 191 *len = static_cast<uint32_t>(str->value().size()); | |
| 192 if (str->value().empty()) | |
| 193 return ""; // Don't return NULL on success. | |
| 194 return str->value().data(); | |
| 195 } | |
| 196 | |
| 197 PP_Bool HasProperty(PP_Var var, | |
| 198 PP_Var name, | |
| 199 PP_Var* exception) { | |
| 200 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | |
| 201 if (accessor.has_exception()) | |
| 202 return PP_FALSE; | |
| 203 return BoolToPPBool(WebBindings::hasProperty(NULL, | |
| 204 accessor.object()->np_object(), | |
| 205 accessor.identifier())); | |
| 206 } | |
| 207 | |
| 208 bool HasPropertyDeprecated(PP_Var var, | |
| 209 PP_Var name, | |
| 210 PP_Var* exception) { | |
| 211 return PPBoolToBool(HasProperty(var, name, exception)); | |
| 212 } | |
| 213 | |
| 214 bool HasMethodDeprecated(PP_Var var, | |
| 215 PP_Var name, | |
| 216 PP_Var* exception) { | |
| 217 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | |
| 218 if (accessor.has_exception()) | |
| 219 return false; | |
| 220 return WebBindings::hasMethod(NULL, accessor.object()->np_object(), | |
| 221 accessor.identifier()); | |
| 222 } | |
| 223 | |
| 224 PP_Var GetProperty(PP_Var var, | |
| 225 PP_Var name, | |
| 226 PP_Var* exception) { | |
| 227 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | |
| 228 if (accessor.has_exception()) | |
| 229 return PP_MakeUndefined(); | |
| 230 | |
| 231 NPVariant result; | |
| 232 if (!WebBindings::getProperty(NULL, accessor.object()->np_object(), | |
| 233 accessor.identifier(), &result)) { | |
| 234 // An exception may have been raised. | |
| 235 accessor.SetException(kUnableToGetPropertyException); | |
| 236 return PP_MakeUndefined(); | |
| 237 } | |
| 238 | |
| 239 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); | |
| 240 WebBindings::releaseVariantValue(&result); | |
| 241 return ret; | |
| 242 } | |
| 243 | |
| 244 void EnumerateProperties(PP_Var var, | |
| 245 uint32_t* property_count, | |
| 246 PP_Var** properties, | |
| 247 PP_Var* exception) { | |
| 248 *properties = NULL; | |
| 249 *property_count = 0; | |
| 250 | |
| 251 ObjectAccessorTryCatch accessor(var, exception); | |
| 252 if (accessor.has_exception()) | |
| 253 return; | |
| 254 | |
| 255 NPIdentifier* identifiers = NULL; | |
| 256 uint32_t count = 0; | |
| 257 if (!WebBindings::enumerate(NULL, accessor.object()->np_object(), | |
| 258 &identifiers, &count)) { | |
| 259 accessor.SetException(kUnableToGetAllPropertiesException); | |
| 260 return; | |
| 261 } | |
| 262 | |
| 263 if (count == 0) | |
| 264 return; | |
| 265 | |
| 266 *property_count = count; | |
| 267 *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count)); | |
| 268 for (uint32_t i = 0; i < count; ++i) { | |
| 269 (*properties)[i] = NPIdentifierToPPVar( | |
| 270 accessor.GetPluginInstance()->module()->pp_module(), | |
| 271 identifiers[i]); | |
| 272 } | |
| 273 free(identifiers); | |
| 274 } | |
| 275 | |
| 276 void SetPropertyDeprecated(PP_Var var, | |
| 277 PP_Var name, | |
| 278 PP_Var value, | |
| 279 PP_Var* exception) { | |
| 280 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | |
| 281 if (accessor.has_exception()) | |
| 282 return; | |
| 283 | |
| 284 NPVariant variant; | |
| 285 if (!PPVarToNPVariantNoCopy(value, &variant)) { | |
| 286 accessor.SetException(kInvalidValueException); | |
| 287 return; | |
| 288 } | |
| 289 if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), | |
| 290 accessor.identifier(), &variant)) | |
| 291 accessor.SetException(kUnableToSetPropertyException); | |
| 292 } | |
| 293 | |
| 294 void DeletePropertyDeprecated(PP_Var var, | |
| 295 PP_Var name, | |
| 296 PP_Var* exception) { | |
| 297 ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); | |
| 298 if (accessor.has_exception()) | |
| 299 return; | |
| 300 | |
| 301 if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), | |
| 302 accessor.identifier())) | |
| 303 accessor.SetException(kUnableToRemovePropertyException); | |
| 304 } | |
| 305 | |
| 306 PP_Var CallDeprecated(PP_Var var, | |
| 307 PP_Var method_name, | |
| 308 uint32_t argc, | |
| 309 PP_Var* argv, | |
| 310 PP_Var* exception) { | |
| 311 ObjectAccessorTryCatch accessor(var, exception); | |
| 312 if (accessor.has_exception()) | |
| 313 return PP_MakeUndefined(); | |
| 314 | |
| 315 NPIdentifier identifier; | |
| 316 if (method_name.type == PP_VARTYPE_UNDEFINED) { | |
| 317 identifier = NULL; | |
| 318 } else if (method_name.type == PP_VARTYPE_STRING) { | |
| 319 // Specifically allow only string functions to be called. | |
| 320 identifier = PPVarToNPIdentifier(method_name); | |
| 321 if (!identifier) { | |
| 322 accessor.SetException(kInvalidPropertyException); | |
| 323 return PP_MakeUndefined(); | |
| 324 } | |
| 325 } else { | |
| 326 accessor.SetException(kInvalidPropertyException); | |
| 327 return PP_MakeUndefined(); | |
| 328 } | |
| 329 | |
| 330 scoped_array<NPVariant> args; | |
| 331 if (argc) { | |
| 332 args.reset(new NPVariant[argc]); | |
| 333 for (uint32_t i = 0; i < argc; ++i) { | |
| 334 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) { | |
| 335 // This argument was invalid, throw an exception & give up. | |
| 336 accessor.SetException(kInvalidValueException); | |
| 337 return PP_MakeUndefined(); | |
| 338 } | |
| 339 } | |
| 340 } | |
| 341 | |
| 342 bool ok; | |
| 343 | |
| 344 NPVariant result; | |
| 345 if (identifier) { | |
| 346 ok = WebBindings::invoke(NULL, accessor.object()->np_object(), | |
| 347 identifier, args.get(), argc, &result); | |
| 348 } else { | |
| 349 ok = WebBindings::invokeDefault(NULL, accessor.object()->np_object(), | |
| 350 args.get(), argc, &result); | |
| 351 } | |
| 352 | |
| 353 if (!ok) { | |
| 354 // An exception may have been raised. | |
| 355 accessor.SetException(kUnableToCallMethodException); | |
| 356 return PP_MakeUndefined(); | |
| 357 } | |
| 358 | |
| 359 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); | |
| 360 WebBindings::releaseVariantValue(&result); | |
| 361 return ret; | |
| 362 } | |
| 363 | |
| 364 PP_Var Construct(PP_Var var, | |
| 365 uint32_t argc, | |
| 366 PP_Var* argv, | |
| 367 PP_Var* exception) { | |
| 368 ObjectAccessorTryCatch accessor(var, exception); | |
| 369 if (accessor.has_exception()) | |
| 370 return PP_MakeUndefined(); | |
| 371 | |
| 372 scoped_array<NPVariant> args; | |
| 373 if (argc) { | |
| 374 args.reset(new NPVariant[argc]); | |
| 375 for (uint32_t i = 0; i < argc; ++i) { | |
| 376 if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) { | |
| 377 // This argument was invalid, throw an exception & give up. | |
| 378 accessor.SetException(kInvalidValueException); | |
| 379 return PP_MakeUndefined(); | |
| 380 } | |
| 381 } | |
| 382 } | |
| 383 | |
| 384 NPVariant result; | |
| 385 if (!WebBindings::construct(NULL, accessor.object()->np_object(), | |
| 386 args.get(), argc, &result)) { | |
| 387 // An exception may have been raised. | |
| 388 accessor.SetException(kUnableToConstructException); | |
| 389 return PP_MakeUndefined(); | |
| 390 } | |
| 391 | |
| 392 PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); | |
| 393 WebBindings::releaseVariantValue(&result); | |
| 394 return ret; | |
| 395 } | |
| 396 | |
| 397 bool IsInstanceOfDeprecated(PP_Var var, | |
| 398 const PPP_Class_Deprecated* ppp_class, | |
| 399 void** ppp_class_data) { | |
| 400 scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var)); | |
| 401 if (!object) | |
| 402 return false; // Not an object at all. | |
| 403 | |
| 404 return PluginObject::IsInstanceOf(object->np_object(), | |
| 405 ppp_class, ppp_class_data); | |
| 406 } | |
| 407 | |
| 408 PP_Var CreateObjectDeprecated(PP_Instance pp_instance, | |
| 409 const PPP_Class_Deprecated* ppp_class, | |
| 410 void* ppp_class_data) { | |
| 411 PluginInstance* instance = HostGlobals::Get()->GetInstance(pp_instance); | |
| 412 if (!instance) { | |
| 413 DLOG(ERROR) << "Create object passed an invalid instance."; | |
| 414 return PP_MakeNull(); | |
| 415 } | |
| 416 return PluginObject::Create(instance, ppp_class, ppp_class_data); | |
| 417 } | |
| 418 | |
| 419 PP_Var CreateObjectWithModuleDeprecated(PP_Module pp_module, | |
| 420 const PPP_Class_Deprecated* ppp_class, | |
| 421 void* ppp_class_data) { | |
| 422 PluginModule* module = HostGlobals::Get()->GetModule(pp_module); | |
| 423 if (!module) | |
| 424 return PP_MakeNull(); | |
| 425 return PluginObject::Create(module->GetSomeInstance(), | |
| 426 ppp_class, ppp_class_data); | |
| 427 } | |
| 428 | |
| 429 const PPB_Var_Deprecated var_deprecated_interface = { | |
| 430 &AddRefVar, | |
| 431 &ReleaseVar, | |
| 432 &VarFromUtf8, | |
| 433 &VarToUtf8, | |
| 434 &HasPropertyDeprecated, | |
| 435 &HasMethodDeprecated, | |
| 436 &GetProperty, | |
| 437 &EnumerateProperties, | |
| 438 &SetPropertyDeprecated, | |
| 439 &DeletePropertyDeprecated, | |
| 440 &CallDeprecated, | |
| 441 &Construct, | |
| 442 &IsInstanceOfDeprecated, | |
| 443 &CreateObjectDeprecated, | |
| 444 &CreateObjectWithModuleDeprecated, | |
| 445 }; | |
| 446 | |
| 447 const PPB_Var var_interface = { | |
| 448 &AddRefVar, | |
| 449 &ReleaseVar, | |
| 450 &VarFromUtf8, | |
| 451 &VarToUtf8 | |
| 452 }; | |
| 453 | |
| 454 } // namespace | |
| 455 | |
| 456 // static | |
| 457 const PPB_Var* PPB_Var_Impl::GetVarInterface() { | |
| 458 return &var_interface; | |
| 459 } | |
| 460 | |
| 461 // static | |
| 462 const PPB_Var_Deprecated* PPB_Var_Impl::GetVarDeprecatedInterface() { | |
| 463 return &var_deprecated_interface; | |
| 464 } | |
| 465 | |
| 466 } // namespace ppapi | |
| 467 } // namespace webkit | |
| 468 | |
| OLD | NEW |