diff options
author | Adam Domurad <[email protected]> | 2013-08-27 16:53:30 -0400 |
---|---|---|
committer | Adam Domurad <[email protected]> | 2013-08-27 16:53:30 -0400 |
commit | 86c0b6527f5737560419c4c61f30b05997565908 (patch) | |
tree | 7d288e6c7cb36cd9a8ba7132217ae28f75410572 /plugin/icedteanp/IcedTeaScriptablePluginObject.cc | |
parent | 6fbf033b59cff6cedf9d31411835ab01938e048e (diff) |
Do not wait for applet initialization when binding Java applets for NPAPI.
Diffstat (limited to 'plugin/icedteanp/IcedTeaScriptablePluginObject.cc')
-rw-r--r-- | plugin/icedteanp/IcedTeaScriptablePluginObject.cc | 208 |
1 files changed, 150 insertions, 58 deletions
diff --git a/plugin/icedteanp/IcedTeaScriptablePluginObject.cc b/plugin/icedteanp/IcedTeaScriptablePluginObject.cc index d54d94c..d78fb2d 100644 --- a/plugin/icedteanp/IcedTeaScriptablePluginObject.cc +++ b/plugin/icedteanp/IcedTeaScriptablePluginObject.cc @@ -306,24 +306,26 @@ IcedTeaScriptableJavaPackageObject::getProperty(NPObject *npobj, NPIdentifier na //NPIdentifier property = browser_functions.getstringidentifier(property_name.c_str()); - NPObject* obj; + NPObjectRef object; if (isPropertyClass) { PLUGIN_DEBUG("Returning package object\n"); - obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_package_object( + object = IcedTeaScriptableJavaPackageObject::get_scriptable_java_package_object( IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj), property_name.c_str()); } else { PLUGIN_DEBUG("Returning Java object\n"); - obj = IcedTeaScriptableJavaObject::get_scriptable_java_object( + object = IcedTeaScriptableJavaObject::get_scriptable_java_object( IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj), *(java_result->return_string), "0", false); } - OBJECT_TO_NPVARIANT(obj, *result); + OBJECT_TO_NPVARIANT(object.get(), *result); + /* Retain because we are returning an NPObject* */ + object.raw_retain(); return true; } @@ -384,32 +386,33 @@ scriptable_java_package_object_class() { return np_class; } -NPObject* -IcedTeaScriptableJavaObject::get_scriptable_java_object(NPP instance, - std::string class_id, - std::string instance_id, - bool isArray) +/* Creates a scriptable java object (intended to be called asynch.) */ +static void +create_scriptable_java_object_async(void* data) { - /* Shared NPClass instance for IcedTeaScriptablePluginObject */ - static NPClass np_class = scriptable_java_package_object_class(); + PLUGIN_DEBUG("Asynchronously creating object ...\n"); - std::string obj_key = class_id + ":" + instance_id; + std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters; + NPP instance = (NPP) parameters.at(0); + NPClass* np_class = (NPClass*) parameters.at(1); + NPObjectRef* object_ref = (NPObjectRef*) parameters.at(2); - PLUGIN_DEBUG("get_scriptable_java_object searching for %s...\n", obj_key.c_str()); - IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) IcedTeaPluginUtilities::getNPObjectFromJavaKey(obj_key); + *object_ref = browser_functions.createobject(instance, np_class); - if (scriptable_object != NULL) - { - PLUGIN_DEBUG("Returning existing object %p\n", scriptable_object); - browser_functions.retainobject(scriptable_object); - return scriptable_object; - } + ((AsyncCallThreadData*) data)->result_ready = true; +} + +static NPObjectRef +create_scriptable_java_object(NPP instance) +{ + /* Shared NPClass instance for IcedTeaScriptablePluginObject */ + static NPClass np_class = scriptable_java_package_object_class(); // try to create normally - scriptable_object = (IcedTeaScriptableJavaObject*)browser_functions.createobject(instance, &np_class); + NPObjectRef np_object = NPObjectRef::create(instance, &np_class); // didn't work? try creating asynch - if (!scriptable_object) + if (np_object.empty()) { AsyncCallThreadData thread_data = AsyncCallThreadData(); thread_data.result_ready = false; @@ -418,45 +421,104 @@ IcedTeaScriptableJavaObject::get_scriptable_java_object(NPP instance, thread_data.parameters.push_back(instance); thread_data.parameters.push_back(&np_class); - thread_data.parameters.push_back(&scriptable_object); + thread_data.parameters.push_back(&np_object); - IcedTeaPluginUtilities::callAndWaitForResult(instance, &_createAndRetainJavaObject, &thread_data); - } else + IcedTeaPluginUtilities::callAndWaitForResult(instance, &create_scriptable_java_object_async, &thread_data); + } + + return np_object; +} + +/* If we are uninitialized, make a Java request for the applet java class & instance ID for the plugin instance. + * Only objects representing an applet will begin uninitialized, to prevent blocking when the browser requests the object. + * Returns false on initialization error. */ +bool +IcedTeaScriptableJavaObject::tryToInitializeIfApplet() { + if (initialization_failed || initialized) { - // Else retain object and continue - browser_functions.retainobject(scriptable_object); + return !initialization_failed; } - PLUGIN_DEBUG("Constructed new Java Object with classid=%s, instanceid=%s, isArray=%d and scriptable_object=%p\n", class_id.c_str(), instance_id.c_str(), isArray, scriptable_object); + JavaRequestProcessor java_request; - scriptable_object->class_id = class_id; - scriptable_object->is_object_array = isArray; + std::string id = IcedTeaPluginUtilities::stringPrintf("%d", get_id_from_instance(instance)); + + /* Try to fetch the specific applet Java instance */ + JavaResultData* instance_result = java_request.getAppletObjectInstance(id); + if (instance_result->error_occurred) + { + printf("Error: Unable to fetch applet instance id from Java side.\n"); + initialization_failed = true; + return false; + } + this->instance_id = *instance_result->return_string; + + /* Try to fetch the applet Java class */ + JavaResultData* class_result = java_request.getClassID(id); + if (class_result->error_occurred) + { + printf("Error: Unable to fetch applet instance id from Java side.\n"); + initialization_failed = true; + return false; + } + this->class_id = *class_result->return_string; + + std::string obj_key = getClassID() + ":" + getInstanceID(); + IcedTeaPluginUtilities::storeObjectMapping(obj_key, this); - if (instance_id != "0") - scriptable_object->instance_id = instance_id; + printf("Object was initialized at '%s'.\n", obj_key.c_str()); - IcedTeaPluginUtilities::storeInstanceID(scriptable_object, instance); - IcedTeaPluginUtilities::storeObjectMapping(obj_key, scriptable_object); + initialized = true; - PLUGIN_DEBUG("Inserting into object_map key %s->%p\n", obj_key.c_str(), scriptable_object); - return scriptable_object; + return true; } -/* Creates and retains a scriptable java object (intended to be called asynch.) */ -void -_createAndRetainJavaObject(void* data) +NPObjectRef +IcedTeaScriptableJavaObject::get_scriptable_applet_object(NPP instance) { - PLUGIN_DEBUG("Asynchronously creating/retaining object ...\n"); + PLUGIN_DEBUG("get_scriptable_applet_object creating applet object for %p...\n", instance); - std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters; - NPP instance = (NPP) parameters.at(0); - NPClass* np_class = (NPClass*) parameters.at(1); - NPObject** scriptable_object = (NPObject**) parameters.at(2); + /* Do not mark as initialized, object will lookup class & instance IDs before use */ + NPObjectRef object = create_scriptable_java_object(instance); + IcedTeaPluginUtilities::storeInstanceID(object.get(), instance); + return object; +} + +NPObjectRef +IcedTeaScriptableJavaObject::get_scriptable_java_object(NPP instance, + std::string class_id, + std::string instance_id, + bool isArray) +{ + std::string obj_key = class_id + ":" + instance_id; + + PLUGIN_DEBUG("get_scriptable_java_object searching for %s...\n", obj_key.c_str()); + NPObjectRef object = IcedTeaPluginUtilities::getNPObjectFromJavaKey(obj_key); + + if (!object.empty()) + { + PLUGIN_DEBUG("Returning existing object %p\n", object.get()); + return object; + } - *scriptable_object = browser_functions.createobject(instance, np_class); - browser_functions.retainobject(*scriptable_object); + object = create_scriptable_java_object(instance); + PLUGIN_DEBUG("Constructed new Java Object with classid=%s, instanceid=%s, isArray=%d and scriptable_object=%p\n", class_id.c_str(), instance_id.c_str(), isArray, object.get()); - ((AsyncCallThreadData*) data)->result_ready = true; + IcedTeaScriptableJavaObject* scriptable_object = object.as<IcedTeaScriptableJavaObject*>(); + scriptable_object->class_id = class_id; + scriptable_object->is_object_array = isArray; + /* We know the class & instance already at this point, so we are initialized */ + scriptable_object->initialized = true; + + if (instance_id != "0") { + scriptable_object->instance_id = instance_id; + } + + IcedTeaPluginUtilities::storeInstanceID(object.get(), instance); + IcedTeaPluginUtilities::storeObjectMapping(obj_key, object.get()); + + PLUGIN_DEBUG("Inserting into object_map key %s->%p\n", obj_key.c_str(), object.get()); + return object; } bool @@ -467,8 +529,13 @@ IcedTeaScriptableJavaPackageObject::is_valid_java_object(NPObject* object_ptr) { bool IcedTeaScriptableJavaObject::hasMethod(NPObject *npobj, NPIdentifier name_id) { - std::string name = IcedTeaPluginUtilities::NPIdentifierAsString(name_id); IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) npobj; + /* If we are an applet object, we may not be initialized yet. */ + if (!scriptable_object->tryToInitializeIfApplet()) { + return false; + } + + std::string name = IcedTeaPluginUtilities::NPIdentifierAsString(name_id); PLUGIN_DEBUG("IcedTeaScriptableJavaObject::hasMethod %s (ival=%d)\n", name.c_str(), browser_functions.intfromidentifier(name_id)); bool hasMethod = false; @@ -496,6 +563,12 @@ bool IcedTeaScriptableJavaObject::invoke(NPObject *npobj, NPIdentifier name_id, const NPVariant *args, uint32_t argCount, NPVariant *result) { + IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) npobj; + /* If we are an applet object, we may not be initialized yet. */ + if (!scriptable_object->tryToInitializeIfApplet()) { + return false; + } + std::string name = IcedTeaPluginUtilities::NPIdentifierAsString(name_id); // Extract arg type array @@ -508,8 +581,6 @@ IcedTeaScriptableJavaObject::invoke(NPObject *npobj, NPIdentifier name_id, const JavaResultData* java_result; JavaRequestProcessor java_request = JavaRequestProcessor(); - IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*)npobj; - std::string instance_id = scriptable_object->instance_id; std::string class_id = scriptable_object->class_id; @@ -561,12 +632,17 @@ IcedTeaScriptableJavaObject::invoke(NPObject *npobj, NPIdentifier name_id, const bool IcedTeaScriptableJavaObject::hasProperty(NPObject *npobj, NPIdentifier name_id) { + IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) npobj; + /* If we are an applet object, we may not be initialized yet. */ + if (!scriptable_object->tryToInitializeIfApplet()) { + return false; + } + std::string name = IcedTeaPluginUtilities::NPIdentifierAsString(name_id); PLUGIN_DEBUG("IcedTeaScriptableJavaObject::hasProperty %s (ival=%d)\n", name.c_str(), browser_functions.intfromidentifier(name_id)); bool hasProperty = false; - IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*)npobj; // If it is an array, only length and indexes are valid if (scriptable_object->is_object_array) { @@ -599,6 +675,12 @@ IcedTeaScriptableJavaObject::hasProperty(NPObject *npobj, NPIdentifier name_id) bool IcedTeaScriptableJavaObject::getProperty(NPObject *npobj, NPIdentifier name_id, NPVariant *result) { + IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) npobj; + /* If we are an applet object, we may not be initialized yet. */ + if (!scriptable_object->tryToInitializeIfApplet()) { + return false; + } + std::string name = IcedTeaPluginUtilities::NPIdentifierAsString(name_id); bool is_string_id = browser_functions.identifierisstring(name_id); PLUGIN_DEBUG("IcedTeaScriptableJavaObject::getProperty %s (ival=%d)\n", name.c_str(), browser_functions.intfromidentifier(name_id)); @@ -606,13 +688,11 @@ IcedTeaScriptableJavaObject::getProperty(NPObject *npobj, NPIdentifier name_id, JavaResultData* java_result; JavaRequestProcessor java_request = JavaRequestProcessor(); - IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*)npobj; - std::string instance_id = scriptable_object->getInstanceID(); std::string class_id = scriptable_object->getClassID(); NPP instance = scriptable_object->instance; - if (instance_id.length() > 0) // Could be an array or a simple object + if (!instance_id.empty()) // Could be an array or a simple object { // If array and requesting length if ( scriptable_object->is_object_array && name == "length") @@ -683,13 +763,18 @@ IcedTeaScriptableJavaObject::getProperty(NPObject *npobj, NPIdentifier name_id, bool IcedTeaScriptableJavaObject::setProperty(NPObject *npobj, NPIdentifier name_id, const NPVariant *value) { + IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) npobj; + /* If we are an applet object, we may not be initialized yet. */ + if (!scriptable_object->tryToInitializeIfApplet()) { + return false; + } + std::string name = IcedTeaPluginUtilities::NPIdentifierAsString(name_id); PLUGIN_DEBUG("IcedTeaScriptableJavaObject::setProperty %s (ival=%d) to:\n", name.c_str(), browser_functions.intfromidentifier(name_id)); IcedTeaPluginUtilities::printNPVariant(*value); JavaResultData* java_result; JavaRequestProcessor java_request = JavaRequestProcessor(); - IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*)npobj; std::string instance_id = scriptable_object->getInstanceID(); std::string class_id = scriptable_object->getClassID(); @@ -763,7 +848,12 @@ bool IcedTeaScriptableJavaObject::construct(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) { - IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*)npobj; + IcedTeaScriptableJavaObject* scriptable_object = (IcedTeaScriptableJavaObject*) npobj; + /* If we are an applet object, we may not be initialized yet. */ + if (!scriptable_object->tryToInitializeIfApplet()) { + return false; + } + // Extract arg type array PLUGIN_DEBUG("IcedTeaScriptableJavaObject::construct %s. Args follow.\n", scriptable_object->getClassID().c_str()); for (int i=0; i < argCount; i++) @@ -814,11 +904,13 @@ IcedTeaScriptableJavaObject::construct(NPObject *npobj, const NPVariant *args, u std::string return_obj_instance_id = *java_result->return_string; std::string return_obj_class_id = scriptable_object->class_id; - NPObject* obj = IcedTeaScriptableJavaObject::get_scriptable_java_object( + NPObjectRef object = IcedTeaScriptableJavaObject::get_scriptable_java_object( IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj), return_obj_class_id, return_obj_instance_id, false); - OBJECT_TO_NPVARIANT(obj, *result); + OBJECT_TO_NPVARIANT(object.get(), *result); + /* Retain because we are returning an NPObject* */ + object.raw_retain(); PLUGIN_DEBUG("IcedTeaScriptableJavaObject::construct returning.\n"); return true; |