Index: webkit/glue/plugins/pepper_plugin_object.cc |
=================================================================== |
--- webkit/glue/plugins/pepper_plugin_object.cc (revision 69381) |
+++ webkit/glue/plugins/pepper_plugin_object.cc (working copy) |
@@ -1,891 +0,0 @@ |
-// Copyright (c) 2010 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/glue/plugins/pepper_plugin_object.h" |
- |
-#include "base/logging.h" |
-#include "base/ref_counted.h" |
-#include "base/scoped_ptr.h" |
-#include "base/string_number_conversions.h" |
-#include "base/string_util.h" |
-#include "third_party/npapi/bindings/npapi.h" |
-#include "third_party/npapi/bindings/npruntime.h" |
-#include "ppapi/c/dev/ppb_var_deprecated.h" |
-#include "ppapi/c/dev/ppp_class_deprecated.h" |
-#include "ppapi/c/pp_resource.h" |
-#include "ppapi/c/pp_var.h" |
-#include "ppapi/c/ppb_class.h" |
-#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" |
-#include "webkit/glue/plugins/pepper_class.h" |
-#include "webkit/glue/plugins/pepper_plugin_module.h" |
-#include "webkit/glue/plugins/pepper_resource.h" |
-#include "webkit/glue/plugins/pepper_string.h" |
-#include "webkit/glue/plugins/pepper_var.h" |
- |
-using WebKit::WebBindings; |
- |
-namespace pepper { |
- |
-namespace { |
- |
-const char kInvalidValueException[] = "Error: Invalid value"; |
-const char kInvalidPluginValue[] = "Error: Plugin returned invalid value."; |
- |
-// ----------------------------------------------------------------------------- |
-// 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 be copied unless the PP_Var corresponds to |
-// an object. |
-bool PPVarToNPVariant(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(base::strdup(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(WebBindings::retainObject(object->np_object()), |
- *result); |
- break; |
- } |
- } |
- return true; |
-} |
- |
-// PPVarArrayFromNPVariantArray ------------------------------------------------ |
- |
-// Converts an array of NPVariants to an array of PP_Var, and scopes the |
-// ownership of the PP_Var. This is used when converting argument lists from |
-// WebKit to the plugin. |
-class PPVarArrayFromNPVariantArray { |
- public: |
- PPVarArrayFromNPVariantArray(PluginModule* module, |
- size_t size, |
- const NPVariant* variants) |
- : size_(size) { |
- if (size_ > 0) { |
- array_.reset(new PP_Var[size_]); |
- for (size_t i = 0; i < size_; i++) |
- array_[i] = Var::NPVariantToPPVar(module, &variants[i]); |
- } |
- } |
- |
- ~PPVarArrayFromNPVariantArray() { |
- for (size_t i = 0; i < size_; i++) |
- Var::PluginReleasePPVar(array_[i]); |
- } |
- |
- PP_Var* array() { return array_.get(); } |
- |
- private: |
- size_t size_; |
- scoped_array<PP_Var> array_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PPVarArrayFromNPVariantArray); |
-}; |
- |
-// PPVarFromNPObject ----------------------------------------------------------- |
- |
-// Converts an NPObject tp PP_Var, and scopes the ownership of the PP_Var. This |
-// is used when converting 'this' pointer from WebKit to the plugin. |
-class PPVarFromNPObject { |
- public: |
- PPVarFromNPObject(PluginModule* module, NPObject* object) |
- : var_(ObjectVar::NPObjectToPPVar(module, object)) { |
- } |
- ~PPVarFromNPObject() { |
- Var::PluginReleasePPVar(var_); |
- } |
- PP_Var var() const { return var_; } |
- private: |
- const PP_Var var_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PPVarFromNPObject); |
-}; |
- |
-// PPResultAndExceptionToNPResult ---------------------------------------------- |
- |
-// Convenience object for converting a PPAPI call that can throw an exception |
-// and optionally return a value, back to the NPAPI layer which expects a |
-// NPVariant as a result. |
-// |
-// Normal usage is that you will pass the result of exception() to the |
-// PPAPI function as the exception output parameter. Then you will either |
-// call SetResult with the result of the PPAPI call, or |
-// CheckExceptionForNoResult if the PPAPI call doesn't return a PP_Var. |
-// |
-// Both SetResult and CheckExceptionForNoResult will throw an exception to |
-// the JavaScript library if the plugin reported an exception. SetResult |
-// will additionally convert the result to an NPVariant and write it to the |
-// output parameter given in the constructor. |
-class PPResultAndExceptionToNPResult { |
- public: |
- // The object_var parameter is the object to associate any exception with. |
- // It may not be NULL. |
- // |
- // The np_result parameter is the NPAPI result output parameter. This may be |
- // NULL if there is no NPVariant result (like for HasProperty). If this is |
- // specified, you must call SetResult() to set it. If it is not, you must |
- // call CheckExceptionForNoResult to do the exception checking with no result |
- // conversion. |
- PPResultAndExceptionToNPResult(NPObject* object_var, |
- NPVariant* np_result) |
- : object_var_(object_var), |
- np_result_(np_result), |
- exception_(PP_MakeUndefined()), |
- success_(false), |
- checked_exception_(false) { |
- } |
- |
- ~PPResultAndExceptionToNPResult() { |
- // The user should have called SetResult or CheckExceptionForNoResult |
- // before letting this class go out of scope, or the exception will have |
- // been lost. |
- DCHECK(checked_exception_); |
- |
- ObjectVar::PluginReleasePPVar(exception_); |
- } |
- |
- // Returns true if an exception has been set. |
- bool has_exception() const { return exception_.type != PP_VARTYPE_UNDEFINED; } |
- |
- // Returns a pointer to the exception. You would pass this to the PPAPI |
- // function as the exception parameter. If it is set to non-void, this object |
- // will take ownership of destroying it. |
- PP_Var* exception() { return &exception_; } |
- |
- // Returns true if everything succeeded with no exception. This is valid only |
- // after calling SetResult/CheckExceptionForNoResult. |
- bool success() const { |
- DCHECK(checked_exception_); |
- return success_; |
- } |
- |
- // Call this with the return value of the PPAPI function. It will convert |
- // the result to the NPVariant output parameter and pass any exception on to |
- // the JS engine. It will update the success flag and return it. |
- bool SetResult(PP_Var result) { |
- DCHECK(!checked_exception_); // Don't call more than once. |
- DCHECK(np_result_); // Should be expecting a result. |
- |
- checked_exception_ = true; |
- |
- if (has_exception()) { |
- ThrowException(); |
- success_ = false; |
- } else if (!PPVarToNPVariant(result, np_result_)) { |
- WebBindings::setException(object_var_, kInvalidPluginValue); |
- success_ = false; |
- } else { |
- success_ = true; |
- } |
- |
- // No matter what happened, we need to release the reference to the |
- // value passed in. On success, a reference to this value will be in |
- // the np_result_. |
- Var::PluginReleasePPVar(result); |
- return success_; |
- } |
- |
- // Call this after calling a PPAPI function that could have set the |
- // exception. It will pass the exception on to the JS engine and update |
- // the success flag. |
- // |
- // The success flag will be returned. |
- bool CheckExceptionForNoResult() { |
- DCHECK(!checked_exception_); // Don't call more than once. |
- DCHECK(!np_result_); // Can't have a result when doing this. |
- |
- checked_exception_ = true; |
- |
- if (has_exception()) { |
- ThrowException(); |
- success_ = false; |
- return false; |
- } |
- success_ = true; |
- return true; |
- } |
- |
- // Call this to ignore any exception. This prevents the DCHECK from failing |
- // in the destructor. |
- void IgnoreException() { |
- checked_exception_ = true; |
- } |
- |
- private: |
- // Throws the current exception to JS. The exception must be set. |
- void ThrowException() { |
- scoped_refptr<StringVar> string(StringVar::FromPPVar(exception_)); |
- if (string) { |
- WebBindings::setException(object_var_, string->value().c_str()); |
- } |
- } |
- |
- NPObject* object_var_; // Non-owning ref (see constructor). |
- NPVariant* np_result_; // Output value, possibly NULL (see constructor). |
- PP_Var exception_; // Exception set by the PPAPI call. We own a ref to it. |
- bool success_; // See the success() function above. |
- bool checked_exception_; // SetResult/CheckExceptionForNoResult was called. |
- |
- DISALLOW_COPY_AND_ASSIGN(PPResultAndExceptionToNPResult); |
-}; |
- |
-// NPObjectAccessorWithIdentifier ---------------------------------------------- |
- |
-// Helper class for our NPObject wrapper. This converts a call from WebKit |
-// where it gives us an NPObject and an NPIdentifier to an easily-accessible |
-// ObjectVar (corresponding to the NPObject) and PP_Var (corresponding to the |
-// NPIdentifier). |
-// |
-// If the NPObject or identifier is invalid, we'll set is_valid() to false. |
-// The caller should check is_valid() before doing anything with the class. |
-// |
-// JS can't have integer functions, so when dealing with these, we don't want |
-// to allow integer identifiers. The calling code can decode if it wants to |
-// allow integer identifiers (like for property access) or prohibit them |
-// (like for method calling) by setting |allow_integer_identifier|. If this |
-// is false and the identifier is an integer, we'll set is_valid() to false. |
-// |
-// Getting an integer identifier in this case should be impossible. V8 |
-// shouldn't be allowing this, and the Pepper Var calls from the plugin are |
-// supposed to error out before calling into V8 (which will then call us back). |
-// Aside from an egregious error, the only time this could happen is an NPAPI |
-// plugin calling us. |
-class NPObjectAccessorWithIdentifier { |
- public: |
- NPObjectAccessorWithIdentifier(NPObject* object, |
- NPIdentifier identifier, |
- bool allow_integer_identifier) |
- : object_(PluginObject::FromNPObject(object)), |
- identifier_(PP_MakeUndefined()) { |
- if (object_) { |
- identifier_ = Var::NPIdentifierToPPVar(object_->module(), identifier); |
- if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier) |
- identifier_.type = PP_VARTYPE_UNDEFINED; // Mark it invalid. |
- } |
- } |
- |
- ~NPObjectAccessorWithIdentifier() { |
- Var::PluginReleasePPVar(identifier_); |
- } |
- |
- // Returns true if both the object and identifier are valid. |
- bool is_valid() const { |
- return object_ && identifier_.type != PP_VARTYPE_UNDEFINED; |
- } |
- |
- PluginObject* object() { return object_; } |
- PP_Var identifier() const { return identifier_; } |
- |
- private: |
- PluginObject* object_; |
- PP_Var identifier_; |
- |
- DISALLOW_COPY_AND_ASSIGN(NPObjectAccessorWithIdentifier); |
-}; |
- |
-// NPObject implementation in terms of PPP_Class_Deprecated -------------------- |
- |
-NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) { |
- return PluginObject::AllocateObjectWrapper(); |
-} |
- |
-void WrapperClass_Deallocate(NPObject* np_object) { |
- PluginObject* plugin_object = PluginObject::FromNPObject(np_object); |
- if (!plugin_object) |
- return; |
- plugin_object->ppp_class()->Deallocate(plugin_object->ppp_class_data()); |
- delete plugin_object; |
-} |
- |
-void WrapperClass_Invalidate(NPObject* object) { |
-} |
- |
-bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) { |
- NPObjectAccessorWithIdentifier accessor(object, method_name, false); |
- if (!accessor.is_valid()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter( |
- accessor.object()->GetNPObject(), NULL); |
- bool rv = accessor.object()->ppp_class()->HasMethod( |
- accessor.object()->ppp_class_data(), accessor.identifier(), |
- result_converter.exception()); |
- result_converter.CheckExceptionForNoResult(); |
- return rv; |
-} |
- |
-bool WrapperClass_Invoke(NPObject* object, NPIdentifier method_name, |
- const NPVariant* argv, uint32_t argc, |
- NPVariant* result) { |
- NPObjectAccessorWithIdentifier accessor(object, method_name, false); |
- if (!accessor.is_valid()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter( |
- accessor.object()->GetNPObject(), result); |
- PPVarArrayFromNPVariantArray args(accessor.object()->module(), argc, argv); |
- |
- return result_converter.SetResult(accessor.object()->ppp_class()->Call( |
- accessor.object()->ppp_class_data(), accessor.identifier(), |
- argc, args.array(), result_converter.exception())); |
-} |
- |
-bool WrapperClass_InvokeDefault(NPObject* np_object, const NPVariant* argv, |
- uint32_t argc, NPVariant* result) { |
- PluginObject* obj = PluginObject::FromNPObject(np_object); |
- if (!obj) |
- return false; |
- |
- PPVarArrayFromNPVariantArray args(obj->module(), argc, argv); |
- PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result); |
- |
- result_converter.SetResult(obj->ppp_class()->Call( |
- obj->ppp_class_data(), PP_MakeUndefined(), argc, args.array(), |
- result_converter.exception())); |
- return result_converter.success(); |
-} |
- |
-bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) { |
- NPObjectAccessorWithIdentifier accessor(object, property_name, true); |
- if (!accessor.is_valid()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter( |
- accessor.object()->GetNPObject(), NULL); |
- bool rv = accessor.object()->ppp_class()->HasProperty( |
- accessor.object()->ppp_class_data(), accessor.identifier(), |
- result_converter.exception()); |
- result_converter.CheckExceptionForNoResult(); |
- return rv; |
-} |
- |
-bool WrapperClass_GetProperty(NPObject* object, NPIdentifier property_name, |
- NPVariant* result) { |
- NPObjectAccessorWithIdentifier accessor(object, property_name, true); |
- if (!accessor.is_valid()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter( |
- accessor.object()->GetNPObject(), result); |
- return result_converter.SetResult(accessor.object()->ppp_class()->GetProperty( |
- accessor.object()->ppp_class_data(), accessor.identifier(), |
- result_converter.exception())); |
-} |
- |
-bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name, |
- const NPVariant* value) { |
- NPObjectAccessorWithIdentifier accessor(object, property_name, true); |
- if (!accessor.is_valid()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter( |
- accessor.object()->GetNPObject(), NULL); |
- PP_Var value_var = Var::NPVariantToPPVar(accessor.object()->module(), value); |
- accessor.object()->ppp_class()->SetProperty( |
- accessor.object()->ppp_class_data(), accessor.identifier(), value_var, |
- result_converter.exception()); |
- Var::PluginReleasePPVar(value_var); |
- return result_converter.CheckExceptionForNoResult(); |
-} |
- |
-bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) { |
- NPObjectAccessorWithIdentifier accessor(object, property_name, true); |
- if (!accessor.is_valid()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter( |
- accessor.object()->GetNPObject(), NULL); |
- accessor.object()->ppp_class()->RemoveProperty( |
- accessor.object()->ppp_class_data(), accessor.identifier(), |
- result_converter.exception()); |
- return result_converter.CheckExceptionForNoResult(); |
-} |
- |
-bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values, |
- uint32_t* count) { |
- *values = NULL; |
- *count = 0; |
- PluginObject* obj = PluginObject::FromNPObject(object); |
- if (!obj) |
- return false; |
- |
- uint32_t property_count = 0; |
- PP_Var* properties = NULL; // Must be freed! |
- PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), NULL); |
- obj->ppp_class()->GetAllPropertyNames(obj->ppp_class_data(), |
- &property_count, &properties, |
- result_converter.exception()); |
- |
- // Convert the array of PP_Var to an array of NPIdentifiers. If any |
- // conversions fail, we will set the exception. |
- if (!result_converter.has_exception()) { |
- if (property_count > 0) { |
- *values = static_cast<NPIdentifier*>( |
- malloc(sizeof(NPIdentifier) * property_count)); |
- *count = 0; // Will be the number of items successfully converted. |
- for (uint32_t i = 0; i < property_count; ++i) { |
- if (!((*values)[i] = Var::PPVarToNPIdentifier(properties[i]))) { |
- // Throw an exception for the failed convertion. |
- *result_converter.exception() = StringVar::StringToPPVar( |
- obj->module(), kInvalidValueException); |
- break; |
- } |
- (*count)++; |
- } |
- |
- if (result_converter.has_exception()) { |
- // We don't actually have to free the identifiers we converted since |
- // all identifiers leak anyway :( . |
- free(*values); |
- *values = NULL; |
- *count = 0; |
- } |
- } |
- } |
- |
- // This will actually throw the exception, either from GetAllPropertyNames, |
- // or if anything was set during the conversion process. |
- result_converter.CheckExceptionForNoResult(); |
- |
- // Release the PP_Var that the plugin allocated. On success, they will all |
- // be converted to NPVariants, and on failure, we want them to just go away. |
- for (uint32_t i = 0; i < property_count; ++i) |
- Var::PluginReleasePPVar(properties[i]); |
- free(properties); |
- return result_converter.success(); |
-} |
- |
-bool WrapperClass_Construct(NPObject* object, const NPVariant* argv, |
- uint32_t argc, NPVariant* result) { |
- PluginObject* obj = PluginObject::FromNPObject(object); |
- if (!obj) |
- return false; |
- |
- PPVarArrayFromNPVariantArray args(obj->module(), argc, argv); |
- PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result); |
- return result_converter.SetResult(obj->ppp_class()->Construct( |
- obj->ppp_class_data(), argc, args.array(), |
- result_converter.exception())); |
-} |
- |
-const NPClass wrapper_class = { |
- NP_CLASS_STRUCT_VERSION, |
- WrapperClass_Allocate, |
- WrapperClass_Deallocate, |
- WrapperClass_Invalidate, |
- WrapperClass_HasMethod, |
- WrapperClass_Invoke, |
- WrapperClass_InvokeDefault, |
- WrapperClass_HasProperty, |
- WrapperClass_GetProperty, |
- WrapperClass_SetProperty, |
- WrapperClass_RemoveProperty, |
- WrapperClass_Enumerate, |
- WrapperClass_Construct |
-}; |
- |
-} // namespace |
- |
-// PluginObject ---------------------------------------------------------------- |
- |
-struct PluginObject::NPObjectWrapper : public NPObject { |
- // Points to the var object that owns this wrapper. This value may be NULL |
- // if there is no var owning this wrapper. This can happen if the plugin |
- // releases all references to the var, but a reference to the underlying |
- // NPObject is still held by script on the page. |
- PluginObject* obj; |
-}; |
- |
-PluginObject::PluginObject(PluginModule* module, |
- NPObjectWrapper* object_wrapper, |
- const PPP_Class_Deprecated* ppp_class, |
- void* ppp_class_data) |
- : module_(module), |
- object_wrapper_(object_wrapper), |
- ppp_class_(ppp_class), |
- ppp_class_data_(ppp_class_data) { |
- // Make the object wrapper refer back to this class so our NPObject |
- // implementation can call back into the Pepper layer. |
- object_wrapper_->obj = this; |
- module_->AddPluginObject(this); |
-} |
- |
-PluginObject::~PluginObject() { |
- // The wrapper we made for this NPObject may still have a reference to it |
- // from JavaScript, so we clear out its ObjectVar back pointer which will |
- // cause all calls "up" to the plugin to become NOPs. Our ObjectVar base |
- // class will release our reference to the object, which may or may not |
- // delete the NPObject. |
- DCHECK(object_wrapper_->obj == this); |
- object_wrapper_->obj = NULL; |
- module_->RemovePluginObject(this); |
-} |
- |
-PP_Var PluginObject::Create(PluginModule* module, |
- const PPP_Class_Deprecated* ppp_class, |
- void* ppp_class_data) { |
- // This will internally end up calling our AllocateObjectWrapper via the |
- // WrapperClass_Allocated function which will have created an object wrapper |
- // appropriate for this class (derived from NPObject). |
- NPObjectWrapper* wrapper = static_cast<NPObjectWrapper*>( |
- WebBindings::createObject(NULL, const_cast<NPClass*>(&wrapper_class))); |
- |
- // This object will register itself both with the NPObject and with the |
- // PluginModule. The NPObject will normally handle its lifetime, and it |
- // will get deleted in the destroy method. It may also get deleted when the |
- // plugin module is deallocated. |
- new PluginObject(module, wrapper, ppp_class, ppp_class_data); |
- |
- // We can just use a normal ObjectVar to refer to this object from the |
- // plugin. It will hold a ref to the underlying NPObject which will in turn |
- // hold our pluginObject. |
- return ObjectVar::NPObjectToPPVar(module, wrapper); |
-} |
- |
-NPObject* PluginObject::GetNPObject() const { |
- return object_wrapper_; |
-} |
- |
-// static |
-bool PluginObject::IsInstanceOf(NPObject* np_object, |
- const PPP_Class_Deprecated* ppp_class, |
- void** ppp_class_data) { |
- // Validate that this object is implemented by our wrapper class before |
- // trying to get the PluginObject. |
- if (np_object->_class != &wrapper_class) |
- return false; |
- |
- PluginObject* plugin_object = FromNPObject(np_object); |
- if (!plugin_object) |
- return false; // Object is no longer alive. |
- |
- if (plugin_object->ppp_class() != ppp_class) |
- return false; |
- if (ppp_class_data) |
- *ppp_class_data = plugin_object->ppp_class_data(); |
- return true; |
-} |
- |
-// static |
-PluginObject* PluginObject::FromNPObject(NPObject* object) { |
- return static_cast<NPObjectWrapper*>(object)->obj; |
-} |
- |
-// static |
-NPObject* PluginObject::AllocateObjectWrapper() { |
- NPObjectWrapper* wrapper = new NPObjectWrapper; |
- memset(wrapper, 0, sizeof(NPObjectWrapper)); |
- return wrapper; |
-} |
- |
-// VarObjectClass::InstanceData ----------------------------------------------- |
- |
-struct VarObjectClass::InstanceData : public NPObject { |
- InstanceData() : native_data(NULL) {} |
- |
- scoped_refptr<VarObjectClass> object_class; |
- void* native_data; |
-}; |
- |
-// VarObjectClass::Property --------------------------------------------------- |
- |
-VarObjectClass::Property::Property(const PP_ClassProperty& prop) |
- : method(prop.method), |
- getter(prop.getter), |
- setter(prop.setter), |
- writable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_READONLY)), |
- enumerable(!(prop.modifiers & PP_OBJECTPROPERTY_MODIFIER_DONTENUM)) { |
-} |
- |
- |
-// VarObjectAccessorWithIdentifier --------------------------------------------- |
- |
-// Helper class for the new (PPB_Class) NPObject wrapper. This converts a call |
-// from WebKit where it gives us an NPObject and an NPIdentifier to an |
-// easily-accessible InstanceData (corresponding to the NPObject) and |
-// std::string and Property (corresponding to the NPIdentifier). |
-class VarObjectAccessorWithIdentifier { |
- public: |
- VarObjectAccessorWithIdentifier(NPObject* object, NPIdentifier identifier) |
- : exists_(false), |
- instance_(static_cast<VarObjectClass::InstanceData*>(object)), |
- property_(NULL) { |
- if (instance_) { |
- const NPUTF8* string_value = NULL; |
- int32_t int_value = 0; |
- bool is_string = false; |
- WebBindings::extractIdentifierData(identifier, string_value, int_value, |
- is_string); |
- if (is_string) { |
- property_name_ = string_value; |
- |
- const VarObjectClass::PropertyMap& properties = |
- instance_->object_class->properties(); |
- VarObjectClass::PropertyMap::const_iterator it = |
- properties.find(property_name_); |
- if (it != properties.end()) { |
- property_ = &it->second; |
- exists_ = true; |
- } |
- } |
- } |
- } |
- |
- // Return true if the object is valid, the identifier is valid, and the |
- // property with said name exists. |
- bool exists() const { return exists_; } |
- bool is_method() const { return exists() && property_->method; } |
- bool is_readable() const { return exists() && property_->getter; } |
- bool is_writable() const { |
- return exists() && property_->setter && property_->writable; |
- } |
- const VarObjectClass::InstanceData* instance() const { return instance_; } |
- const VarObjectClass::Property* property() const { return property_; } |
- PluginModule* module() const { |
- return instance_ ? instance_->object_class->module() : NULL; |
- } |
- |
- private: |
- bool exists_; |
- const VarObjectClass::InstanceData* instance_; |
- std::string property_name_; |
- const VarObjectClass::Property* property_; |
- |
- DISALLOW_COPY_AND_ASSIGN(VarObjectAccessorWithIdentifier); |
-}; |
- |
-// NPObject implementation in terms of PPB_Class ------------------------------- |
- |
-namespace { |
- |
-NPObject* VarObjectClassAllocate(NPP npp, NPClass* the_class) { |
- return new VarObjectClass::InstanceData; |
-} |
- |
-void VarObjectClassDeallocate(NPObject* object) { |
- VarObjectClass::InstanceData* instance = |
- static_cast<VarObjectClass::InstanceData*>(object); |
- if (instance->object_class->instance_native_destructor()) |
- instance->object_class->instance_native_destructor()(instance->native_data); |
- delete instance; |
-} |
- |
-bool VarObjectClassHasMethod(NPObject* np_obj, NPIdentifier name) { |
- VarObjectAccessorWithIdentifier accessor(np_obj, name); |
- return accessor.is_method(); |
-} |
- |
-bool VarObjectClassInvoke(NPObject* np_obj, NPIdentifier name, |
- const NPVariant* args, uint32 arg_count, |
- NPVariant* result) { |
- VarObjectAccessorWithIdentifier accessor(np_obj, name); |
- if (!accessor.is_method()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter(np_obj, result); |
- PPVarArrayFromNPVariantArray arguments(accessor.module(), arg_count, args); |
- PPVarFromNPObject self(accessor.module(), np_obj); |
- |
- return result_converter.SetResult(accessor.property()->method( |
- accessor.instance()->native_data, self.var(), arguments.array(), arg_count, |
- result_converter.exception())); |
-} |
- |
-bool VarObjectClassInvokeDefault(NPObject* np_obj, |
- const NPVariant* args, |
- uint32 arg_count, |
- NPVariant* result) { |
- VarObjectClass::InstanceData* instance = |
- static_cast<VarObjectClass::InstanceData*>(np_obj); |
- if (!instance || !instance->object_class->instance_invoke()) |
- return false; |
- |
- PPResultAndExceptionToNPResult result_converter(np_obj, result); |
- PPVarArrayFromNPVariantArray arguments(instance->object_class->module(), |
- arg_count, args); |
- PPVarFromNPObject self(instance->object_class->module(), np_obj); |
- |
- return result_converter.SetResult(instance->object_class->instance_invoke()( |
- instance->native_data, self.var(), arguments.array(), arg_count, |
- result_converter.exception())); |
-} |
- |
-bool VarObjectClassHasProperty(NPObject* np_obj, NPIdentifier name) { |
- VarObjectAccessorWithIdentifier accessor(np_obj, name); |
- return accessor.is_readable(); |
-} |
- |
-bool VarObjectClassGetProperty(NPObject* np_obj, NPIdentifier name, |
- NPVariant* result) { |
- VarObjectAccessorWithIdentifier accessor(np_obj, name); |
- if (!accessor.is_readable()) { |
- return false; |
- } |
- |
- PPResultAndExceptionToNPResult result_converter(np_obj, result); |
- PPVarFromNPObject self(accessor.module(), np_obj); |
- |
- return result_converter.SetResult(accessor.property()->getter( |
- accessor.instance()->native_data, self.var(), 0, 0, |
- result_converter.exception())); |
-} |
- |
-bool VarObjectClassSetProperty(NPObject* np_obj, NPIdentifier name, |
- const NPVariant* variant) { |
- VarObjectAccessorWithIdentifier accessor(np_obj, name); |
- if (!accessor.is_writable()) { |
- return false; |
- } |
- |
- PPResultAndExceptionToNPResult result_converter(np_obj, NULL); |
- PPVarArrayFromNPVariantArray arguments(accessor.module(), 1, variant); |
- PPVarFromNPObject self(accessor.module(), np_obj); |
- |
- // Ignore return value. |
- Var::PluginReleasePPVar(accessor.property()->setter( |
- accessor.instance()->native_data, self.var(), arguments.array(), 1, |
- result_converter.exception())); |
- |
- return result_converter.CheckExceptionForNoResult(); |
-} |
- |
-bool VarObjectClassEnumerate(NPObject *np_obj, NPIdentifier **value, |
- uint32_t *count) { |
- VarObjectClass::InstanceData* instance = |
- static_cast<VarObjectClass::InstanceData*>(np_obj); |
- *count = 0; |
- *value = NULL; |
- if (!instance) |
- return false; |
- |
- const VarObjectClass::PropertyMap& properties = |
- instance->object_class->properties(); |
- |
- // Don't bother calculating the size of enumerable properties, just allocate |
- // enough for all and then fill it partially. |
- *value = static_cast<NPIdentifier*>( |
- malloc(sizeof(NPIdentifier) * properties.size())); |
- |
- NPIdentifier* inserter = *value; |
- for (VarObjectClass::PropertyMap::const_iterator i = properties.begin(); |
- i != properties.end(); ++i) |
- if (i->second.enumerable) |
- *inserter++ = WebBindings::getStringIdentifier(i->first.c_str()); |
- |
- *count = inserter - *value; |
- return true; |
-} |
- |
-NPClass objectclassvar_class = { |
- NP_CLASS_STRUCT_VERSION, |
- &VarObjectClassAllocate, |
- &VarObjectClassDeallocate, |
- NULL, |
- &VarObjectClassHasMethod, |
- &VarObjectClassInvoke, |
- &VarObjectClassInvokeDefault, |
- &VarObjectClassHasProperty, |
- &VarObjectClassGetProperty, |
- &VarObjectClassSetProperty, |
- NULL, |
- &VarObjectClassEnumerate, |
-}; |
- |
-// PPB_Class interface --------------------------------------------------------- |
- |
-PP_Resource Create(PP_Module module, PP_ClassDestructor destruct, |
- PP_ClassFunction invoke, PP_ClassProperty* properties) { |
- PluginModule* plugin_module = ResourceTracker::Get()->GetModule(module); |
- if (!properties || !plugin_module) |
- return 0; |
- scoped_refptr<VarObjectClass> cls = new VarObjectClass(plugin_module, |
- destruct, |
- invoke, |
- properties); |
- if (!cls) |
- return 0; |
- return cls->GetReference(); |
-} |
- |
-PP_Var Instantiate(PP_Resource class_object, void* native_data, |
- PP_Var* exception) { |
- scoped_refptr<VarObjectClass> object_class = |
- Resource::GetAs<VarObjectClass>(class_object); |
- if (!object_class) |
- return PP_MakeUndefined(); |
- NPObject* obj = WebBindings::createObject(NULL, &objectclassvar_class); |
- VarObjectClass::InstanceData* instance_data = |
- static_cast<VarObjectClass::InstanceData*>(obj); |
- instance_data->object_class = object_class; |
- instance_data->native_data = native_data; |
- return ObjectVar::NPObjectToPPVar(object_class->module(), obj); |
-} |
- |
-} // namespace |
- |
-// VarObjectClass -------------------------------------------------------------- |
- |
-VarObjectClass::VarObjectClass(PluginModule* module, |
- PP_ClassDestructor destruct, |
- PP_ClassFunction invoke, |
- PP_ClassProperty* properties) |
- : Resource(module), |
- instance_native_destructor_(destruct), |
- instance_invoke_(invoke) { |
- PP_ClassProperty* prop = properties; |
- while (prop->name) { |
- properties_.insert(std::make_pair(std::string(prop->name), |
- Property(*prop))); |
- ++prop; |
- } |
-} |
- |
-// static |
-const PPB_Class* VarObjectClass::GetInterface() { |
- static PPB_Class interface = { |
- &Create, |
- &Instantiate |
- }; |
- return &interface; |
-} |
- |
-// virtual |
-VarObjectClass::~VarObjectClass() { } |
- |
-VarObjectClass* VarObjectClass::AsVarObjectClass() { |
- return this; |
-} |
- |
-} // namespace pepper |