Chromium Code Reviews| Index: content/renderer/pepper/ppb_var_deprecated_impl.cc |
| diff --git a/content/renderer/pepper/ppb_var_deprecated_impl.cc b/content/renderer/pepper/ppb_var_deprecated_impl.cc |
| index bafbada0ddd44d9ba23ee561e9bd9cb390bcee08..d3481aa88ace331ec91ecfc6eb806583c54ed1a2 100644 |
| --- a/content/renderer/pepper/ppb_var_deprecated_impl.cc |
| +++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc |
| @@ -7,314 +7,258 @@ |
| #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(), true, 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(), true, 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(), true, 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(), true, 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.get()); |
| } |
| - 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; |
| + *properties = identifier_vars.Release( |
| + ScopedPPVarArray::PassPPBMemoryAllocatedArray(), |
| + &size); |
| + *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(), true, 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(), true, 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_method(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_method = ScopedPPVar(ScopedPPVar::PassRef(), |
| + StringVar::StringToPPVar("")); |
| + } |
| + |
| + PepperTryCatchVar try_catch(accessor.instance(), true, exception); |
| + v8::Handle<v8::Value> v8_method_name = try_catch.ToV8(scoped_method.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(); |
| } |
| - 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 (try_catch.HasException()) |
| + return PP_MakeUndefined(); |
| + |
| + if (!function->IsFunction()) { |
| + try_catch.SetException(kUnableToCallMethodException); |
| + return PP_MakeUndefined(); |
| } |
| - if (!ok) { |
| - // An exception may have been raised. |
| - accessor->SetException(kUnableToCallMethodException); |
| + 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(); |
| + } |
| + |
| + blink::WebLocalFrame* frame = |
| + accessor.instance()->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; |
| + // TODO(raymes): Is this the right way to do this? |
| + v8::Handle<v8::Value> result = frame->callFunctionEvenIfScriptDisabled( |
| + function.As<v8::Function>(), recv, argc, converted_args.get()); |
|
raymes
2014/08/11 06:49:03
jochen: is this the appropriate way to execute a f
|
| + 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 +266,38 @@ 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); |
| + PepperTryCatchVar try_catch(object->instance(), false, NULL); |
| + 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, |