diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-28 16:12:04 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-28 16:12:04 +0000 |
commit | aaa72e79db2cda858908164f9e7aec4dbc8e14de (patch) | |
tree | aafde038620d62a0f516309a85708cfb19173815 /webkit/plugins/ppapi/ppb_var_impl.cc | |
parent | 996d322fc47bc052f00c17f0ea07e5a1799aaf35 (diff) | |
download | chromium_src-aaa72e79db2cda858908164f9e7aec4dbc8e14de.zip chromium_src-aaa72e79db2cda858908164f9e7aec4dbc8e14de.tar.gz chromium_src-aaa72e79db2cda858908164f9e7aec4dbc8e14de.tar.bz2 |
Make Var less dependent on NPAPI. The goal is to remove all of these
dependencies and then move Var and the associated tracking stuff to the
shared_impl, where it can be used to replace the similar code in the proxy.
There should be no difference in functionality.
- I moved the Var/NPAPI conversion stuff from the Var and ObjectVar object into
NPAPI glue.
- I moved the Var scripting interface implementation (which forwards to NPAPI)
to the ppb_var_impl file which is nice because it also matches other
interfaces.
- I moved the ObjectVar lifetime tracking from the instance into the
ResourceTracker with the other var stuff. It turns out we were already
tracking the object vars there, so I did a little cleanup.
- I changed the PluginModule and PluginInstance in the var object to PP_Module
and PP_Instance.
The only remaining NPAPI stuff to worry about are the calls to WebBindings in
the ObjectVar constructor & destructor. I will probably move this to the
resource tracker when I move the var file out.
Review URL: http://codereview.chromium.org/7371010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94470 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/plugins/ppapi/ppb_var_impl.cc')
-rw-r--r-- | webkit/plugins/ppapi/ppb_var_impl.cc | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/webkit/plugins/ppapi/ppb_var_impl.cc b/webkit/plugins/ppapi/ppb_var_impl.cc new file mode 100644 index 0000000..a3cf3d5d --- /dev/null +++ b/webkit/plugins/ppapi/ppb_var_impl.cc @@ -0,0 +1,456 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/plugins/ppapi/ppb_var_impl.h" + +#include <limits> + +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/c/pp_var.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" +#include "webkit/plugins/ppapi/common.h" +#include "webkit/plugins/ppapi/npapi_glue.h" +#include "webkit/plugins/ppapi/plugin_module.h" +#include "webkit/plugins/ppapi/plugin_object.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" +#include "webkit/plugins/ppapi/resource_tracker.h" +#include "webkit/plugins/ppapi/var.h" +#include "v8/include/v8.h" + +using WebKit::WebBindings; + +namespace webkit { +namespace ppapi { + +namespace { + +const char kInvalidObjectException[] = "Error: Invalid object"; +const char kInvalidPropertyException[] = "Error: Invalid property"; +const char kInvalidValueException[] = "Error: Invalid value"; +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 + +// Converts the given PP_Var to an NPVariant, returning true on success. +// False means that the given variant is invalid. In this case, the result +// NPVariant will be set to a void one. +// +// 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. +bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) { + switch (var.type) { + case PP_VARTYPE_UNDEFINED: + VOID_TO_NPVARIANT(*result); + break; + case PP_VARTYPE_NULL: + NULL_TO_NPVARIANT(*result); + break; + case PP_VARTYPE_BOOL: + BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result); + break; + case PP_VARTYPE_INT32: + INT32_TO_NPVARIANT(var.value.as_int, *result); + break; + case PP_VARTYPE_DOUBLE: + DOUBLE_TO_NPVARIANT(var.value.as_double, *result); + break; + case PP_VARTYPE_STRING: { + scoped_refptr<StringVar> string(StringVar::FromPPVar(var)); + if (!string) { + VOID_TO_NPVARIANT(*result); + return false; + } + const std::string& value = string->value(); + STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result); + break; + } + case PP_VARTYPE_OBJECT: { + scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); + if (!object) { + VOID_TO_NPVARIANT(*result); + return false; + } + OBJECT_TO_NPVARIANT(object->np_object(), *result); + break; + } + default: + VOID_TO_NPVARIANT(*result); + return false; + } + return true; +} + +// ObjectAccessorTryCatch ------------------------------------------------------ + +// Automatically sets up a TryCatch for accessing the object identified by the +// given PP_Var. The module from the object will be used for the exception +// strings generated by the TryCatch. +// +// This will automatically retrieve the ObjectVar from the object and throw +// an exception if it's invalid. At the end of construction, if there is no +// exception, you know that there is no previously set exception, that the +// object passed in is valid and ready to use (via the object() getter), and +// that the TryCatch's pp_module() getter is also set up properly and ready to +// use. +class ObjectAccessorTryCatch : public TryCatch { + public: + ObjectAccessorTryCatch(PP_Var object, PP_Var* exception) + : TryCatch(0, exception), + object_(ObjectVar::FromPPVar(object)) { + if (!object_) { + // No object or an invalid object was given. This means we have no module + // to associated with the exception text, so use the magic invalid object + // exception. + SetInvalidObjectException(); + } else { + // When the object is valid, we have a valid module to associate + set_pp_module(object_->pp_module()); + } + } + + ObjectVar* object() { return object_.get(); } + + PluginInstance* GetPluginInstance() { + return ResourceTracker::Get()->GetInstance(object()->pp_instance()); + } + + protected: + scoped_refptr<ObjectVar> object_; + + DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch); +}; + +// ObjectAccessiorWithIdentifierTryCatch --------------------------------------- + +// Automatically sets up a TryCatch for accessing the identifier on the given +// object. This just extends ObjectAccessorTryCatch to additionally convert +// the given identifier to an NPIdentifier and validate it, throwing an +// exception if it's invalid. +// +// At the end of construction, if there is no exception, you know that there is +// no previously set exception, that the object passed in is valid and ready to +// use (via the object() getter), that the identifier is valid and ready to +// use (via the identifier() getter), and that the TryCatch's pp_module() getter +// is also set up properly and ready to use. +class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch { + public: + ObjectAccessorWithIdentifierTryCatch(PP_Var object, + PP_Var identifier, + PP_Var* exception) + : ObjectAccessorTryCatch(object, exception), + identifier_(0) { + if (!has_exception()) { + identifier_ = PPVarToNPIdentifier(identifier); + if (!identifier_) + SetException(kInvalidPropertyException); + } + } + + NPIdentifier identifier() const { return identifier_; } + + private: + NPIdentifier identifier_; + + DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); +}; + +// PPB_Var methods ------------------------------------------------------------- + +PP_Var VarFromUtf8(PP_Module module, const char* data, uint32_t len) { + return StringVar::StringToPPVar(module, data, len); +} + +const char* VarToUtf8(PP_Var var, uint32_t* len) { + scoped_refptr<StringVar> str(StringVar::FromPPVar(var)); + if (!str) { + *len = 0; + return NULL; + } + *len = static_cast<uint32_t>(str->value().size()); + if (str->value().empty()) + return ""; // Don't return NULL on success. + return str->value().data(); +} + +PP_Bool HasProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return PP_FALSE; + return BoolToPPBool(WebBindings::hasProperty(NULL, + accessor.object()->np_object(), + accessor.identifier())); +} + +bool HasPropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + return PPBoolToBool(HasProperty(var, name, exception)); +} + +bool HasMethodDeprecated(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return false; + return WebBindings::hasMethod(NULL, accessor.object()->np_object(), + accessor.identifier()); +} + +PP_Var GetProperty(PP_Var var, + PP_Var name, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return PP_MakeUndefined(); + + NPVariant result; + if (!WebBindings::getProperty(NULL, accessor.object()->np_object(), + accessor.identifier(), &result)) { + // An exception may have been raised. + accessor.SetException(kUnableToGetPropertyException); + return PP_MakeUndefined(); + } + + PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + +void EnumerateProperties(PP_Var var, + uint32_t* property_count, + PP_Var** properties, + PP_Var* exception) { + *properties = NULL; + *property_count = 0; + + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) + return; + + NPIdentifier* identifiers = NULL; + uint32_t count = 0; + if (!WebBindings::enumerate(NULL, accessor.object()->np_object(), + &identifiers, &count)) { + accessor.SetException(kUnableToGetAllPropertiesException); + return; + } + + if (count == 0) + return; + + *property_count = count; + *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count)); + for (uint32_t i = 0; i < count; ++i) { + (*properties)[i] = NPIdentifierToPPVar( + accessor.GetPluginInstance()->module()->pp_module(), + identifiers[i]); + } + free(identifiers); +} + +void SetPropertyDeprecated(PP_Var var, + PP_Var name, + PP_Var value, + PP_Var* exception) { + ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); + if (accessor.has_exception()) + return; + + NPVariant variant; + if (!PPVarToNPVariantNoCopy(value, &variant)) { + accessor.SetException(kInvalidValueException); + return; + } + if (!WebBindings::setProperty(NULL, accessor.object()->np_object(), + accessor.identifier(), &variant)) + accessor.SetException(kUnableToSetPropertyException); +} + +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(), + accessor.identifier())) + accessor.SetException(kUnableToRemovePropertyException); +} + +PP_Var CallDeprecated(PP_Var var, + PP_Var method_name, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) + return PP_MakeUndefined(); + + NPIdentifier identifier; + if (method_name.type == PP_VARTYPE_UNDEFINED) { + identifier = NULL; + } else if (method_name.type == PP_VARTYPE_STRING) { + // Specifically allow only string functions to be called. + identifier = PPVarToNPIdentifier(method_name); + if (!identifier) { + accessor.SetException(kInvalidPropertyException); + return PP_MakeUndefined(); + } + } else { + accessor.SetException(kInvalidPropertyException); + return PP_MakeUndefined(); + } + + scoped_array<NPVariant> 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(); + } + } + } + + bool ok; + + NPVariant result; + if (identifier) { + ok = WebBindings::invoke(NULL, accessor.object()->np_object(), + identifier, args.get(), argc, &result); + } else { + ok = WebBindings::invokeDefault(NULL, accessor.object()->np_object(), + args.get(), argc, &result); + } + + if (!ok) { + // An exception may have been raised. + accessor.SetException(kUnableToCallMethodException); + return PP_MakeUndefined(); + } + + PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + +PP_Var Construct(PP_Var var, + uint32_t argc, + PP_Var* argv, + PP_Var* exception) { + ObjectAccessorTryCatch accessor(var, exception); + if (accessor.has_exception()) + return PP_MakeUndefined(); + + scoped_array<NPVariant> 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::construct(NULL, accessor.object()->np_object(), + args.get(), argc, &result)) { + // An exception may have been raised. + accessor.SetException(kUnableToConstructException); + return PP_MakeUndefined(); + } + + PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); + WebBindings::releaseVariantValue(&result); + return ret; +} + +bool IsInstanceOfDeprecated(PP_Var var, + const PPP_Class_Deprecated* ppp_class, + void** ppp_class_data) { + scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); + if (!object) + return false; // Not an object at all. + + return PluginObject::IsInstanceOf(object->np_object(), + ppp_class, ppp_class_data); +} + +PP_Var CreateObjectDeprecated(PP_Instance instance_id, + const PPP_Class_Deprecated* ppp_class, + void* ppp_class_data) { + PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); + if (!instance) { + DLOG(ERROR) << "Create object passed an invalid instance."; + return PP_MakeNull(); + } + return PluginObject::Create(instance, ppp_class, ppp_class_data); +} + +PP_Var CreateObjectWithModuleDeprecated(PP_Module module_id, + const PPP_Class_Deprecated* ppp_class, + void* ppp_class_data) { + PluginModule* module = ResourceTracker::Get()->GetModule(module_id); + if (!module) + return PP_MakeNull(); + return PluginObject::Create(module->GetSomeInstance(), + ppp_class, ppp_class_data); +} + +const PPB_Var_Deprecated var_deprecated_interface = { + &Var::PluginAddRefPPVar, + &Var::PluginReleasePPVar, + &VarFromUtf8, + &VarToUtf8, + &HasPropertyDeprecated, + &HasMethodDeprecated, + &GetProperty, + &EnumerateProperties, + &SetPropertyDeprecated, + &DeletePropertyDeprecated, + &CallDeprecated, + &Construct, + &IsInstanceOfDeprecated, + &CreateObjectDeprecated, + &CreateObjectWithModuleDeprecated, +}; + +const PPB_Var var_interface = { + &Var::PluginAddRefPPVar, + &Var::PluginReleasePPVar, + &VarFromUtf8, + &VarToUtf8 +}; + +} // namespace + +// static +const PPB_Var* PPB_Var_Impl::GetVarInterface() { + return &var_interface; +} + +// static +const PPB_Var_Deprecated* PPB_Var_Impl::GetVarDeprecatedInterface() { + return &var_deprecated_interface; +} + +} // namespace ppapi +} // namespace webkit + |