From e340dd3131637817f78de99896f9a2fccfc6dbba Mon Sep 17 00:00:00 2001 From: "neb@chromium.org" Date: Mon, 25 Oct 2010 18:23:32 +0000 Subject: PPB_Var implementation, Chrome side. This implements the new PPB_Var interface on pepper. BUG=57613 TEST=ppapi_tests, yet uncommitted. Review URL: http://codereview.chromium.org/3801006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63752 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/glue/plugins/pepper_plugin_module.cc | 3 + webkit/glue/plugins/pepper_var.cc | 230 +++++++++++++++++++++++++++- webkit/glue/plugins/pepper_var.h | 4 + 3 files changed, 235 insertions(+), 2 deletions(-) (limited to 'webkit') diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc index 13390d5..52a8916 100644 --- a/webkit/glue/plugins/pepper_plugin_module.cc +++ b/webkit/glue/plugins/pepper_plugin_module.cc @@ -44,6 +44,7 @@ #include "third_party/ppapi/c/ppb_graphics_2d.h" #include "third_party/ppapi/c/ppb_image_data.h" #include "third_party/ppapi/c/ppb_instance.h" +#include "third_party/ppapi/c/ppb_var.h" #include "third_party/ppapi/c/ppp.h" #include "third_party/ppapi/c/ppp_instance.h" #include "webkit/glue/plugins/pepper_audio.h" @@ -199,6 +200,8 @@ const void* GetInterface(const char* name) { return &core_interface; if (strcmp(name, PPB_VAR_DEPRECATED_INTERFACE) == 0) return Var::GetDeprecatedInterface(); + if (strcmp(name, PPB_VAR_INTERFACE) == 0) + return Var::GetInterface(); if (strcmp(name, PPB_INSTANCE_INTERFACE) == 0) return PluginInstance::GetInterface(); if (strcmp(name, PPB_IMAGEDATA_INTERFACE) == 0) diff --git a/webkit/glue/plugins/pepper_var.cc b/webkit/glue/plugins/pepper_var.cc index 6daece9..b9d019d 100644 --- a/webkit/glue/plugins/pepper_var.cc +++ b/webkit/glue/plugins/pepper_var.cc @@ -4,12 +4,16 @@ #include "webkit/glue/plugins/pepper_var.h" +#include + #include "base/logging.h" #include "base/scoped_ptr.h" #include "base/string_util.h" #include "third_party/ppapi/c/dev/ppb_var_deprecated.h" +#include "third_party/ppapi/c/ppb_var.h" #include "third_party/ppapi/c/pp_var.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" +#include "webkit/glue/plugins/pepper_plugin_instance.h" #include "webkit/glue/plugins/pepper_plugin_module.h" #include "webkit/glue/plugins/pepper_plugin_object.h" #include "v8/include/v8.h" @@ -154,6 +158,63 @@ class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch { DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); }; +PP_Var RunJSFunction(PP_Var scope_var, + const char* function_script, + PP_Var* argv, + unsigned argc, + PP_Var* exception) { + TryCatch try_catch(NULL, exception); + if (try_catch.has_exception()) + return PP_MakeUndefined(); + + scoped_refptr obj = ObjectVar::FromPPVar(scope_var); + if (!obj) { + try_catch.SetInvalidObjectException(); + return PP_MakeUndefined(); + } + + try_catch.set_module(obj->module()); + + scoped_array args; + if (argc) { + args.reset(new NPVariant[argc]); + for (uint32_t i = 0; i < argc; ++i) { + if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) { + // This argument was invalid, throw an exception & give up. + try_catch.SetException(kInvalidValueException); + return PP_MakeUndefined(); + } + } + } + + NPVariant function_var; + VOID_TO_NPVARIANT(function_var); + NPString function_string = { function_script, strlen(function_script) }; + if (!WebBindings::evaluate(NULL, obj->np_object(), &function_string, + &function_var)) { + try_catch.SetException(kInvalidValueException); + return PP_MakeUndefined(); + } + DCHECK(NPVARIANT_IS_OBJECT(function_var)); + DCHECK(!try_catch.has_exception()); + + NPVariant result_var; + VOID_TO_NPVARIANT(result_var); + PP_Var result; + + if (WebBindings::invokeDefault(NULL, NPVARIANT_TO_OBJECT(function_var), + args.get(), argc, &result_var)) { + result = Var::NPVariantToPPVar(obj->module(), &result_var); + } else { + DCHECK(try_catch.has_exception()); + result = PP_MakeUndefined(); + } + + WebBindings::releaseVariantValue(&function_var); + WebBindings::releaseVariantValue(&result_var); + return result; +} + // PPB_Var methods ------------------------------------------------------------- PP_Var VarFromUtf8(PP_Module module_id, const char* data, uint32_t len) { @@ -175,6 +236,99 @@ const char* VarToUtf8(PP_Var var, uint32_t* len) { return str->value().data(); } +PP_Var ConvertType(PP_Instance instance, + struct PP_Var var, + PP_VarType new_type, + PP_Var* exception) { + TryCatch try_catch(NULL, exception); + if (try_catch.has_exception()) + return PP_MakeUndefined(); + + if (var.type == new_type) + return var; + + PluginInstance* plugin_instance = + ResourceTracker::Get()->GetInstance(instance); + if (!plugin_instance) { + try_catch.SetInvalidObjectException(); + return PP_MakeUndefined(); + } + + try_catch.set_module(plugin_instance->module()); + PP_Var object = plugin_instance->GetWindowObject(); + + PP_Var params[] = { + var, + PP_MakeInt32(new_type), + PP_MakeInt32(PP_VARTYPE_NULL), + PP_MakeInt32(PP_VARTYPE_BOOL), + PP_MakeInt32(PP_VARTYPE_INT32), + PP_MakeInt32(PP_VARTYPE_DOUBLE), + PP_MakeInt32(PP_VARTYPE_STRING), + PP_MakeInt32(PP_VARTYPE_OBJECT) + }; + PP_Var result = RunJSFunction(object, + "(function(v, new_type, type_null, type_bool, type_int32, type_double," + " type_string, type_object) {" + " switch(new_type) {" + " case type_null: return null;" + " case type_bool: return Boolean(v);" + " case type_int32: case type_double: return Number(v);" + " case type_string: return String(v);" + " case type_object: return Object(v);" + " default: return undefined;" + " }})", + params, sizeof(params) / sizeof(PP_Var), exception); + + // Massage Number into the correct type. + if (new_type == PP_VARTYPE_INT32 && result.type == PP_VARTYPE_DOUBLE) { + double value = result.value.as_double; + // Exclusive test wouldn't deal with NaNs correctly. + if (value >= std::numeric_limits::max() + && value <= std::numeric_limits::min()) + result = PP_MakeInt32(static_cast(value)); + else + result = PP_MakeInt32(0); + } else if (new_type == PP_VARTYPE_DOUBLE && result.type == PP_VARTYPE_INT32) { + result = PP_MakeDouble(result.value.as_int); + } + + Var::PluginReleasePPVar(object); + return result; +} + +void DefineProperty(struct PP_Var object, + struct PP_ObjectProperty property, + PP_Var* exception) { + PP_Var params[] = { + object, property.name, + PP_MakeBool(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_HASVALUE)), + property.value, + PP_MakeBool(property.getter.type == PP_VARTYPE_OBJECT), + property.getter, + PP_MakeBool(property.setter.type == PP_VARTYPE_OBJECT), + property.setter, + PP_MakeBool(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)), + PP_MakeBool(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTDELETE)), + PP_MakeBool(!!(property.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) + }; + + RunJSFunction(object, + "(function(o, name," + " has_value, value," + " has_getter, getter," + " has_setter, setter," + " modifier_readonly, modifier_dontdelete, modifier_dontenum) {" + " prop = { 'enumerable': !modifier_dontenum," + " 'configurable': !modifier_dontdelete };" + " if (has_value && !modifier_readonly) prop.writable = true;" + " if (has_value) prop.value = value;" + " if (has_getter) prop.get = getter;" + " if (has_setter) prop.set = setter;" + " return Object.defineProperty(o, name, prop); })", + params, sizeof(params) / sizeof(PP_Var), exception); +} + bool HasProperty(PP_Var var, PP_Var name, PP_Var* exception) { @@ -264,11 +418,22 @@ void SetPropertyDeprecated(PP_Var var, accessor.SetException(kUnableToSetPropertyException); } -void DeleteProperty(PP_Var var, +bool DeleteProperty(PP_Var var, PP_Var name, PP_Var* exception) { ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); if (accessor.has_exception()) + return false; + + return WebBindings::removeProperty(NULL, accessor.object()->np_object(), + accessor.identifier()); +} + +void DeletePropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) return; if (!WebBindings::removeProperty(NULL, accessor.object()->np_object(), @@ -276,6 +441,46 @@ void DeleteProperty(PP_Var var, accessor.SetException(kUnableToRemovePropertyException); } +bool IsCallable(struct PP_Var object) { + PP_Var result = RunJSFunction(object, + "(function() { return typeof(this) == 'function' })", NULL, 0, NULL); + return result.type == PP_VARTYPE_BOOL && result.value.as_bool; +} + +struct PP_Var Call(struct PP_Var object, + struct PP_Var this_object, + uint32_t argc, + struct PP_Var* argv, + struct PP_Var* exception) { + ObjectAccessorTryCatch accessor(object, exception); + if (accessor.has_exception()) + return PP_MakeUndefined(); + + scoped_array args; + if (argc) { + args.reset(new NPVariant[argc]); + for (uint32_t i = 0; i < argc; ++i) { + if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) { + // This argument was invalid, throw an exception & give up. + accessor.SetException(kInvalidValueException); + return PP_MakeUndefined(); + } + } + } + + NPVariant result; + if (!WebBindings::invokeDefault(NULL, accessor.object()->np_object(), + args.get(), argc, &result)) { + // An exception may have been raised. + accessor.SetException(kUnableToCallMethodException); + return PP_MakeUndefined(); + } + + PP_Var ret = Var::NPVariantToPPVar(accessor.module(), &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + PP_Var CallDeprecated(PP_Var var, PP_Var method_name, uint32_t argc, @@ -397,13 +602,30 @@ const PPB_Var_Deprecated var_deprecated_interface = { &GetProperty, &EnumerateProperties, &SetPropertyDeprecated, - &DeleteProperty, + &DeletePropertyDeprecated, &CallDeprecated, &Construct, &IsInstanceOfDeprecated, &CreateObjectDeprecated }; +const PPB_Var var_interface = { + &Var::PluginAddRefPPVar, + &Var::PluginReleasePPVar, + &VarFromUtf8, + &VarToUtf8, + &ConvertType, + &DefineProperty, + &HasProperty, + &GetProperty, + &DeleteProperty, + &EnumerateProperties, + &IsCallable, + &Call, + &Construct, +}; + + } // namespace // Var ------------------------------------------------------------------------- @@ -492,6 +714,10 @@ const PPB_Var_Deprecated* Var::GetDeprecatedInterface() { return &var_deprecated_interface; } +const PPB_Var* Var::GetInterface() { + return &var_interface; +} + // StringVar ------------------------------------------------------------------- StringVar::StringVar(PluginModule* module, const char* str, uint32 len) diff --git a/webkit/glue/plugins/pepper_var.h b/webkit/glue/plugins/pepper_var.h index 0eb1807..8929448 100644 --- a/webkit/glue/plugins/pepper_var.h +++ b/webkit/glue/plugins/pepper_var.h @@ -10,6 +10,7 @@ #include "webkit/glue/plugins/pepper_resource.h" struct PP_Var; +struct PPB_Var; struct PPB_Var_Deprecated; typedef struct NPObject NPObject; typedef struct _NPVariant NPVariant; @@ -82,6 +83,9 @@ class Var : public Resource { // Returns the PPB_Var_Deprecated interface for the plugin to use. static const PPB_Var_Deprecated* GetDeprecatedInterface(); + // Returns the PPB_Var interface for the plugin to use. + static const PPB_Var* GetInterface(); + protected: // This can only be constructed as a StringVar or an ObjectVar. explicit Var(PluginModule* module); -- cgit v1.1