/* 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 #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* >* message_queue = new std::vector< std::vector* >(); /** * PluginRequestProcessor constructor. * * Initializes various complex data structures used by the class. */ PluginRequestProcessor::PluginRequestProcessor() { this->pendingRequests = new std::map(); internal_req_ref_counter = 0; pthread_mutex_init(&message_queue_mutex, NULL); pthread_mutex_init(&syn_write_mutex, NULL); pthread_mutex_init(&tc_mutex, NULL); pthread_cond_init(&cond_message_available, NULL); } /** * PluginRequestProcessor destructor. * * Frees memory used by complex objects. */ PluginRequestProcessor::~PluginRequestProcessor() { PLUGIN_DEBUG("PluginRequestProcessor::~PluginRequestProcessor\n"); if (pendingRequests) delete pendingRequests; pthread_mutex_destroy(&message_queue_mutex); pthread_mutex_destroy(&syn_write_mutex); pthread_mutex_destroy(&tc_mutex); pthread_cond_destroy(&cond_message_available); } /** * 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* message_parts = IcedTeaPluginUtilities::strSplit(message, " "); std::vector::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* 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* 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(); 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* message_parts) { NPP instance; std::string* window_ptr_str; NPVariant* window_ptr; int reference; std::string window_function_name; std::vector args = std::vector(); std::vector arg_ids = std::vector(); 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(); 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* 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(); 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* 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->c_str()); //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(); 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* message_parts) { // member initialization std::vector 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->c_str()); //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(); 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->c_str()); //goto cleanup; } jsObjectClassID.append(*(java_result->return_string)); args = std::vector(); std::string longArg = "J"; args.push_back(longArg); java_result = java_request.getMethodID(jsObjectClassID, browser_functions.getstringidentifier(""), 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->c_str()); //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->c_str()); //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* 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()); } static void queue_cleanup(void* data) { pthread_mutex_destroy((pthread_mutex_t*) data); PLUGIN_DEBUG("Queue processing stopped.\n"); } void* queue_processor(void* data) { PluginRequestProcessor* processor = (PluginRequestProcessor*) data; std::vector* message_parts = NULL; std::string command; pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER; PLUGIN_DEBUG("Queue processor initialized. Queue = %p\n", message_queue); pthread_mutex_init(&wait_mutex, NULL); pthread_cleanup_push(queue_cleanup, (void*) &wait_mutex); 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_mutex_lock(&wait_mutex); pthread_cond_wait(&cond_message_available, &wait_mutex); pthread_mutex_unlock(&wait_mutex); } message_parts = NULL; pthread_testcancel(); } pthread_cleanup_pop(1); } /****************************************** * 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 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 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* call_data = (std::vector*) 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* call_data = (std::vector*) 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* call_data = (std::vector*) 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"); }