diff options
Diffstat (limited to 'content/renderer/pepper/ppb_var_deprecated_impl.cc')
-rw-r--r-- | content/renderer/pepper/ppb_var_deprecated_impl.cc | 453 |
1 files changed, 190 insertions, 263 deletions
diff --git a/content/renderer/pepper/ppb_var_deprecated_impl.cc b/content/renderer/pepper/ppb_var_deprecated_impl.cc index bafbada..a071277 100644 --- a/content/renderer/pepper/ppb_var_deprecated_impl.cc +++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc @@ -7,314 +7,259 @@ #include <limits> #include "content/renderer/pepper/host_globals.h" -#include "content/renderer/pepper/npapi_glue.h" -#include "content/renderer/pepper/npobject_var.h" +#include "content/renderer/pepper/message_channel.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" +#include "content/renderer/pepper/pepper_try_catch.h" #include "content/renderer/pepper/plugin_module.h" #include "content/renderer/pepper/plugin_object.h" +#include "content/renderer/pepper/v8object_var.h" #include "ppapi/c/dev/ppb_var_deprecated.h" #include "ppapi/c/ppb_var.h" -#include "ppapi/c/pp_var.h" #include "ppapi/shared_impl/ppb_var_shared.h" -#include "third_party/WebKit/public/web/WebBindings.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebPluginContainer.h" #include "third_party/WebKit/public/web/WebScopedUserGesture.h" -using ppapi::NPObjectVar; +using ppapi::V8ObjectVar; using ppapi::PpapiGlobals; +using ppapi::ScopedPPVar; +using ppapi::ScopedPPVarArray; using ppapi::StringVar; using ppapi::Var; -using blink::WebBindings; namespace content { namespace { +const char kInvalidIdentifierException[] = "Error: Invalid identifier."; 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: { - 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<NPObjectVar> object(NPObjectVar::FromPPVar(var)); - if (!object.get()) { - 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 { +class ObjectAccessor { public: - ObjectAccessorTryCatch(PP_Var object, PP_Var* exception) - : TryCatch(exception), object_(NPObjectVar::FromPPVar(object)) { - if (!object_.get()) { - SetException(kInvalidObjectException); - } + ObjectAccessor(PP_Var var) + : object_var_(V8ObjectVar::FromPPVar(var)), + instance_(object_var_ ? object_var_->instance() : NULL) { } - NPObjectVar* object() { return object_.get(); } - - PepperPluginInstanceImpl* GetPluginInstance() { - return HostGlobals::Get()->GetInstance(object()->pp_instance()); - } - - protected: - scoped_refptr<NPObjectVar> 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); - } + // Check if the object is valid. If it isn't, set an exception and return + // false. + bool IsValid(PP_Var* exception) { + // If we already have an exception, then the call is invalid according to + // the unittests. + if (exception && exception->type != PP_VARTYPE_UNDEFINED) + return false; + if (instance_) + return true; + if (exception) + *exception = ppapi::StringVar::StringToPPVar(kInvalidObjectException); + return false; } - - NPIdentifier identifier() const { return identifier_; } + // Lazily grab the object so that the handle is created in the current handle + // scope. + v8::Handle<v8::Object> GetObject() { return object_var_->GetHandle(); } + PepperPluginInstanceImpl* instance() { return instance_; } private: - NPIdentifier identifier_; - - DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); + V8ObjectVar* object_var_; + PepperPluginInstanceImpl* instance_; }; -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 PP_FromBool(WebBindings::hasProperty( - NULL, accessor.object()->np_object(), accessor.identifier())); +bool IsValidIdentifer(PP_Var identifier, PP_Var* exception) { + if (identifier.type == PP_VARTYPE_INT32 || + identifier.type == PP_VARTYPE_STRING) { + return true; + } + if (exception) + *exception = ppapi::StringVar::StringToPPVar(kInvalidIdentifierException); + return false; } bool HasPropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) { - return PP_ToBool(HasProperty(var, name, exception)); + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) + return false; + + PepperTryCatchVar try_catch(accessor.instance(), exception); + v8::Handle<v8::Value> v8_name = try_catch.ToV8(name); + if (try_catch.HasException()) + return false; + + bool result = accessor.GetObject()->Has(v8_name); + if (try_catch.HasException()) + return false; + return result; } bool HasMethodDeprecated(PP_Var var, PP_Var name, PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) + return false; + + PepperTryCatchVar try_catch(accessor.instance(), exception); + v8::Handle<v8::Value> v8_name = try_catch.ToV8(name); + if (try_catch.HasException()) return false; - return WebBindings::hasMethod( - NULL, accessor.object()->np_object(), accessor.identifier()); + + bool result = accessor.GetObject()->Has(v8_name) && + accessor.GetObject()->Get(v8_name)->IsFunction(); + if (try_catch.HasException()) + return false; + return result; } PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception) || !IsValidIdentifer(name, 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); + PepperTryCatchVar try_catch(accessor.instance(), exception); + v8::Handle<v8::Value> v8_name = try_catch.ToV8(name); + if (try_catch.HasException()) return PP_MakeUndefined(); - } - PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result); - WebBindings::releaseVariantValue(&result); - return ret; + ScopedPPVar result_var = try_catch.FromV8(accessor.GetObject()->Get(v8_name)); + if (try_catch.HasException()) + return PP_MakeUndefined(); + + return result_var.Release(); } void EnumerateProperties(PP_Var var, uint32_t* property_count, PP_Var** properties, PP_Var* exception) { + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception)) + return; + + PepperTryCatchVar try_catch(accessor.instance(), 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); + v8::Local<v8::Array> identifiers = accessor.GetObject()->GetPropertyNames(); + if (try_catch.HasException()) return; + ScopedPPVarArray identifier_vars(identifiers->Length()); + for (uint32_t i = 0; i < identifiers->Length(); ++i) { + ScopedPPVar var = try_catch.FromV8(identifiers->Get(i)); + if (try_catch.HasException()) + return; + identifier_vars.Set(i, var); } - 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(identifiers[i]); - } - free(identifiers); + size_t size = identifier_vars.size(); + *properties = identifier_vars.Release( + ScopedPPVarArray::PassPPBMemoryAllocatedArray()); + *property_count = size; } void SetPropertyDeprecated(PP_Var var, PP_Var name, PP_Var value, PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) return; - NPVariant variant; - if (!PPVarToNPVariantNoCopy(value, &variant)) { - accessor.SetException(kInvalidValueException); + PepperTryCatchVar try_catch(accessor.instance(), exception); + v8::Handle<v8::Value> v8_name = try_catch.ToV8(name); + v8::Handle<v8::Value> v8_value = try_catch.ToV8(value); + + if (try_catch.HasException()) return; - } - if (!WebBindings::setProperty(NULL, - accessor.object()->np_object(), - accessor.identifier(), - &variant)) - accessor.SetException(kUnableToSetPropertyException); + + accessor.GetObject()->Set(v8_name, v8_value); + try_catch.HasException(); // Ensure an exception gets set if one occured. } void DeletePropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) { - ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception); - if (accessor.has_exception()) + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) return; - if (!WebBindings::removeProperty( - NULL, accessor.object()->np_object(), accessor.identifier())) - accessor.SetException(kUnableToRemovePropertyException); + PepperTryCatchVar try_catch(accessor.instance(), exception); + v8::Handle<v8::Value> v8_name = try_catch.ToV8(name); + + if (try_catch.HasException()) + return; + + accessor.GetObject()->Delete(v8_name); + try_catch.HasException(); // Ensure an exception gets set if one occured. } -PP_Var InternalCallDeprecated(ObjectAccessorTryCatch* accessor, +PP_Var CallDeprecatedInternal(PP_Var var, PP_Var method_name, uint32_t argc, PP_Var* argv, PP_Var* exception) { - NPIdentifier identifier; + ObjectAccessor accessor(var); + if (!accessor.IsValid(exception)) + return PP_MakeUndefined(); + + // If the method name is undefined, set it to the empty string to trigger + // calling |var| as a function. + ScopedPPVar scoped_name(method_name); 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); + scoped_name = ScopedPPVar(ScopedPPVar::PassRef(), + StringVar::StringToPPVar("")); + } + + PepperTryCatchVar try_catch(accessor.instance(), exception); + v8::Handle<v8::Value> v8_method_name = try_catch.ToV8(scoped_name.get()); + if (try_catch.HasException()) + return PP_MakeUndefined(); + + if (!v8_method_name->IsString()) { + try_catch.SetException(kUnableToCallMethodException); return PP_MakeUndefined(); } - scoped_ptr<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(); - } - } + v8::Handle<v8::Object> function = accessor.GetObject(); + v8::Handle<v8::Object> recv = + accessor.instance()->GetContext()->Global(); + if (v8_method_name.As<v8::String>()->Length() != 0) { + function = function->Get(v8_method_name)->ToObject(); + recv = accessor.GetObject(); + } + + if (try_catch.HasException()) + return PP_MakeUndefined(); + + if (!function->IsFunction()) { + try_catch.SetException(kUnableToCallMethodException); + 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); + scoped_ptr<v8::Handle<v8::Value>[] > converted_args( + new v8::Handle<v8::Value>[argc]); + for (uint32_t i = 0; i < argc; ++i) { + converted_args[i] = try_catch.ToV8(argv[i]); + if (try_catch.HasException()) + return PP_MakeUndefined(); } - if (!ok) { - // An exception may have been raised. - accessor->SetException(kUnableToCallMethodException); + blink::WebPluginContainer* container = accessor.instance()->container(); + blink::WebLocalFrame* frame = NULL; + if (container) + frame = container->element().document().frame(); + + if (!frame) { + try_catch.SetException("No frame to execute script in."); return PP_MakeUndefined(); } - PP_Var ret = NPVariantToPPVar(accessor->GetPluginInstance(), &result); - WebBindings::releaseVariantValue(&result); - return ret; + v8::Handle<v8::Value> result = frame->callFunctionEvenIfScriptDisabled( + function.As<v8::Function>(), recv, argc, converted_args.get()); + ScopedPPVar result_var = try_catch.FromV8(result); + + if (try_catch.HasException()) + return PP_MakeUndefined(); + + return result_var.Release(); } PP_Var CallDeprecated(PP_Var var, @@ -322,57 +267,39 @@ PP_Var CallDeprecated(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) { - ObjectAccessorTryCatch accessor(var, exception); - if (accessor.has_exception()) - return PP_MakeUndefined(); - PepperPluginInstanceImpl* plugin = accessor.GetPluginInstance(); - if (plugin && plugin->IsProcessingUserGesture()) { - blink::WebScopedUserGesture user_gesture(plugin->CurrentUserGestureToken()); - return InternalCallDeprecated( - &accessor, method_name, argc, argv, exception); + ObjectAccessor accessor(var); + if (accessor.instance() && accessor.instance()->IsProcessingUserGesture()) { + blink::WebScopedUserGesture user_gesture( + accessor.instance()->CurrentUserGestureToken()); + return CallDeprecatedInternal(var, method_name, argc, argv, exception); } - return InternalCallDeprecated(&accessor, method_name, argc, argv, exception); + return CallDeprecatedInternal(var, method_name, argc, argv, exception); } 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_ptr<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; + // Deprecated. + NOTREACHED(); + return PP_MakeUndefined(); } bool IsInstanceOfDeprecated(PP_Var var, const PPP_Class_Deprecated* ppp_class, void** ppp_class_data) { - scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var)); + scoped_refptr<V8ObjectVar> object(V8ObjectVar::FromPPVar(var)); if (!object.get()) return false; // Not an object at all. - return PluginObject::IsInstanceOf( - object->np_object(), ppp_class, ppp_class_data); + v8::HandleScope handle_scope(object->instance()->GetIsolate()); + v8::Context::Scope context_scope(object->instance()->GetContext()); + PluginObject* plugin_object = PluginObject::FromV8Object( + object->instance()->GetIsolate(), object->GetHandle()); + if (plugin_object && plugin_object->ppp_class() == ppp_class) { + if (ppp_class_data) + *ppp_class_data = plugin_object->ppp_class_data(); + return true; + } + + return false; } PP_Var CreateObjectDeprecated(PP_Instance pp_instance, |