From 518209e0679963a6916eac655925d9932fd3018d Mon Sep 17 00:00:00 2001 From: "darin@chromium.org" Date: Wed, 19 May 2010 22:20:05 +0000 Subject: Add initial support for exceptions. Move some code into the anonymous namespace since it doesn't need to be exposed outside of pepper_var.cc. R=brettw BUG=none TEST=To be written once the new framework is available. Review URL: http://codereview.chromium.org/2123009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47738 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/glue/plugins/pepper_var.cc | 333 ++++++++++++++++++++++++-------------- webkit/glue/plugins/pepper_var.h | 18 --- 2 files changed, 211 insertions(+), 140 deletions(-) (limited to 'webkit') diff --git a/webkit/glue/plugins/pepper_var.cc b/webkit/glue/plugins/pepper_var.cc index 23894f7..1620ccc2 100644 --- a/webkit/glue/plugins/pepper_var.cc +++ b/webkit/glue/plugins/pepper_var.cc @@ -11,6 +11,10 @@ #include "third_party/ppapi/c/ppb_var.h" #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" #include "webkit/glue/plugins/pepper_string.h" +#include "v8/include/v8.h" + +// Uncomment to enable catching JS exceptions +// #define HAVE_WEBBINDINGS_EXCEPTION_HANDLER 1 using WebKit::WebBindings; @@ -18,6 +22,58 @@ namespace pepper { namespace { +PP_Var VarFromUtf8(const char* data, uint32_t len); + +// --------------------------------------------------------------------------- +// Exceptions + +class TryCatch { + public: + TryCatch(PP_Var* exception) : exception_(exception) { +#ifdef HAVE_WEBBINDINGS_EXCEPTION_HANDLER + WebBindings::pushExceptionHandler(&TryCatch::Catch, this); +#endif + } + + ~TryCatch() { +#ifdef HAVE_WEBBINDINGS_EXCEPTION_HANDLER + WebBindings::popExceptionHandler(); +#endif + } + + bool HasException() const { + return exception_ && exception_->type != PP_VarType_Void; + } + + void SetException(const char* message) { + DCHECK(!HasException()); + if (exception_) + *exception_ = VarFromUtf8(message, strlen(message)); + } + + private: + static void Catch(void* self, const NPUTF8* message) { + static_cast(self)->SetException(message); + } + + // May be null if the consumer isn't interesting in catching exceptions. + PP_Var* exception_; +}; + +const char kInvalidObjectException[] = "Error: Invalid object"; +const char kInvalidPropertyException[] = "Error: Invalid property"; +const char kUnableToGetPropertyException[] = "Error: Unable to get property"; +const char kUnableToSetPropertyException[] = "Error: Unable to set property"; +const char kUnableToRemovePropertyException[] = + "Error: Unable to remove property"; +const char kUnableToGetAllPropertiesException[] = + "Error: Unable to get all properties"; +const char kUnableToCallMethodException[] = "Error: Unable to call method"; +const char kUnableToConstructException[] = "Error: Unable to construct"; + +// --------------------------------------------------------------------------- +// Utilities + String* GetStringUnchecked(PP_Var var) { return reinterpret_cast(var.value.as_id); } @@ -32,6 +88,116 @@ NPObject* GetNPObject(PP_Var var) { return GetNPObjectUnchecked(var); } +// Returns a PP_Var that corresponds to the given NPVariant. The contents of +// the NPVariant will be copied unless the NPVariant corresponds to an object. +PP_Var NPVariantToPPVar(NPVariant* variant) { + switch (variant->type) { + case NPVariantType_Void: + return PP_MakeVoid(); + case NPVariantType_Null: + return PP_MakeNull(); + case NPVariantType_Bool: + return PP_MakeBool(NPVARIANT_TO_BOOLEAN(*variant)); + case NPVariantType_Int32: + return PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); + case NPVariantType_Double: + return PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); + case NPVariantType_String: + return VarFromUtf8(NPVARIANT_TO_STRING(*variant).UTF8Characters, + NPVARIANT_TO_STRING(*variant).UTF8Length); + case NPVariantType_Object: + return NPObjectToPPVar(NPVARIANT_TO_OBJECT(*variant)); + } + NOTREACHED(); + return PP_MakeVoid(); +} + +// Returns a NPVariant that corresponds to the given PP_Var. The contents of +// the PP_Var will be copied unless the PP_Var corresponds to an object. +NPVariant PPVarToNPVariant(PP_Var var) { + NPVariant ret; + switch (var.type) { + case PP_VarType_Void: + VOID_TO_NPVARIANT(ret); + break; + case PP_VarType_Null: + NULL_TO_NPVARIANT(ret); + break; + case PP_VarType_Bool: + BOOLEAN_TO_NPVARIANT(var.value.as_bool, ret); + break; + case PP_VarType_Int32: + INT32_TO_NPVARIANT(var.value.as_int, ret); + break; + case PP_VarType_Double: + DOUBLE_TO_NPVARIANT(var.value.as_double, ret); + break; + case PP_VarType_String: { + const std::string& value = GetStringUnchecked(var)->value(); + STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), ret); + break; + } + case PP_VarType_Object: { + NPObject* object = GetNPObjectUnchecked(var); + OBJECT_TO_NPVARIANT(WebBindings::retainObject(object), ret); + break; + } + } + return ret; +} + +// Returns a NPVariant that corresponds to the given PP_Var. The contents of +// the PP_Var will NOT be copied, so you need to ensure that the PP_Var remains +// valid while the resultant NPVariant is in use. +NPVariant PPVarToNPVariantNoCopy(PP_Var var) { + NPVariant ret; + switch (var.type) { + case PP_VarType_Void: + VOID_TO_NPVARIANT(ret); + break; + case PP_VarType_Null: + NULL_TO_NPVARIANT(ret); + break; + case PP_VarType_Bool: + BOOLEAN_TO_NPVARIANT(var.value.as_bool, ret); + break; + case PP_VarType_Int32: + INT32_TO_NPVARIANT(var.value.as_int, ret); + break; + case PP_VarType_Double: + DOUBLE_TO_NPVARIANT(var.value.as_double, ret); + break; + case PP_VarType_String: { + const std::string& value = GetStringUnchecked(var)->value(); + STRINGN_TO_NPVARIANT(value.c_str(), value.size(), ret); + break; + } + case PP_VarType_Object: { + OBJECT_TO_NPVARIANT(GetNPObjectUnchecked(var), ret); + break; + } + } + return ret; +} + +// Returns a NPIdentifier that corresponds to the given PP_Var. The contents +// of the PP_Var will be copied. Returns NULL if the given PP_Var is not a a +// string or integer type. +NPIdentifier PPVarToNPIdentifier(PP_Var var) { + switch (var.type) { + case PP_VarType_String: + return WebBindings::getStringIdentifier( + GetStringUnchecked(var)->value().c_str()); + case PP_VarType_Int32: + return WebBindings::getIntIdentifier(var.value.as_int); + default: + return NULL; + } +} + +// --------------------------------------------------------------------------- +// PPB_Var methods + void AddRef(PP_Var var) { if (var.type == PP_VarType_String) { GetStringUnchecked(var)->AddRef(); @@ -74,18 +240,19 @@ const char* VarToUtf8(PP_Var var, uint32_t* len) { bool HasProperty(PP_Var var, PP_Var name, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return false; NPObject* object = GetNPObject(var); if (!object) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidObjectException); return false; } NPIdentifier identifier = PPVarToNPIdentifier(name); if (!identifier) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidPropertyException); return false; } @@ -95,24 +262,27 @@ bool HasProperty(PP_Var var, PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return PP_MakeVoid(); NPObject* object = GetNPObject(var); if (!object) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidObjectException); return PP_MakeVoid(); } NPIdentifier identifier = PPVarToNPIdentifier(name); if (!identifier) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidPropertyException); return PP_MakeVoid(); } NPVariant result; if (!WebBindings::getProperty(NULL, object, identifier, &result)) { - // TODO(darin): raise exception + // An exception may have been raised. + if (!try_catch.HasException()) + try_catch.SetException(kUnableToGetPropertyException); return PP_MakeVoid(); } @@ -125,54 +295,64 @@ void GetAllPropertyNames(PP_Var var, uint32_t* property_count, PP_Var** properties, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return; - // TODO(darin) + // TODO(darin): Implement this method! + try_catch.SetException(kUnableToGetAllPropertiesException); } void SetProperty(PP_Var var, PP_Var name, PP_Var value, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return; NPObject* object = GetNPObject(var); if (!object) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidObjectException); return; } NPIdentifier identifier = PPVarToNPIdentifier(name); if (!identifier) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidPropertyException); return; } NPVariant variant = PPVarToNPVariantNoCopy(value); - WebBindings::setProperty(NULL, object, identifier, &variant); + if (!WebBindings::setProperty(NULL, object, identifier, &variant)) { + if (!try_catch.HasException()) + try_catch.SetException(kUnableToSetPropertyException); + } } void RemoveProperty(PP_Var var, PP_Var name, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return; NPObject* object = GetNPObject(var); if (!object) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidObjectException); return; } NPIdentifier identifier = PPVarToNPIdentifier(name); if (!identifier) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidPropertyException); return; } - WebBindings::removeProperty(NULL, object, identifier); + if (!WebBindings::removeProperty(NULL, object, identifier)) { + if (!try_catch.HasException()) + try_catch.SetException(kUnableToRemovePropertyException); + } } PP_Var Call(PP_Var var, @@ -180,12 +360,13 @@ PP_Var Call(PP_Var var, int32_t argc, PP_Var* argv, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return PP_MakeVoid(); NPObject* object = GetNPObject(var); if (!object) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidObjectException); return PP_MakeVoid(); } @@ -195,7 +376,7 @@ PP_Var Call(PP_Var var, } else { identifier = PPVarToNPIdentifier(method_name); if (!identifier) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidPropertyException); return PP_MakeVoid(); } } @@ -218,7 +399,9 @@ PP_Var Call(PP_Var var, } if (!ok) { - // TODO(darin): raise exception + // An exception may have been raised. + if (!try_catch.HasException()) + try_catch.SetException(kUnableToCallMethodException); return PP_MakeVoid(); } @@ -231,12 +414,13 @@ PP_Var Construct(PP_Var var, int32_t argc, PP_Var* argv, PP_Var* exception) { - if (exception && exception->type != PP_VarType_Void) + TryCatch try_catch(exception); + if (try_catch.HasException()) return PP_MakeVoid(); NPObject* object = GetNPObject(var); if (!object) { - // TODO(darin): raise exception + try_catch.SetException(kInvalidObjectException); return PP_MakeVoid(); } @@ -249,7 +433,9 @@ PP_Var Construct(PP_Var var, NPVariant result; if (!WebBindings::construct(NULL, object, args.get(), argc, &result)) { - // TODO(darin): raise exception + // An exception may have been raised. + if (!try_catch.HasException()) + try_catch.SetException(kUnableToConstructException); return PP_MakeVoid(); } @@ -260,7 +446,7 @@ PP_Var Construct(PP_Var var, PP_Var CreateObject(const PPP_Class* object_class, void* object_data) { - return PP_MakeVoid(); // TODO(darin) + return PP_MakeVoid(); // TODO(darin): Implement this method! } const PPB_Var var_interface = { @@ -292,101 +478,4 @@ PP_Var NPObjectToPPVar(NPObject* object) { return ret; } -PP_Var NPVariantToPPVar(NPVariant* variant) { - switch (variant->type) { - case NPVariantType_Void: - return PP_MakeVoid(); - case NPVariantType_Null: - return PP_MakeNull(); - case NPVariantType_Bool: - return PP_MakeBool(NPVARIANT_TO_BOOLEAN(*variant)); - case NPVariantType_Int32: - return PP_MakeInt32(NPVARIANT_TO_INT32(*variant)); - case NPVariantType_Double: - return PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant)); - case NPVariantType_String: - return VarFromUtf8(NPVARIANT_TO_STRING(*variant).UTF8Characters, - NPVARIANT_TO_STRING(*variant).UTF8Length); - case NPVariantType_Object: - return NPObjectToPPVar(NPVARIANT_TO_OBJECT(*variant)); - } - NOTREACHED(); - return PP_MakeVoid(); -} - -NPVariant PPVarToNPVariant(PP_Var var) { - NPVariant ret; - switch (var.type) { - case PP_VarType_Void: - VOID_TO_NPVARIANT(ret); - break; - case PP_VarType_Null: - NULL_TO_NPVARIANT(ret); - break; - case PP_VarType_Bool: - BOOLEAN_TO_NPVARIANT(var.value.as_bool, ret); - break; - case PP_VarType_Int32: - INT32_TO_NPVARIANT(var.value.as_int, ret); - break; - case PP_VarType_Double: - DOUBLE_TO_NPVARIANT(var.value.as_double, ret); - break; - case PP_VarType_String: { - const std::string& value = GetStringUnchecked(var)->value(); - STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), ret); - break; - } - case PP_VarType_Object: { - NPObject* object = GetNPObjectUnchecked(var); - OBJECT_TO_NPVARIANT(WebBindings::retainObject(object), ret); - break; - } - } - return ret; -} - -NPVariant PPVarToNPVariantNoCopy(PP_Var var) { - NPVariant ret; - switch (var.type) { - case PP_VarType_Void: - VOID_TO_NPVARIANT(ret); - break; - case PP_VarType_Null: - NULL_TO_NPVARIANT(ret); - break; - case PP_VarType_Bool: - BOOLEAN_TO_NPVARIANT(var.value.as_bool, ret); - break; - case PP_VarType_Int32: - INT32_TO_NPVARIANT(var.value.as_int, ret); - break; - case PP_VarType_Double: - DOUBLE_TO_NPVARIANT(var.value.as_double, ret); - break; - case PP_VarType_String: { - const std::string& value = GetStringUnchecked(var)->value(); - STRINGN_TO_NPVARIANT(value.c_str(), value.size(), ret); - break; - } - case PP_VarType_Object: { - OBJECT_TO_NPVARIANT(GetNPObjectUnchecked(var), ret); - break; - } - } - return ret; -} - -NPIdentifier PPVarToNPIdentifier(PP_Var var) { - switch (var.type) { - case PP_VarType_String: - return WebBindings::getStringIdentifier( - GetStringUnchecked(var)->value().c_str()); - case PP_VarType_Int32: - return WebBindings::getIntIdentifier(var.value.as_int); - default: - return NULL; - } -} - } // namespace pepper diff --git a/webkit/glue/plugins/pepper_var.h b/webkit/glue/plugins/pepper_var.h index 6c8c6b5..4c5c221 100644 --- a/webkit/glue/plugins/pepper_var.h +++ b/webkit/glue/plugins/pepper_var.h @@ -22,24 +22,6 @@ const PPB_Var* GetVarInterface(); // function multiple times given the same NPObject results in the same PP_Var. PP_Var NPObjectToPPVar(NPObject* object); -// Returns a PP_Var that corresponds to the given NPVariant. The contents of -// the NPVariant will be copied unless the NPVariant corresponds to an object. -PP_Var NPVariantToPPVar(NPVariant* variant); - -// Returns a NPVariant that corresponds to the given PP_Var. The contents of -// the PP_Var will be copied unless the PP_Var corresponds to an object. -NPVariant PPVarToNPVariant(PP_Var var); - -// Returns a NPVariant that corresponds to the given PP_Var. The contents of -// the PP_Var will NOT be copied, so you need to ensure that the PP_Var remains -// valid while the resultant NPVariant is in use. -NPVariant PPVarToNPVariantNoCopy(PP_Var var); - -// Returns a NPIdentifier that corresponds to the given PP_Var. The contents -// of the PP_Var will be copied. Returns NULL if the given PP_Var is not a a -// string or integer type. -NPIdentifier PPVarToNPIdentifier(PP_Var var); - } // namespace pepper #endif // WEBKIT_GLUE_PLUGINS_PEPPER_VAR_H_ -- cgit v1.1