diff options
Diffstat (limited to 'plugin/icedteanp/IcedTeaPluginRequestProcessor.cc')
-rw-r--r-- | plugin/icedteanp/IcedTeaPluginRequestProcessor.cc | 988 |
1 files changed, 988 insertions, 0 deletions
diff --git a/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc b/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc new file mode 100644 index 0000000..373be59 --- /dev/null +++ b/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc @@ -0,0 +1,988 @@ +/* IcedTeaPluginRequestProcessor.cc + + Copyright (C) 2009, 2010 Red Hat + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +IcedTea is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include <typeinfo> + +#include "IcedTeaScriptablePluginObject.h" +#include "IcedTeaNPPlugin.h" +#include "IcedTeaPluginRequestProcessor.h" + +/* + * This class processes requests made by Java. The requests include pointer + * information, script execution and variable get/set + */ + +// Initialize static members used by the queue processing framework +pthread_mutex_t message_queue_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t syn_write_mutex = PTHREAD_MUTEX_INITIALIZER; +std::vector< std::vector<std::string*>* >* message_queue = new std::vector< std::vector<std::string*>* >(); + +/** + * PluginRequestProcessor constructor. + * + * Initializes various complex data structures used by the class. + */ + +PluginRequestProcessor::PluginRequestProcessor() +{ + this->pendingRequests = new std::map<pthread_t, uintmax_t>(); + + internal_req_ref_counter = 0; +} + +/** + * PluginRequestProcessor destructor. + * + * Frees memory used by complex objects. + */ + +PluginRequestProcessor::~PluginRequestProcessor() +{ + PLUGIN_DEBUG("PluginRequestProcessor::~PluginRequestProcessor\n"); + + if (pendingRequests) + delete pendingRequests; +} + +/** + * Processes plugin (C++ side) requests from the Java side, and internally. + * + * @param message The message request to process + * @return boolean indicating whether the message is serviceable by this object + */ + +bool +PluginRequestProcessor::newMessageOnBus(const char* message) +{ + PLUGIN_DEBUG("PluginRequestProcessor processing %s\n", message); + + std::string* type; + std::string* command; + int counter = 0; + + std::vector<std::string*>* message_parts = IcedTeaPluginUtilities::strSplit(message, " "); + + std::vector<std::string*>::iterator the_iterator; + the_iterator = message_parts->begin(); + + IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::newMessageOnBus:", message_parts); + + type = message_parts->at(0); + command = message_parts->at(4); + + if (!type->find("instance")) + { + if (!command->find("GetWindow")) + { + // Window can be queried from the main thread only. And this call + // returns immediately, so we do it in the same thread. + this->sendWindow(message_parts); + return true; + } else if (!command->find("GetMember") || + !command->find("SetMember") || + !command->find("ToString") || + !command->find("Call") || + !command->find("GetSlot") || + !command->find("SetSlot") || + !command->find("Eval") || + !command->find("Finalize")) + { + + // Update queue synchronously + pthread_mutex_lock(&message_queue_mutex); + message_queue->push_back(message_parts); + pthread_mutex_unlock(&message_queue_mutex); + + // Broadcast that a message is now available + pthread_cond_broadcast(&cond_message_available); + + return true; + } + + } + + IcedTeaPluginUtilities::freeStringPtrVector(message_parts); + + // If we got here, it means we couldn't process the message. Let the caller know. + return false; +} + +/** + * Sends the window pointer to the Java side. + * + * @param message_parts The request message. + */ + +void +PluginRequestProcessor::sendWindow(std::vector<std::string*>* message_parts) +{ + std::string* type; + std::string* command; + int reference; + std::string response = std::string(); + std::string window_ptr_str = std::string(); + NPVariant* variant = new NPVariant(); + static NPObject* window_ptr; + int id; + + type = message_parts->at(0); + id = atoi(message_parts->at(1)->c_str()); + reference = atoi(message_parts->at(3)->c_str()); + command = message_parts->at(4); + + NPP instance; + get_instance_from_id(id, instance); + + browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr); + PLUGIN_DEBUG("ID=%d, Instance=%p, WindowPTR = %p\n", id, instance, window_ptr); + + OBJECT_TO_NPVARIANT(window_ptr, *variant); + browser_functions.retainobject(window_ptr); + IcedTeaPluginUtilities::JSIDToString(variant, &window_ptr_str); + + // We need the context 0 for backwards compatibility with the Java side + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + response += " JavaScriptGetWindow "; + response += window_ptr_str; + + plugin_to_java_bus->post(response.c_str()); + + // store the instance pointer for future reference + IcedTeaPluginUtilities::storeInstanceID(variant, instance); +} + +/** + * Evaluates the given script + * + * @param message_parts The request message. + */ + +void +PluginRequestProcessor::eval(std::vector<std::string*>* message_parts) +{ + JavaRequestProcessor request_processor = JavaRequestProcessor(); + JavaResultData* java_result; + + NPVariant* window_ptr; + NPP instance; + std::string script; + NPVariant result; + int reference; + std::string response = std::string(); + std::string return_type = std::string(); + int id; + + reference = atoi(message_parts->at(3)->c_str()); + window_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(message_parts->at(5)); + instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr); + + java_result = request_processor.getString(*(message_parts->at(6))); + CHECK_JAVA_RESULT(java_result); + script.append(*(java_result->return_string)); + + AsyncCallThreadData thread_data = AsyncCallThreadData(); + thread_data.result_ready = false; + thread_data.parameters = std::vector<void*>(); + thread_data.result = std::string(); + + thread_data.parameters.push_back(instance); + thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*window_ptr)); + thread_data.parameters.push_back(&script); + +#ifdef CHROMIUM_WORKAROUND + // Workaround for chromium + _eval(&thread_data); + + if (!thread_data.call_successful) + { +#endif + thread_data.result_ready = false; + browser_functions.pluginthreadasynccall(instance, &_eval, &thread_data); + + while (!thread_data.result_ready) usleep(2000); // Wait till result is ready +#ifdef CHROMIUM_WORKAROUND + } +#endif + + NPVariant* result_variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(thread_data.result); + std::string result_variant_jniid = std::string(); + createJavaObjectFromVariant(instance, *result_variant, &result_variant_jniid); + + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + response += " JavaScriptEval "; + response += result_variant_jniid; + + plugin_to_java_bus->post(response.c_str()); +} + +/** + * Calls the given javascript script + * + * @param message_parts The request message. + */ + +void +PluginRequestProcessor::call(std::vector<std::string*>* message_parts) +{ + NPP instance; + std::string* window_ptr_str; + NPVariant* window_ptr; + int reference; + std::string window_function_name; + std::vector<NPVariant> args = std::vector<NPVariant>(); + std::vector<std::string> arg_ids = std::vector<std::string>(); + int arg_count; + std::string response = std::string(); + JavaRequestProcessor java_request = JavaRequestProcessor(); + JavaResultData* java_result; + + reference = atoi(message_parts->at(3)->c_str()); + + // window + window_ptr_str = message_parts->at(5); + window_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(window_ptr_str); + + // instance + instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr); + + // function name + java_result = java_request.getString(*(message_parts->at(6))); + CHECK_JAVA_RESULT(java_result); + window_function_name.append(*(java_result->return_string)); + + // arguments + for (int i=7; i < message_parts->size(); i++) + { + arg_ids.push_back(*(message_parts->at(i))); + } + + // determine arguments + for (int i=0; i < arg_ids.size(); i++) + { + NPVariant* variant = new NPVariant(); + java_result = java_request.getValue(arg_ids[i]); + CHECK_JAVA_RESULT(java_result); + + IcedTeaPluginUtilities::javaResultToNPVariant(instance, java_result->return_string, variant); + + args.push_back(*variant); + } + + arg_count = args.size(); + NPVariant *args_array = (NPVariant*) malloc(sizeof(NPVariant)*args.size()); + for (int i=0; i < args.size(); i++) + args_array[i] = args[i]; + + AsyncCallThreadData thread_data = AsyncCallThreadData(); + thread_data.result_ready = false; + thread_data.parameters = std::vector<void*>(); + thread_data.result = std::string(); + + thread_data.parameters.push_back(instance); + thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*window_ptr)); + thread_data.parameters.push_back(&window_function_name); + thread_data.parameters.push_back(&arg_count); + thread_data.parameters.push_back(args_array); + +#ifdef CHROMIUM_WORKAROUND + // Workaround for chromium + _call(&thread_data); + + if (!thread_data.call_successful) + { +#endif + thread_data.result_ready = false; + browser_functions.pluginthreadasynccall(instance, &_call, &thread_data); + + while (!thread_data.result_ready) usleep(2000); // wait till ready +#ifdef CHROMIUM_WORKAROUND + } +#endif + + NPVariant* result_variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(thread_data.result); + std::string result_variant_jniid = std::string(); + + if (result_variant) + { + createJavaObjectFromVariant(instance, *result_variant, &result_variant_jniid); + } else + { + result_variant_jniid = "0"; + } + + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + response += " JavaScriptCall "; + response += result_variant_jniid; + + plugin_to_java_bus->post(response.c_str()); + + cleanup: + free(args_array); +} + +/** + * Sends the string value of the requested variable + * + * @param message_parts The request message. + */ +void +PluginRequestProcessor::sendString(std::vector<std::string*>* message_parts) +{ + std::string variant_ptr; + NPVariant* variant; + JavaRequestProcessor java_request = JavaRequestProcessor(); + JavaResultData* java_result; + int reference; + std::string response = std::string(); + + reference = atoi(message_parts->at(3)->c_str()); + variant_ptr = *(message_parts->at(5)); + + variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr); + AsyncCallThreadData thread_data = AsyncCallThreadData(); + thread_data.result_ready = false; + thread_data.parameters = std::vector<void*>(); + thread_data.result = std::string(); + + NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(variant); + thread_data.parameters.push_back(instance); + thread_data.parameters.push_back(variant); + +#ifdef CHROMIUM_WORKAROUND + // Workaround for chromium + _getString(&thread_data); + + if (!thread_data.call_successful) + { +#endif + thread_data.result_ready = false; + browser_functions.pluginthreadasynccall(instance, &_getString, &thread_data); + while (!thread_data.result_ready) usleep(2000); // wait till ready +#ifdef CHROMIUM_WORKAROUND + } +#endif + + // We need the context 0 for backwards compatibility with the Java side + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + response += " JavaScriptToString "; + response += thread_data.result; + + plugin_to_java_bus->post(response.c_str()); + + cleanup: + + pthread_mutex_lock(&tc_mutex); + thread_count--; + pthread_mutex_unlock(&tc_mutex); +} + +/** + * Sets variable to given value + * + * @param message_parts The request message. + */ + +void +PluginRequestProcessor::setMember(std::vector<std::string*>* message_parts) +{ + std::string propertyNameID; + std::string value = std::string(); + std::string response = std::string(); + int reference; + + NPP instance; + NPVariant* member; + NPIdentifier property_identifier; + + JavaRequestProcessor java_request = JavaRequestProcessor(); + JavaResultData* java_result; + + IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::_setMember - ", message_parts); + + reference = atoi(message_parts->at(3)->c_str()); + + member = (NPVariant*) (IcedTeaPluginUtilities::stringToJSID(*(message_parts->at(5)))); + propertyNameID = *(message_parts->at(6)); + + if (*(message_parts->at(7)) == "literalreturn") + { + value.append(*(message_parts->at(7))); + value.append(" "); + value.append(*(message_parts->at(8))); + } else + { + value.append(*(message_parts->at(7))); + } + + instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(member); + + if (*(message_parts->at(4)) == "SetSlot") + { + property_identifier = browser_functions.getintidentifier(atoi(message_parts->at(6)->c_str())); + } else + { + java_result = java_request.getString(propertyNameID); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occurred) + { + printf("Unable to get member name for setMember. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } + + property_identifier = browser_functions.getstringidentifier(java_result->return_string->c_str()); + } + + AsyncCallThreadData thread_data = AsyncCallThreadData(); + thread_data.result_ready = false; + thread_data.parameters = std::vector<void*>(); + thread_data.result = std::string(); + + thread_data.parameters.push_back(instance); + thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*member)); + thread_data.parameters.push_back(&property_identifier); + thread_data.parameters.push_back(&value); + +#ifdef CHROMIUM_WORKAROUND + // Workaround for chromium + _setMember(&thread_data); + + if (!thread_data.call_successful) + { +#endif + thread_data.result_ready = false; + browser_functions.pluginthreadasynccall(instance, &_setMember, &thread_data); + + while (!thread_data.result_ready) usleep(2000); // wait till ready +#ifdef CHROMIUM_WORKAROUND + } +#endif + + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + response.append(" JavaScriptSetMember "); + plugin_to_java_bus->post(response.c_str()); + + cleanup: + + // property_name, type and value are deleted by _setMember + pthread_mutex_lock(&tc_mutex); + thread_count--; + pthread_mutex_unlock(&tc_mutex); +} + +/** + * Sends request member pointer to the Java side. + * + * This is a static function, called in another thread. Since certain data + * can only be requested from the main thread in Mozilla, this function + * does whatever it can seperately, and then makes an internal request that + * causes _sendMember to do the rest of the work. + * + * @param message_parts The request message + */ + +void +PluginRequestProcessor::sendMember(std::vector<std::string*>* message_parts) +{ + // member initialization + std::vector<std::string> args; + JavaRequestProcessor java_request = JavaRequestProcessor(); + JavaResultData* java_result; + NPVariant* parent_ptr; + + //int reference; + std::string member_id = std::string(); + std::string jsObjectClassID = std::string(); + std::string jsObjectConstructorID = std::string(); + std::string response = std::string(); + + NPIdentifier member_identifier; + + int method_id; + int instance_id; + int reference; + + // debug printout of parent thread data + IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::getMember:", message_parts); + + reference = atoi(message_parts->at(3)->c_str()); + + // store info in local variables for easy access + instance_id = atoi(message_parts->at(1)->c_str()); + parent_ptr = (NPVariant*) (IcedTeaPluginUtilities::stringToJSID(message_parts->at(5))); + member_id.append(*(message_parts->at(6))); + + /** Request data from Java if necessary **/ + if (*(message_parts->at(4)) == "GetSlot") + { + member_identifier = browser_functions.getintidentifier(atoi(member_id.c_str())); + } else + { + // make a new request for getString, to get the name of the identifier + java_result = java_request.getString(member_id); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occurred) + { + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } + + member_identifier = browser_functions.getstringidentifier(java_result->return_string->c_str()); + } + + AsyncCallThreadData thread_data = AsyncCallThreadData(); + thread_data.result_ready = false; + thread_data.parameters = std::vector<void*>(); + thread_data.result = std::string(); + + NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(parent_ptr); + thread_data.parameters.push_back(instance); + thread_data.parameters.push_back(NPVARIANT_TO_OBJECT(*parent_ptr)); + thread_data.parameters.push_back(&member_identifier); + +#ifdef CHROMIUM_WORKAROUND + // Workaround for chromium + _getMember(&thread_data); + + if (!thread_data.call_successful) + { +#endif + thread_data.result_ready = false; + browser_functions.pluginthreadasynccall(instance, &_getMember, &thread_data); + + while (!thread_data.result_ready) usleep(2000); // wait till ready + +#ifdef CHROMIUM_WORKAROUND + } +#endif + + PLUGIN_DEBUG("Member PTR after internal request: %s\n", thread_data.result.c_str()); + + java_result = java_request.findClass(0, "netscape.javascript.JSObject"); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occurred) + { + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } + + jsObjectClassID.append(*(java_result->return_string)); + + args = std::vector<std::string>(); + std::string longArg = "J"; + args.push_back(longArg); + + java_result = java_request.getMethodID(jsObjectClassID, + browser_functions.getstringidentifier("<init>"), + args); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occurred) + { + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } + + jsObjectConstructorID.append(*(java_result->return_string)); + + // We have the method id. Now create a new object. + + args.clear(); + args.push_back(thread_data.result); + java_result = java_request.newObjectWithConstructor("", + jsObjectClassID, + jsObjectConstructorID, + args); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occurred) + { + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } + + + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + if (*(message_parts->at(2)) == "GetSlot") + { + response.append(" JavaScriptGetMember "); + } else { + response.append(" JavaScriptGetSlot "); + } + response.append(java_result->return_string->c_str()); + plugin_to_java_bus->post(response.c_str()); + + + // Now be a good citizen and help keep the heap free of garbage + cleanup: + + pthread_mutex_lock(&tc_mutex); + thread_count--; + pthread_mutex_unlock(&tc_mutex); +} + +/** + * Decrements reference count to given object + * + * @param message_parts The request message. + */ + +void +PluginRequestProcessor::finalize(std::vector<std::string*>* message_parts) +{ + std::string* type; + std::string* command; + int reference; + std::string response = std::string(); + std::string* variant_ptr_str; + NPVariant* variant_ptr; + NPObject* window_ptr; + int id; + + type = message_parts->at(0); + id = atoi(message_parts->at(1)->c_str()); + reference = atoi(message_parts->at(3)->c_str()); + variant_ptr_str = message_parts->at(5); + + NPP instance; + get_instance_from_id(id, instance); + + variant_ptr = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr_str); + window_ptr = NPVARIANT_TO_OBJECT(*variant_ptr); + browser_functions.releaseobject(window_ptr); + + // remove reference + IcedTeaPluginUtilities::removeInstanceID(variant_ptr); + + // clear memory + free(variant_ptr); + + // We need the context 0 for backwards compatibility with the Java side + IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &response); + response += " JavaScriptFinalize"; + + plugin_to_java_bus->post(response.c_str()); +} + + +void* +queue_processor(void* data) +{ + + PluginRequestProcessor* processor = (PluginRequestProcessor*) data; + std::vector<std::string*>* message_parts = NULL; + std::string command; + pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER; // This is needed for API compat. and is unused + + PLUGIN_DEBUG("Queue processor initialized. Queue = %p\n", message_queue); + + while (true) + { + pthread_mutex_lock(&message_queue_mutex); + if (message_queue->size() > 0) + { + message_parts = message_queue->front(); + message_queue->erase(message_queue->begin()); + } + pthread_mutex_unlock(&message_queue_mutex); + + if (message_parts) + { + command = *(message_parts->at(4)); + + if (command == "GetMember") + { + processor->sendMember(message_parts); + } else if (command == "ToString") + { + processor->sendString(message_parts); + } else if (command == "SetMember") + { + // write methods are synchronized + pthread_mutex_lock(&syn_write_mutex); + processor->setMember(message_parts); + pthread_mutex_unlock(&syn_write_mutex); + } else if (command == "Call") + { + // write methods are synchronized + pthread_mutex_lock(&syn_write_mutex); + processor->call(message_parts); + pthread_mutex_unlock(&syn_write_mutex); + } else if (command == "Eval") + { + // write methods are synchronized + pthread_mutex_lock(&syn_write_mutex); + processor->eval(message_parts); + pthread_mutex_unlock(&syn_write_mutex); + } else if (command == "GetSlot") + { + // write methods are synchronized + pthread_mutex_lock(&syn_write_mutex); + processor->sendMember(message_parts); + pthread_mutex_unlock(&syn_write_mutex); + } else if (command == "SetSlot") + { + // write methods are synchronized + pthread_mutex_lock(&syn_write_mutex); + processor->setMember(message_parts); + pthread_mutex_unlock(&syn_write_mutex); + } else if (command == "Finalize") + { + // write methods are synchronized + pthread_mutex_lock(&syn_write_mutex); + processor->finalize(message_parts); + pthread_mutex_unlock(&syn_write_mutex); + } else + { + // Nothing matched + IcedTeaPluginUtilities::printStringPtrVector("Error: Unable to process message: ", message_parts); + } + + // Free memory for message_parts + IcedTeaPluginUtilities::freeStringPtrVector(message_parts); + + } else + { + pthread_cond_wait(&cond_message_available, &wait_mutex); + pthread_testcancel(); + } + + message_parts = NULL; + } + + PLUGIN_DEBUG("Queue processing stopped.\n"); +} + +/****************************************** + * Functions delegated to the main thread * + ******************************************/ + +void +_setMember(void* data) +{ + std::string* value; + + NPP instance; + NPVariant value_variant = NPVariant(); + NPObject* member; + NPIdentifier* property; + + std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters; + instance = (NPP) parameters.at(0); + member = (NPObject*) parameters.at(1); + property = (NPIdentifier*) parameters.at(2); + value = (std::string*) parameters.at(3); + + PLUGIN_DEBUG("Setting %s on instance %p, object %p to value %s\n", browser_functions.utf8fromidentifier(*property), instance, member, value->c_str()); + + IcedTeaPluginUtilities::javaResultToNPVariant(instance, value, &value_variant); + + ((AsyncCallThreadData*) data)->call_successful = browser_functions.setproperty(instance, member, *property, &value_variant); + + ((AsyncCallThreadData*) data)->result_ready = true; +} + +void +_getMember(void* data) +{ + NPObject* parent_ptr; + NPVariant* member_ptr = new NPVariant(); + std::string member_ptr_str = std::string(); + NPP instance; + + std::vector<void*> parameters = ((AsyncCallThreadData*) data)->parameters; + + instance = (NPP) parameters.at(0); + parent_ptr = (NPObject*) parameters.at(1); + NPIdentifier* member_identifier = (NPIdentifier*) parameters.at(2); + + // Get the NPVariant corresponding to this member + PLUGIN_DEBUG("Looking for %p %p %p (%s)\n", instance, parent_ptr, member_identifier, browser_functions.utf8fromidentifier(*member_identifier)); + + if (!browser_functions.hasproperty(instance, parent_ptr, *member_identifier)) + { + printf("%s not found!\n", browser_functions.utf8fromidentifier(*member_identifier)); + } + ((AsyncCallThreadData*) data)->call_successful = browser_functions.getproperty(instance, parent_ptr, *member_identifier, member_ptr); + + IcedTeaPluginUtilities::printNPVariant(*member_ptr); + + if (((AsyncCallThreadData*) data)->call_successful) + { + IcedTeaPluginUtilities::JSIDToString(member_ptr, &member_ptr_str); + ((AsyncCallThreadData*) data)->result.append(member_ptr_str); + } + ((AsyncCallThreadData*) data)->result_ready = true; + + // store member -> instance link + IcedTeaPluginUtilities::storeInstanceID(member_ptr, instance); + + PLUGIN_DEBUG("_getMember returning.\n"); +} + +void +_eval(void* data) +{ + NPP instance; + NPObject* window_ptr; + std::string* script_str; + NPIdentifier script_identifier; + NPString script = NPString(); + NPVariant* eval_result = new NPVariant(); + std::string eval_result_ptr_str = std::string(); + + PLUGIN_DEBUG("_eval called\n"); + + std::vector<void*>* call_data = (std::vector<void*>*) data; + + instance = (NPP) call_data->at(0); + window_ptr = (NPObject*) call_data->at(1); + script_str = (std::string*) call_data->at(2); + +#if MOZILLA_VERSION_COLLAPSED < 1090200 + script.utf8characters = script_str->c_str(); + script.utf8length = script_str->size(); + + PLUGIN_DEBUG("Evaluating: %s\n", script.utf8characters); +#else + script.UTF8Characters = script_str->c_str(); + script.UTF8Length = script_str->size(); + + PLUGIN_DEBUG("Evaluating: %s\n", script.UTF8Characters); +#endif + + ((AsyncCallThreadData*) data)->call_successful = browser_functions.evaluate(instance, window_ptr, &script, eval_result); + IcedTeaPluginUtilities::printNPVariant(*eval_result); + + if (((AsyncCallThreadData*) data)->call_successful) + { + IcedTeaPluginUtilities::JSIDToString(eval_result, &eval_result_ptr_str); + ((AsyncCallThreadData*) data)->result.append(eval_result_ptr_str); + } + ((AsyncCallThreadData*) data)->result_ready = true; + + PLUGIN_DEBUG("_eval returning\n"); +} + + +void +_call(void* data) +{ + NPP instance; + NPObject* window_ptr; + std::string* function_name; + NPIdentifier function; + int* arg_count; + NPVariant* args; + NPVariant* call_result = new NPVariant(); + std::string call_result_ptr_str = std::string(); + + PLUGIN_DEBUG("_call called\n"); + + std::vector<void*>* call_data = (std::vector<void*>*) data; + + instance = (NPP) call_data->at(0); + window_ptr = (NPObject*) call_data->at(1); + function_name = (std::string*) call_data->at(2); + + function = browser_functions.getstringidentifier(function_name->c_str()); + arg_count = (int*) call_data->at(3); + args = (NPVariant*) call_data->at(4); + + for (int i=0; i < *arg_count; i++) { + IcedTeaPluginUtilities::printNPVariant(args[i]); + } + + PLUGIN_DEBUG("_calling\n"); + ((AsyncCallThreadData*) data)->call_successful = browser_functions.invoke(instance, window_ptr, function, args, *arg_count, call_result); + PLUGIN_DEBUG("_called\n"); + + IcedTeaPluginUtilities::printNPVariant(*call_result); + + if (((AsyncCallThreadData*) data)->call_successful) + { + IcedTeaPluginUtilities::JSIDToString(call_result, &call_result_ptr_str); + ((AsyncCallThreadData*) data)->result.append(call_result_ptr_str); + } + + ((AsyncCallThreadData*) data)->result_ready = true; + + PLUGIN_DEBUG("_call returning\n"); +} + +void +_getString(void* data) +{ + NPP instance; + NPObject* object; + NPIdentifier toString = browser_functions.getstringidentifier("toString"); + NPVariant tostring_result; + std::string result = std::string(); + + std::vector<void*>* call_data = (std::vector<void*>*) data; + instance = (NPP) call_data->at(0); + NPVariant* variant = (NPVariant*) call_data->at(1); + + PLUGIN_DEBUG("_getString called with %p and %p\n", instance, variant); + + if (NPVARIANT_IS_OBJECT(*variant)) + { + ((AsyncCallThreadData*) data)->call_successful = browser_functions.invoke(instance, NPVARIANT_TO_OBJECT(*variant), toString, NULL, 0, &tostring_result); + } + else + { + IcedTeaPluginUtilities::NPVariantToString(*variant, &result); + tostring_result = NPVariant(); + STRINGZ_TO_NPVARIANT(result.c_str(), tostring_result); + ((AsyncCallThreadData*) data)->call_successful = true; + } + + PLUGIN_DEBUG("ToString result: "); + IcedTeaPluginUtilities::printNPVariant(tostring_result); + + if (((AsyncCallThreadData*) data)->call_successful) + { + createJavaObjectFromVariant(instance, tostring_result, &(((AsyncCallThreadData*) data)->result)); + } + ((AsyncCallThreadData*) data)->result_ready = true; + + PLUGIN_DEBUG("_getString returning\n"); +} + |