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..6b2febd9b425259eee41ec94c642f2d5d375d973 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/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_(NULL) { |
+ if (object_var_) { |
+ instance_ = static_cast<PepperPluginInstanceImpl*>( |
+ PepperPluginInstance::Get(object_var_->instance())); |
} |
} |
- 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; |
- return WebBindings::hasMethod( |
- NULL, accessor.object()->np_object(), accessor.identifier()); |
+ |
+ 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) && |
+ 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.Release()); |
} |
- 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(&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()->GetPluginContext()->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::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()); |
+ 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,40 @@ 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); |
+ PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( |
+ PepperPluginInstance::Get(object->instance())); |
+ PepperTryCatchVar try_catch(instance, false, NULL); |
+ PluginObject* plugin_object = PluginObject::FromV8Object( |
+ 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, |