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 a07127781dca7286aa24c776765eb2b28204f3ea..bafbada0ddd44d9ba23ee561e9bd9cb390bcee08 100644 |
--- a/content/renderer/pepper/ppb_var_deprecated_impl.cc |
+++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc |
@@ -7,259 +7,314 @@ |
#include <limits> |
#include "content/renderer/pepper/host_globals.h" |
-#include "content/renderer/pepper/message_channel.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/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/WebBindings.h" |
#include "third_party/WebKit/public/web/WebScopedUserGesture.h" |
-using ppapi::V8ObjectVar; |
+using ppapi::NPObjectVar; |
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"; |
- |
-class ObjectAccessor { |
+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 { |
public: |
- ObjectAccessor(PP_Var var) |
- : object_var_(V8ObjectVar::FromPPVar(var)), |
- instance_(object_var_ ? object_var_->instance() : NULL) { |
- } |
- |
- // 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); |
+ ObjectAccessorTryCatch(PP_Var object, PP_Var* exception) |
+ : TryCatch(exception), object_(NPObjectVar::FromPPVar(object)) { |
+ if (!object_.get()) { |
+ SetException(kInvalidObjectException); |
+ } |
+ } |
+ |
+ 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); |
+ } |
+ } |
+ |
+ NPIdentifier identifier() const { return identifier_; } |
+ |
+ private: |
+ NPIdentifier identifier_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch); |
+}; |
+ |
+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 HasPropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) { |
+ return PP_ToBool(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; |
- } |
- // 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: |
- V8ObjectVar* object_var_; |
- PepperPluginInstanceImpl* instance_; |
-}; |
- |
-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) { |
- 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) { |
- 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) && |
- accessor.GetObject()->Get(v8_name)->IsFunction(); |
- if (try_catch.HasException()) |
- return false; |
- return result; |
+ return WebBindings::hasMethod( |
+ NULL, accessor.object()->np_object(), accessor.identifier()); |
} |
PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) { |
- ObjectAccessor accessor(var); |
- if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) |
- return PP_MakeUndefined(); |
- |
- PepperTryCatchVar try_catch(accessor.instance(), exception); |
- v8::Handle<v8::Value> v8_name = try_catch.ToV8(name); |
- if (try_catch.HasException()) |
- return PP_MakeUndefined(); |
- |
- ScopedPPVar result_var = try_catch.FromV8(accessor.GetObject()->Get(v8_name)); |
- if (try_catch.HasException()) |
- return PP_MakeUndefined(); |
- |
- return result_var.Release(); |
+ 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) { |
- ObjectAccessor accessor(var); |
- if (!accessor.IsValid(exception)) |
- return; |
- |
- PepperTryCatchVar try_catch(accessor.instance(), exception); |
- |
*properties = NULL; |
*property_count = 0; |
- 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); |
- } |
- |
- size_t size = identifier_vars.size(); |
- *properties = identifier_vars.Release( |
- ScopedPPVarArray::PassPPBMemoryAllocatedArray()); |
- *property_count = size; |
+ 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(identifiers[i]); |
+ } |
+ free(identifiers); |
} |
void SetPropertyDeprecated(PP_Var var, |
PP_Var name, |
PP_Var value, |
PP_Var* exception) { |
- ObjectAccessor accessor(var); |
- if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) |
- return; |
- |
- 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; |
- |
- accessor.GetObject()->Set(v8_name, v8_value); |
- try_catch.HasException(); // Ensure an exception gets set if one occured. |
+ 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) { |
- ObjectAccessor accessor(var); |
- if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception)) |
- return; |
- |
- 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 CallDeprecatedInternal(PP_Var var, |
+ 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 InternalCallDeprecated(ObjectAccessorTryCatch* accessor, |
PP_Var method_name, |
uint32_t argc, |
PP_Var* argv, |
PP_Var* exception) { |
- 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); |
+ NPIdentifier identifier; |
if (method_name.type == PP_VARTYPE_UNDEFINED) { |
- 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(); |
- } |
- |
- 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(); |
- } |
- |
- 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()) |
+ 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(); |
- } |
- |
- 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(); |
- } |
- |
- 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(); |
+ } |
+ } else { |
+ accessor->SetException(kInvalidPropertyException); |
+ 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(); |
+ } |
+ } |
+ } |
+ |
+ 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 CallDeprecated(PP_Var var, |
@@ -267,39 +322,57 @@ |
uint32_t argc, |
PP_Var* argv, |
PP_Var* 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 CallDeprecatedInternal(var, method_name, argc, argv, 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); |
+ } |
+ return InternalCallDeprecated(&accessor, method_name, argc, argv, exception); |
} |
PP_Var Construct(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) { |
- // Deprecated. |
- NOTREACHED(); |
- return PP_MakeUndefined(); |
+ 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; |
} |
bool IsInstanceOfDeprecated(PP_Var var, |
const PPP_Class_Deprecated* ppp_class, |
void** ppp_class_data) { |
- scoped_refptr<V8ObjectVar> object(V8ObjectVar::FromPPVar(var)); |
+ scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var)); |
if (!object.get()) |
return false; // Not an object at all. |
- 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; |
+ return PluginObject::IsInstanceOf( |
+ object->np_object(), ppp_class, ppp_class_data); |
} |
PP_Var CreateObjectDeprecated(PP_Instance pp_instance, |