Mercurial > hg > release > icedtea6-1.6
changeset 1643:4ec5e065fb53
- Added support for FindClass, GetClassName, GetMethodID, GetToStringValue,
NewObject and NewStringUTF.
- Split the request wait code in Java processor into a generic function.
- Centralized all debug output calls.
- ICEDTEAPLUGIN_DEBUG flag now supported.
- Dynamic cookie fetching support ported over from current plugin.
- Added support for modifying JS objects via SetMember calls.
- Message processing model made more robust by using dedicated processing
threads, rather than dynamically initialized threads.
With this commit,
http://www.apl.jhu.edu/~hall/CWP-Sources/CWP-Examples/Chapter19/Everest.html
now works.
author | Deepak Bhole <dbhole@redhat.com> |
---|---|
date | Thu, 23 Jul 2009 11:39:18 -0400 |
parents | d20bab985f89 |
children | 090e738a38e7 |
files | ChangeLog plugin/icedteanp/IcedTeaJavaRequestProcessor.cc plugin/icedteanp/IcedTeaJavaRequestProcessor.h plugin/icedteanp/IcedTeaNPPlugin.cc plugin/icedteanp/IcedTeaNPPlugin.h plugin/icedteanp/IcedTeaPluginRequestProcessor.cc plugin/icedteanp/IcedTeaPluginRequestProcessor.h plugin/icedteanp/IcedTeaPluginUtils.cc plugin/icedteanp/IcedTeaPluginUtils.h plugin/icedteanp/IcedTeaRunnable.cc plugin/icedteanp/IcedTeaRunnable.h plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java |
diffstat | 12 files changed, 1505 insertions(+), 480 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Fri Jul 17 06:04:59 2009 -0400 +++ b/ChangeLog Thu Jul 23 11:39:18 2009 -0400 @@ -1,3 +1,26 @@ +2009-07-23 Deepak Bhole <dbhole@redhat.com> + + * plugin/icedteanp/IcedTeaJavaRequestProcessor.c: Added support for + FindClass, GetClassName, GetMethodID, GetToStringValue, NewObject and + NewStringUTF. Split the request wait code into a generic function. + * plugin/icedteanp/IcedTeaNPPlugin.cc: Centralize debug output calls. Obey + the ICEDTEAPLUGIN_DEBUG flag. Support dynamic cookie fetching. + * plugin/icedteanp/IcedTeaPluginRequestProcessor.c: Update multi-threaded + processing model. Support SetMember. Set up a dedicated message queue + processor (arbitrarily scalable). + * plugin/icedteanp/IcedTeaPluginRequestProcessor.h: Add function and + variable declerations as needed by the .cc file. + * plugin/icedteanp/IcedTeaPluginUtils.cc: Use only long and long long for + memory address translation. Add additional utility methods. + * plugin/icedteanp/IcedTeaPluginUtils.h: Update as needed by the .cc file. + * plugin/icedteanp/IcedTeaRunnable.h: New file. Represents a dispatchable + event, extends nsIRunnable. + * plugin/icedteanp/IcedTeaRunnable.h: New file. Header for + IcedTeaRunnable.cc. + * plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java: Fix + signature handling to remove the need for return type. Add support for + GetToStringValue and GetClassName. + 2009-07-17 Gary Benson <gbenson@redhat.com> * ports/hotspot/src/share/vm/shark/sharkBuilder.hpp
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc Thu Jul 23 11:39:18 2009 -0400 @@ -67,7 +67,8 @@ // Gather the results // GetStringUTFChars - if (message_parts->at(4) == "GetStringUTFChars") + if (message_parts->at(4) == "GetStringUTFChars" || + message_parts->at(4) == "GetToStringValue") { // first item is length, and it is radix 10 int length = strtol(message_parts->at(5).c_str(), NULL, 10); @@ -82,6 +83,31 @@ IcedTeaPluginUtilities::getUTF16LEString(length, 6 /* start at */, message_parts, result->return_wstring); result_ready = true; + } else if (message_parts->at(4) == "FindClass") + { + result->return_identifier = atoi(message_parts->at(5).c_str()); + result->return_string->append(message_parts->at(5)); // store it as a string as well, for easy access + result_ready = true; + } else if (message_parts->at(4) == "GetClassName") + { + result->return_identifier = atoi(message_parts->at(5).c_str()); + result->return_string->append(message_parts->at(5)); // store it as a string as well, for easy access + result_ready = true; + } else if (message_parts->at(4) == "GetMethodID") + { + result->return_identifier = atoi(message_parts->at(5).c_str()); + result->return_string->append(message_parts->at(5)); // store it as a string as well, for easy access + result_ready = true; + } else if (message_parts->at(4) == "NewObject") + { + result->return_identifier = atoi(message_parts->at(5).c_str()); + result->return_string->append(message_parts->at(5)); // store it as a string as well, for easy access + result_ready = true; + } else if (message_parts->at(4) == "NewStringUTF") + { + result->return_identifier = atoi(message_parts->at(5).c_str()); + result->return_string->append(message_parts->at(5)); // store it as a string as well, for easy access + result_ready = true; } delete message_parts; @@ -119,6 +145,8 @@ JavaRequestProcessor::~JavaRequestProcessor() { + PLUGIN_DEBUG_0ARG("JavaRequestProcessor::~JavaRequestProcessor\n"); + if (result) { if (result->error_msg) @@ -134,32 +162,12 @@ } } -/** - * Given a string id, fetches the actual string from Java side - * - * @param request_data The JavaRequest struct containing request relevant information - * @return A JavaResultData struct containing the result of the request - */ - -JavaResultData* -JavaRequestProcessor::getString(JavaRequest* request_data) +void +JavaRequestProcessor::postAndWaitForResponse(std::string* message) { - std::string string_id; - std::string* message; - - this->instance = 0; // context is always 0 (needed for java-side backwards compat.) - this->reference = IcedTeaPluginUtilities::getReference(); - - string_id = request_data->data->at(0); - - message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); - - message->append(" GetStringUTFChars "); // get it in UTF8 - message->append(string_id); - struct timespec t; clock_gettime(CLOCK_REALTIME, &t); - t.tv_sec += 60; // 1 minute timeout + t.tv_sec += REQUESTTIMEOUT; // 1 minute timeout result_ready = false; java_to_plugin_bus->subscribe(this); @@ -174,7 +182,7 @@ bool timedout = false; if (!result_ready && (curr_t.tv_sec < t.tv_sec)) - sleep(1); + usleep(2000); else break; @@ -187,9 +195,195 @@ } java_to_plugin_bus->unSubscribe(this); +} + +/** + * Given an object id, fetches the toString() value from Java + * + * @param object_id The ID of the object + * @return A JavaResultData struct containing the result of the request + */ + +JavaResultData* +JavaRequestProcessor::getToStringValue(std::string object_id) +{ + std::string* message; + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + + message->append(" GetToStringValue "); // get it in UTF8 + message->append(object_id); + + postAndWaitForResponse(message); + IcedTeaPluginUtilities::releaseReference(); + delete message; + + return result; +} + +/** + * Given a string id, fetches the actual string from Java side + * + * @param string_id The ID of the string + * @return A JavaResultData struct containing the result of the request + */ + +JavaResultData* +JavaRequestProcessor::getString(std::string string_id) +{ + std::string* message; + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + + message->append(" GetStringUTFChars "); // get it in UTF8 + message->append(string_id); + + postAndWaitForResponse(message); + + IcedTeaPluginUtilities::releaseReference(); + delete message; + + return result; +} + +JavaResultData* +JavaRequestProcessor::findClass(std::string name) +{ + std::string* message; + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + + message->append(" FindClass "); + message->append(name); + + postAndWaitForResponse(message); delete message; return result; } + +JavaResultData* +JavaRequestProcessor::getClassName(std::string ID) +{ + std::string* message; + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + + message->append(" GetClassName "); + message->append(ID); + + postAndWaitForResponse(message); + + delete message; + + return result; +} + +JavaResultData* +JavaRequestProcessor::getMethodID(std::string objectID, NPIdentifier methodName, + std::vector<std::string> args) +{ + JavaRequestProcessor* java_request; + std::string* message; + std::string* signature; + + signature = new std::string(); + *signature += "("; + + // FIXME: Need to determine how to extract array types and complex java objects + for (int i=0; i < args.size(); i++) + { + *signature += args[i]; + } + + *signature += ")"; + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + *message += " GetMethodID "; + *message += objectID; + *message += " "; + *message += browser_functions.utf8fromidentifier(methodName); + *message += " "; + *message += *signature; + + postAndWaitForResponse(message); + + IcedTeaPluginUtilities::releaseReference(); + delete signature; + delete message; + + return result; +} + +JavaResultData* +JavaRequestProcessor::newObject(std::string objectID, std::string methodID, + std::vector<std::string> args) +{ + JavaRequestProcessor* java_request; + std::string* message; + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + *message += " NewObject "; + *message += objectID; + *message += " "; + *message += methodID; + *message += " "; + + for (int i=0; i < args.size(); i++) + { + *message += args[i]; + *message += " "; + } + + postAndWaitForResponse(message); + + IcedTeaPluginUtilities::releaseReference(); + delete message; + + return result; +} + +JavaResultData* +JavaRequestProcessor::newString(std::string str) +{ + JavaRequestProcessor* java_request; + std::string* utf_string = new std::string(); + std::string* message; + + IcedTeaPluginUtilities::convertStringToUTF8(&str, utf_string); + + this->instance = 0; // context is always 0 (needed for java-side backwards compat.) + this->reference = IcedTeaPluginUtilities::getReference(); + + message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference); + message->append(" NewStringUTF "); + message->append(*utf_string); + + postAndWaitForResponse(message); + + IcedTeaPluginUtilities::releaseReference(); + delete utf_string; + delete message; + + return result; +}
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.h Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.h Thu Jul 23 11:39:18 2009 -0400 @@ -46,6 +46,8 @@ #include "IcedTeaNPPlugin.h" #include "IcedTeaPluginUtils.h" +#define REQUESTTIMEOUT 60 + /* * This struct holds data specific to a Java operation requested by the plugin */ @@ -97,11 +99,41 @@ bool result_ready; JavaResultData* result; + /* Post message on bus and wait */ + void postAndWaitForResponse(std::string* message); + public: JavaRequestProcessor(); ~JavaRequestProcessor(); virtual bool newMessageOnBus(const char* message); - JavaResultData* getString(JavaRequest* request_data); + + /* Returns the toString() value, given an object identifier */ + JavaResultData* getToStringValue(std::string object_id); + + /* Returns the string, given the identifier */ + JavaResultData* getString(std::string string_id); + + /* Returns the method ID from Java side */ + JavaResultData* getMethodID1(NPObject* obj, NPIdentifier methodName, + std::vector<NPVariant> args); + + /* Returns the method id */ + JavaResultData* getMethodID(std::string objectID, NPIdentifier methodName, + std::vector<std::string> args); + + /* Creates a new object */ + JavaResultData* newObject(std::string objectID, std::string methodID, + std::vector<std::string> args); + + /* Returns the class ID */ + JavaResultData* findClass(std::string name); + + /* Returns the type class name */ + JavaResultData* getClassName(std::string ID); + + /* Creates a new string in the Java store */ + JavaResultData* newString(std::string str); + }; #endif /* ICEDTEAJAVAREQUESTPROCESSOR_H_ */
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaNPPlugin.cc Thu Jul 23 11:39:18 2009 -0400 @@ -71,14 +71,6 @@ #include "IcedTeaScriptablePluginObject.h" #include "IcedTeaNPPlugin.h" -// Debugging macros. -#define PLUGIN_DEBUG(message) \ - g_print ("GCJ PLUGIN: thread %p: %s\n", g_thread_self (), message) - -#define PLUGIN_DEBUG_TWO(first, second) \ - g_print ("GCJ PLUGIN: thread %p: %s %s\n", g_thread_self (), \ - first, second) - // Error reporting macros. #define PLUGIN_ERROR(message) \ g_printerr ("%s:%d: thread %p: Error: %s\n", __FILE__, __LINE__, \ @@ -180,7 +172,7 @@ // Various message buses carrying information to/from Java, and internally MessageBus* plugin_to_java_bus = new MessageBus(); MessageBus* java_to_plugin_bus = new MessageBus(); -MessageBus* internal_bus = new MessageBus(); +//MessageBus* internal_bus = new MessageBus(); // Processor for plugin requests PluginRequestProcessor* plugin_req_proc = new PluginRequestProcessor(); @@ -265,6 +257,8 @@ static GPid appletviewer_pid = -1; static guint appletviewer_watch_id = -1; +int plugin_debug = getenv ("ICEDTEAPLUGIN_DEBUG") != NULL; + // Functions prefixed by GCJ_ are instance functions. They are called // by the browser and operate on instances of GCJPluginData. // Functions prefixed by plugin_ are static helper functions. @@ -289,7 +283,22 @@ int16 argc, char* argn[], char* argv[], NPSavedData* saved) { - PLUGIN_DEBUG ("GCJ_New"); + PLUGIN_DEBUG_0ARG("GCJ_New\n"); + + static NPObject *window_ptr; + NPIdentifier identifier; + NPVariant member_ptr; + browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr); + identifier = browser_functions.getstringidentifier("document"); + printf("Looking for %p %p %p (%s)\n", instance, window_ptr, identifier, "document"); + if (!browser_functions.hasproperty(instance, window_ptr, identifier)) + { + printf("%s not found!\n", "document"); + } + browser_functions.getproperty(instance, window_ptr, identifier, &member_ptr); + + PLUGIN_DEBUG_1ARG("Got variant %p\n", &member_ptr); + NPError np_error = NPERR_NO_ERROR; GCJPluginData* data = NULL; @@ -390,9 +399,6 @@ instance->pdata = data; - java_to_plugin_bus->subscribe(plugin_req_proc); - plugin_to_java_bus->subscribe(java_req_proc); - goto cleanup_done; cleanup_appletviewer_mutex: @@ -428,7 +434,7 @@ g_hash_table_insert(id_to_instance_map, GINT_TO_POINTER(instance_counter), instance); instance_counter++; - PLUGIN_DEBUG ("GCJ_New return"); + PLUGIN_DEBUG_0ARG ("GCJ_New return\n"); return np_error; } @@ -475,14 +481,14 @@ // clean up any older pip unlink (in_pipe_name); - PLUGIN_DEBUG_TWO ("GCJ_New: creating input fifo:", in_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: creating input fifo: %s", in_pipe_name); if (mkfifo (in_pipe_name, 0700) == -1 && errno != EEXIST) { PLUGIN_ERROR_TWO ("Failed to create input pipe", strerror (errno)); np_error = NPERR_GENERIC_ERROR; goto cleanup_in_pipe_name; } - PLUGIN_DEBUG_TWO ("GCJ_New: created input fifo:", in_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: created input fifo: %s\n", in_pipe_name); // Create plugin-to-appletviewer pipe which we refer to as the // output pipe. @@ -501,14 +507,14 @@ // clean up any older pip unlink (out_pipe_name); - PLUGIN_DEBUG_TWO ("GCJ_New: creating output fifo:", out_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: creating output fifo: %s\n", out_pipe_name); if (mkfifo (out_pipe_name, 0700) == -1 && errno != EEXIST) { PLUGIN_ERROR_TWO ("Failed to create output pipe", strerror (errno)); np_error = NPERR_GENERIC_ERROR; goto cleanup_out_pipe_name; } - PLUGIN_DEBUG_TWO ("GCJ_New: created output fifo:", out_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: created output fifo: %s\n", out_pipe_name); // Start a separate appletviewer process for each applet, even if // there are multiple applets in the same page. We may need to @@ -599,9 +605,9 @@ // cleanup_out_pipe: // Delete output pipe. - PLUGIN_DEBUG_TWO ("GCJ_New: deleting input fifo:", in_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: deleting input fifo: %s\n", in_pipe_name); unlink (out_pipe_name); - PLUGIN_DEBUG_TWO ("GCJ_New: deleted input fifo:", in_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: deleted input fifo: %s\n", in_pipe_name); cleanup_out_pipe_name: g_free (out_pipe_name); @@ -609,9 +615,9 @@ // cleanup_in_pipe: // Delete input pipe. - PLUGIN_DEBUG_TWO ("GCJ_New: deleting output fifo:", out_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: deleting output fifo: %s\n", out_pipe_name); unlink (in_pipe_name); - PLUGIN_DEBUG_TWO ("GCJ_New: deleted output fifo:", out_pipe_name); + PLUGIN_DEBUG_1ARG ("GCJ_New: deleted output fifo: %s\n", out_pipe_name); cleanup_in_pipe_name: g_free (in_pipe_name); @@ -627,7 +633,7 @@ NPError GCJ_GetValue (NPP instance, NPPVariable variable, void* value) { - PLUGIN_DEBUG ("GCJ_GetValue"); + PLUGIN_DEBUG_0ARG ("GCJ_GetValue\n"); NPError np_error = NPERR_NO_ERROR; @@ -636,7 +642,7 @@ // This plugin needs XEmbed support. case NPPVpluginNeedsXEmbed: { - PLUGIN_DEBUG ("GCJ_GetValue: returning TRUE for NeedsXEmbed."); + PLUGIN_DEBUG_0ARG ("GCJ_GetValue: returning TRUE for NeedsXEmbed.\n"); PRBool* bool_value = (PRBool*) value; *bool_value = PR_TRUE; } @@ -653,7 +659,7 @@ break; } - PLUGIN_DEBUG ("GCJ_GetValue return"); + PLUGIN_DEBUG_0ARG ("GCJ_GetValue return\n"); return np_error; } @@ -661,7 +667,7 @@ NPError GCJ_Destroy (NPP instance, NPSavedData** save) { - PLUGIN_DEBUG ("GCJ_Destroy"); + PLUGIN_DEBUG_0ARG ("GCJ_Destroy\n"); GCJPluginData* data = (GCJPluginData*) instance->pdata; @@ -671,7 +677,7 @@ plugin_data_destroy (instance); } - PLUGIN_DEBUG ("GCJ_Destroy return"); + PLUGIN_DEBUG_0ARG ("GCJ_Destroy return\n"); return NPERR_NO_ERROR; } @@ -679,7 +685,7 @@ NPError GCJ_SetWindow (NPP instance, NPWindow* window) { - PLUGIN_DEBUG ("GCJ_SetWindow"); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow"); if (instance == NULL) { @@ -701,7 +707,7 @@ // Simply return if we receive a NULL window. if ((window == NULL) || (window->window == NULL)) { - PLUGIN_DEBUG ("GCJ_SetWindow: got NULL window."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: got NULL window.\n"); return NPERR_NO_ERROR; } @@ -712,7 +718,7 @@ if (data->window_handle == window->window) { // The parent window is the same as in previous calls. - PLUGIN_DEBUG ("GCJ_SetWindow: window already exists."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: window already exists.\n"); // Critical region. Read data->appletviewer_mutex and send // a message to the appletviewer. @@ -727,7 +733,7 @@ // SetWindow call. if (window->width != data->window_width) { - PLUGIN_DEBUG ("GCJ_SetWindow: window width changed."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: window width changed.\n"); // The width of the plugin window has changed. // Store the new width. @@ -737,7 +743,7 @@ if (window->height != data->window_height) { - PLUGIN_DEBUG ("GCJ_SetWindow: window height changed."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: window height changed.\n"); // The height of the plugin window has changed. // Store the new height. @@ -759,7 +765,7 @@ else { // The appletviewer is not running. - PLUGIN_DEBUG ("GCJ_SetWindow: appletviewer is not running."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: appletviewer is not running.\n"); } g_mutex_unlock (data->appletviewer_mutex); @@ -768,12 +774,12 @@ { // The parent window has changed. This branch does run but // doing nothing in response seems to be sufficient. - PLUGIN_DEBUG ("GCJ_SetWindow: parent window changed."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: parent window changed.\n"); } } else { - PLUGIN_DEBUG ("GCJ_SetWindow: setting window."); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow: setting window.\n"); // Critical region. Send messages to appletviewer. g_mutex_lock (data->appletviewer_mutex); @@ -797,7 +803,7 @@ data->window_handle = window->window; } - PLUGIN_DEBUG ("GCJ_SetWindow return"); + PLUGIN_DEBUG_0ARG ("GCJ_SetWindow return\n"); return NPERR_NO_ERROR; } @@ -806,9 +812,9 @@ GCJ_NewStream (NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) { - PLUGIN_DEBUG ("GCJ_NewStream"); + PLUGIN_DEBUG_0ARG ("GCJ_NewStream\n"); - PLUGIN_DEBUG ("GCJ_NewStream return"); + PLUGIN_DEBUG_0ARG ("GCJ_NewStream return\n"); return NPERR_NO_ERROR; } @@ -816,17 +822,17 @@ void GCJ_StreamAsFile (NPP instance, NPStream* stream, const char* filename) { - PLUGIN_DEBUG ("GCJ_StreamAsFile"); + PLUGIN_DEBUG_0ARG ("GCJ_StreamAsFile\n"); - PLUGIN_DEBUG ("GCJ_StreamAsFile return"); + PLUGIN_DEBUG_0ARG ("GCJ_StreamAsFile return\n"); } NPError GCJ_DestroyStream (NPP instance, NPStream* stream, NPReason reason) { - PLUGIN_DEBUG ("GCJ_DestroyStream"); + PLUGIN_DEBUG_0ARG ("GCJ_DestroyStream\n"); - PLUGIN_DEBUG ("GCJ_DestroyStream return"); + PLUGIN_DEBUG_0ARG ("GCJ_DestroyStream return\n"); return NPERR_NO_ERROR; } @@ -834,9 +840,9 @@ int32 GCJ_WriteReady (NPP instance, NPStream* stream) { - PLUGIN_DEBUG ("GCJ_WriteReady"); + PLUGIN_DEBUG_0ARG ("GCJ_WriteReady\n"); - PLUGIN_DEBUG ("GCJ_WriteReady return"); + PLUGIN_DEBUG_0ARG ("GCJ_WriteReady return\n"); return 0; } @@ -845,9 +851,9 @@ GCJ_Write (NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) { - PLUGIN_DEBUG ("GCJ_Write"); + PLUGIN_DEBUG_0ARG ("GCJ_Write\n"); - PLUGIN_DEBUG ("GCJ_Write return"); + PLUGIN_DEBUG_0ARG ("GCJ_Write return\n"); return 0; } @@ -855,17 +861,17 @@ void GCJ_Print (NPP instance, NPPrint* platformPrint) { - PLUGIN_DEBUG ("GCJ_Print"); + PLUGIN_DEBUG_0ARG ("GCJ_Print\n"); - PLUGIN_DEBUG ("GCJ_Print return"); + PLUGIN_DEBUG_0ARG ("GCJ_Print return\n"); } int16 GCJ_HandleEvent (NPP instance, void* event) { - PLUGIN_DEBUG ("GCJ_HandleEvent"); + PLUGIN_DEBUG_0ARG ("GCJ_HandleEvent\n"); - PLUGIN_DEBUG ("GCJ_HandleEvent return"); + PLUGIN_DEBUG_0ARG ("GCJ_HandleEvent return\n"); return 0; } @@ -874,17 +880,17 @@ GCJ_URLNotify (NPP instance, const char* url, NPReason reason, void* notifyData) { - PLUGIN_DEBUG ("GCJ_URLNotify"); + PLUGIN_DEBUG_0ARG ("GCJ_URLNotify\n"); - PLUGIN_DEBUG ("GCJ_URLNotify return"); + PLUGIN_DEBUG_0ARG ("GCJ_URLNotify return\n"); } jref GCJ_GetJavaClass (void) { - PLUGIN_DEBUG ("GCJ_GetJavaClass"); + PLUGIN_DEBUG_0ARG ("GCJ_GetJavaClass\n"); - PLUGIN_DEBUG ("GCJ_GetJavaClass return"); + PLUGIN_DEBUG_0ARG ("GCJ_GetJavaClass return\n"); return 0; } @@ -892,7 +898,6 @@ NS_IMETHODIMP get_cookie_info(const char* siteAddr, char** cookieString) { - nsresult rv; nsCOMPtr<nsIScriptSecurityManager> sec_man = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); @@ -931,7 +936,7 @@ static void plugin_data_new (GCJPluginData** data) { - PLUGIN_DEBUG ("plugin_data_new"); + PLUGIN_DEBUG_0ARG ("plugin_data_new"); *data = (GCJPluginData*) (*browser_functions.memalloc) (sizeof (struct GCJPluginData)); @@ -940,7 +945,7 @@ if (*data) memset (*data, 0, sizeof (struct GCJPluginData)); - PLUGIN_DEBUG ("plugin_data_new return"); + PLUGIN_DEBUG_0ARG ("plugin_data_new return\n"); } // Documentbase retrieval. This function gets the current document's @@ -952,7 +957,7 @@ static gchar* plugin_get_documentbase (NPP instance) { - PLUGIN_DEBUG ("plugin_get_documentbase"); + PLUGIN_DEBUG_0ARG ("plugin_get_documentbase"); nsIPluginInstance* xpcom_instance = NULL; nsIPluginInstancePeer* peer = NULL; @@ -1004,7 +1009,7 @@ NS_RELEASE (peer); cleanup_done: - PLUGIN_DEBUG ("plugin_get_documentbase return"); + PLUGIN_DEBUG_0ARG ("plugin_get_documentbase return\n"); return documentbase_copy; } @@ -1016,7 +1021,7 @@ { GtkWidget* dialog = NULL; - PLUGIN_DEBUG ("plugin_display_failure_dialog"); + PLUGIN_DEBUG_0ARG ("plugin_display_failure_dialog"); dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1028,7 +1033,7 @@ gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); - PLUGIN_DEBUG ("plugin_display_failure_dialog return"); + PLUGIN_DEBUG_0ARG ("plugin_display_failure_dialog return\n"); } @@ -1042,7 +1047,7 @@ GIOCondition condition, gpointer plugin_data) { - PLUGIN_DEBUG ("plugin_in_pipe_callback"); + PLUGIN_DEBUG_0ARG ("plugin_in_pipe_callback\n"); gboolean keep_installed = TRUE; @@ -1077,18 +1082,18 @@ if (condition & (G_IO_ERR | G_IO_HUP)) { - PLUGIN_DEBUG ("appletviewer has stopped."); + PLUGIN_DEBUG_0ARG ("appletviewer has stopped.\n"); keep_installed = FALSE; } - PLUGIN_DEBUG ("plugin_in_pipe_callback return"); + PLUGIN_DEBUG_0ARG ("plugin_in_pipe_callback return\n"); return keep_installed; } void consume_message(gchar* message) { - g_print (" PIPE: plugin read: %s\n", message); + PLUGIN_DEBUG_1ARG (" PIPE: plugin read: %s\n", message); if (g_str_has_prefix (message, "instance")) { @@ -1117,8 +1122,8 @@ gchar* decoded_url = (gchar*) malloc(strlen(parts[3])*sizeof(gchar) + sizeof(gchar)); decode_url(parts[3], &decoded_url); - PLUGIN_DEBUG_TWO ("plugin_in_pipe_callback: opening URL", decoded_url); - PLUGIN_DEBUG_TWO ("plugin_in_pipe_callback: URL target", parts[4]); + PLUGIN_DEBUG_1ARG ("plugin_in_pipe_callback: opening URL %s\n", decoded_url); + PLUGIN_DEBUG_1ARG ("plugin_in_pipe_callback: URL target %s\n", parts[4]); NPError np_error = (*browser_functions.geturl) (data->owner, decoded_url, parts[4]); @@ -1140,7 +1145,7 @@ // join the rest gchar* status_message = g_strjoinv(" ", parts); - PLUGIN_DEBUG_TWO ("plugin_in_pipe_callback: setting status", status_message); + PLUGIN_DEBUG_1ARG ("plugin_in_pipe_callback: setting status %s\n", status_message); (*browser_functions.status) (data->owner, status_message); g_free(status_message); @@ -1148,7 +1153,7 @@ } else if (g_str_has_prefix (parts[1], "internal")) { - internal_bus->post(message); + //s->post(message); } else { @@ -1201,6 +1206,29 @@ proxy_host = NULL; g_free(proxy_port); proxy_port = NULL; + } else if (g_str_has_prefix(parts[1], "PluginCookieInfo")) + { + GError *error = g_error_new(ITNP_PLUGIN_ERROR, 0, ""); + + gchar* decoded_url = (gchar*) malloc(strlen(parts[2])*sizeof(gchar) + sizeof(gchar)); + decode_url(parts[2], &decoded_url); + + gchar* cookie_info = g_strconcat ("plugin PluginCookieInfo ", parts[2], " ", NULL); + gchar* cookie_string; + if (get_cookie_info(decoded_url, &cookie_string) == NS_OK) + { + cookie_info = g_strconcat (cookie_info, cookie_string, NULL); + } + + PLUGIN_DEBUG_1ARG("Cookie info: %s\n", cookie_info); + plugin_send_message_to_appletviewer(cookie_info); + + g_free(decoded_url); + decoded_url = NULL; + g_free(cookie_string); + cookie_string = NULL; + g_free(cookie_info); + cookie_info = NULL; } } else @@ -1309,6 +1337,42 @@ PLUGIN_DEBUG_4ARG("Proxy info for %s: %s %s %s\n", siteAddr, *proxy_scheme, *proxy_host, *proxy_port); } +/* +void get_cookie_info(const char* siteAddr, char** cookie_string) +{ + nsresult rv; + nsCOMPtr<nsIScriptSecurityManager> sec_man = do_GetService( + NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + + if (!sec_man) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIIOService> io_svc = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); + + if (NS_FAILED(rv) || !io_svc) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIURI> uri; + io_svc->NewURI(nsCString(siteAddr), NULL, NULL, getter_AddRefs(uri)); + + nsCOMPtr<nsICookieService> cookie_svc = do_GetService( + NS_COOKIESERVICE_CONTRACTID, &rv); + + if (NS_FAILED(rv) || !cookie_svc) { + return NS_ERROR_FAILURE; + } + + rv = cookie_svc->GetCookieString(uri, NULL, cookieString); + + if (NS_FAILED(rv) || !*cookieString) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +}*/ + // plugin_out_pipe_callback is called when the appletviewer crashes or // is killed. It may be called after data has been destroyed in which // case it simply returns FALSE to remove itself from the glib main @@ -1318,13 +1382,13 @@ GIOCondition condition, gpointer plugin_data) { - PLUGIN_DEBUG ("plugin_out_pipe_callback"); + PLUGIN_DEBUG_0ARG ("plugin_out_pipe_callback\n"); GCJPluginData* data = (GCJPluginData*) plugin_data; - PLUGIN_DEBUG ("plugin_out_pipe_callback: appletviewer has stopped."); + PLUGIN_DEBUG_0ARG ("plugin_out_pipe_callback: appletviewer has stopped.\n"); - PLUGIN_DEBUG ("plugin_out_pipe_callback return"); + PLUGIN_DEBUG_0ARG ("plugin_out_pipe_callback return\n"); return FALSE; } @@ -1332,7 +1396,7 @@ static NPError plugin_test_appletviewer () { - PLUGIN_DEBUG ("plugin_test_appletviewer"); + PLUGIN_DEBUG_0ARG ("plugin_test_appletviewer\n"); NPError error = NPERR_NO_ERROR; gchar* command_line[3] = { NULL, NULL, NULL }; @@ -1364,26 +1428,34 @@ g_free (command_line[2]); command_line[2] = NULL; - PLUGIN_DEBUG ("plugin_test_appletviewer return"); + PLUGIN_DEBUG_0ARG ("plugin_test_appletviewer return\n"); return error; } static NPError plugin_start_appletviewer (GCJPluginData* data) { - PLUGIN_DEBUG ("plugin_start_appletviewer"); + PLUGIN_DEBUG_0ARG ("plugin_start_appletviewer\n"); NPError error = NPERR_NO_ERROR; - gchar* command_line[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; + gchar** command_line; - command_line[0] = g_strdup (appletviewer_executable); - // Output from plugin's perspective is appletviewer's input. - // Input from plugin's perspective is appletviewer's output. - command_line[1] = g_strdup("-Xdebug"); - command_line[2] = g_strdup("-Xnoagent"); - command_line[3] = g_strdup("-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"); - command_line[4] = g_strdup("sun.applet.PluginMain"); - command_line[5] = NULL; + if (plugin_debug) + { + command_line = (gchar**) malloc(sizeof(gchar*)*6); + command_line[0] = g_strdup(appletviewer_executable); + command_line[1] = g_strdup("-Xdebug"); + command_line[2] = g_strdup("-Xnoagent"); + command_line[3] = g_strdup("-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"); + command_line[4] = g_strdup("sun.applet.PluginMain"); + command_line[5] = NULL; + } else + { + command_line = (gchar**) malloc(sizeof(gchar)*3); + command_line[0] = g_strdup(appletviewer_executable); + command_line[1] = g_strdup("sun.applet.PluginMain"); + command_line[2] = NULL; + } if (!g_spawn_async (NULL, command_line, NULL, (GSpawnFlags) G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &appletviewer_pid, &channel_error)) @@ -1404,14 +1476,21 @@ command_line[0] = NULL; g_free (command_line[1]); command_line[1] = NULL; - g_free (command_line[2]); - command_line[2] = NULL; - g_free (command_line[3]); - command_line[3] = NULL; - g_free (command_line[4]); - command_line[4] = NULL; - g_free (command_line[5]); - command_line[5] = NULL; + + if (plugin_debug) + { + g_free (command_line[2]); + command_line[2] = NULL; + g_free (command_line[3]); + command_line[3] = NULL; + g_free (command_line[4]); + command_line[4] = NULL; + g_free (command_line[5]); + command_line[5] = NULL; + } + + g_free(command_line); + command_line = NULL; if (appletviewer_pid) { @@ -1420,7 +1499,7 @@ } - PLUGIN_DEBUG ("plugin_start_appletviewer return"); + PLUGIN_DEBUG_0ARG ("plugin_start_appletviewer return\n"); return error; } @@ -1429,7 +1508,7 @@ static gchar* plugin_create_applet_tag (int16 argc, char* argn[], char* argv[]) { - PLUGIN_DEBUG ("plugin_create_applet_tag"); + PLUGIN_DEBUG_0ARG ("plugin_create_applet_tag\n"); gchar* applet_tag = g_strdup ("<EMBED "); gchar* parameters = g_strdup (""); @@ -1501,7 +1580,7 @@ g_free (parameters); parameters = NULL; - PLUGIN_DEBUG ("plugin_create_applet_tag return"); + PLUGIN_DEBUG_0ARG ("plugin_create_applet_tag return\n"); return applet_tag; } @@ -1511,7 +1590,7 @@ void plugin_send_message_to_appletviewer (gchar const* message) { - PLUGIN_DEBUG ("plugin_send_message_to_appletviewer"); + PLUGIN_DEBUG_0ARG ("plugin_send_message_to_appletviewer\n"); if (jvm_up) { @@ -1556,10 +1635,10 @@ g_free (newline_message); newline_message = NULL; - g_print (" PIPE: plugin wrote: %s\n", message); + PLUGIN_DEBUG_1ARG (" PIPE: plugin wrote: %s\n", message); } - PLUGIN_DEBUG ("plugin_send_message_to_appletviewer return"); + PLUGIN_DEBUG_0ARG ("plugin_send_message_to_appletviewer return\n"); } // Stop the appletviewer process. When this is called the @@ -1578,7 +1657,7 @@ static void plugin_stop_appletviewer () { - PLUGIN_DEBUG ("plugin_stop_appletviewer"); + PLUGIN_DEBUG_0ARG ("plugin_stop_appletviewer\n"); if (jvm_up) { @@ -1654,21 +1733,21 @@ jvm_up = FALSE; sleep(2); /* Needed to prevent crashes during debug (when JDWP port is not freed by the kernel right away) */ - PLUGIN_DEBUG ("plugin_stop_appletviewer return"); + PLUGIN_DEBUG_0ARG ("plugin_stop_appletviewer return\n"); } static void appletviewer_monitor(GPid pid, gint status, gpointer data) { - PLUGIN_DEBUG ("appletviewer_monitor"); + PLUGIN_DEBUG_0ARG ("appletviewer_monitor\n"); jvm_up = FALSE; pid = -1; - PLUGIN_DEBUG ("appletviewer_monitor return"); + PLUGIN_DEBUG_0ARG ("appletviewer_monitor return\n"); } static void plugin_data_destroy (NPP instance) { - PLUGIN_DEBUG ("plugin_data_destroy"); + PLUGIN_DEBUG_0ARG ("plugin_data_destroy\n"); GCJPluginData* tofree = (GCJPluginData*) instance->pdata; @@ -1700,7 +1779,7 @@ (*browser_functions.memfree) (tofree); tofree = NULL; - PLUGIN_DEBUG ("plugin_data_destroy return"); + PLUGIN_DEBUG_0ARG ("plugin_data_destroy return\n"); } // FACTORY FUNCTIONS @@ -1717,7 +1796,7 @@ NPError NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) { - PLUGIN_DEBUG ("NP_Initialize"); + PLUGIN_DEBUG_0ARG ("NP_Initialize\n"); if (initialized) return NPERR_NO_ERROR; @@ -1882,9 +1961,18 @@ plugin_instance_mutex = g_mutex_new (); - PLUGIN_DEBUG_TWO ("NP_Initialize: using", appletviewer_executable); + PLUGIN_DEBUG_1ARG ("NP_Initialize: using %s\n", appletviewer_executable); + + PLUGIN_DEBUG_0ARG ("NP_Initialize return\n"); - PLUGIN_DEBUG ("NP_Initialize return"); + java_to_plugin_bus->subscribe(plugin_req_proc); + plugin_to_java_bus->subscribe(java_req_proc); + //internal_bus->subscribe(java_req_proc); + //internal_bus->subscribe(plugin_req_proc); + + pthread_create (&plugin_request_processor_thread1, NULL, &queue_processor, (void*) plugin_req_proc); + pthread_create (&plugin_request_processor_thread2, NULL, &queue_processor, (void*) plugin_req_proc); + pthread_create (&plugin_request_processor_thread3, NULL, &queue_processor, (void*) plugin_req_proc); return NPERR_NO_ERROR; @@ -1917,9 +2005,9 @@ char* NP_GetMIMEDescription (void) { - PLUGIN_DEBUG ("NP_GetMIMEDescription"); + PLUGIN_DEBUG_0ARG ("NP_GetMIMEDescription\n"); - PLUGIN_DEBUG ("NP_GetMIMEDescription return"); + PLUGIN_DEBUG_0ARG ("NP_GetMIMEDescription return\n"); return (char*) PLUGIN_MIME_DESC; } @@ -1929,7 +2017,7 @@ NPError NP_GetValue (void* future, NPPVariable variable, void* value) { - PLUGIN_DEBUG ("NP_GetValue"); + PLUGIN_DEBUG_0ARG ("NP_GetValue\n"); NPError result = NPERR_NO_ERROR; gchar** char_value = (gchar**) value; @@ -1937,12 +2025,12 @@ switch (variable) { case NPPVpluginNameString: - PLUGIN_DEBUG ("NP_GetValue: returning plugin name."); + PLUGIN_DEBUG_0ARG ("NP_GetValue: returning plugin name.\n"); *char_value = g_strdup (PLUGIN_NAME " " PACKAGE_VERSION); break; case NPPVpluginDescriptionString: - PLUGIN_DEBUG ("NP_GetValue: returning plugin description."); + PLUGIN_DEBUG_0ARG ("NP_GetValue: returning plugin description.\n"); *char_value = g_strdup (PLUGIN_DESC); break; @@ -1952,7 +2040,7 @@ break; } - PLUGIN_DEBUG ("NP_GetValue return"); + PLUGIN_DEBUG_0ARG ("NP_GetValue return\n"); return result; } @@ -1962,7 +2050,7 @@ NPError NP_Shutdown (void) { - PLUGIN_DEBUG ("NP_Shutdown"); + PLUGIN_DEBUG_0ARG ("NP_Shutdown\n"); // Free mutex. if (plugin_instance_mutex) @@ -2011,9 +2099,9 @@ // cleanup_out_pipe: // Delete output pipe. - PLUGIN_DEBUG_TWO ("NP_Shutdown: deleting output fifo:", out_pipe_name); + PLUGIN_DEBUG_1ARG ("NP_Shutdown: deleting output fifo: %s\n", out_pipe_name); unlink (out_pipe_name); - PLUGIN_DEBUG_TWO ("NP_Shutdown: deleted output fifo:", out_pipe_name); + PLUGIN_DEBUG_1ARG ("NP_Shutdown: deleted output fifo: %s\n", out_pipe_name); // cleanup_out_pipe_name: g_free (out_pipe_name); @@ -2021,9 +2109,9 @@ // cleanup_in_pipe: // Delete input pipe. - PLUGIN_DEBUG_TWO ("NP_Shutdown: deleting input fifo:", in_pipe_name); + PLUGIN_DEBUG_1ARG ("NP_Shutdown: deleting input fifo: %s\n", in_pipe_name); unlink (in_pipe_name); - PLUGIN_DEBUG_TWO ("NP_Shutdown: deleted input fifo:", in_pipe_name); + PLUGIN_DEBUG_1ARG ("NP_Shutdown: deleted input fifo: %s\n", in_pipe_name); // cleanup_in_pipe_name: g_free (in_pipe_name); @@ -2031,7 +2119,22 @@ initialized = false; - PLUGIN_DEBUG ("NP_Shutdown return"); + pthread_cancel(plugin_request_processor_thread1); + pthread_cancel(plugin_request_processor_thread2); + pthread_cancel(plugin_request_processor_thread3); + + java_to_plugin_bus->unSubscribe(plugin_req_proc); + plugin_to_java_bus->unSubscribe(java_req_proc); + //internal_bus->unSubscribe(java_req_proc); + //internal_bus->unSubscribe(plugin_req_proc); + + delete plugin_req_proc; + delete java_req_proc; + delete java_to_plugin_bus; + delete plugin_to_java_bus; + //delete internal_bus; + + PLUGIN_DEBUG_0ARG ("NP_Shutdown return\n"); return NPERR_NO_ERROR; }
--- a/plugin/icedteanp/IcedTeaNPPlugin.h Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaNPPlugin.h Thu Jul 23 11:39:18 2009 -0400 @@ -54,6 +54,14 @@ #include "IcedTeaPluginUtils.h" #include "IcedTeaPluginRequestProcessor.h" +// Queue processing threads +static pthread_t plugin_request_processor_thread1; +static pthread_t plugin_request_processor_thread2; +static pthread_t plugin_request_processor_thread3; + +// debug switch +extern int plugin_debug; + // Browser function table. extern NPNetscapeFuncs browser_functions; @@ -64,7 +72,7 @@ extern MessageBus* java_to_plugin_bus; // internal messages (e.g ones that need processing in main thread) -extern MessageBus* internal_bus; +//extern MessageBus* internal_bus; // subscribes to plugin_to_java_bus and sends messages over the link extern JavaMessageSender java_request_processor; @@ -79,7 +87,7 @@ int get_id_from_instance(NPP* instance); /* Sends a message to the appletviewer */ -void plugin_send_message_to_appletviewer (gchar const* message); +void plugin_send_message_to_appletviewer(gchar const* message); /* Returns a scriptable npobject */ NPObject* get_scriptable_object(NPP instance); @@ -87,4 +95,7 @@ /* Creates a new scriptable plugin object and returns it */ NPObject* allocate_scriptable_object(NPP npp, NPClass *aClass); +/* SIGUSR1 handler */ +void sigusr1handler(); + #endif /* __ICEDTEANPPLUGIN_H__ */
--- a/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc Thu Jul 23 11:39:18 2009 -0400 @@ -44,6 +44,11 @@ * 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>* >(); + /** * Given the window pointer, returns the instance associated with it * @@ -55,18 +60,18 @@ getInstanceFromMemberPtr(void* member_ptr) { - NPP instance = NULL; - PLUGIN_DEBUG_1ARG("getInstanceFromMemberPtr looking for %p\n", member_ptr); + NPP instance = NULL; + PLUGIN_DEBUG_1ARG("getInstanceFromMemberPtr looking for %p\n", member_ptr); - std::map<void*, NPP>::iterator iterator = instance_map->find(member_ptr); + std::map<void*, NPP>::iterator iterator = instance_map->find(member_ptr); - if (iterator != instance_map->end()) - { - instance = instance_map->find(member_ptr)->second; - PLUGIN_DEBUG_2ARG("getInstanceFromMemberPtr found %p. Instance = %p\n", member_ptr, instance); - } + if (iterator != instance_map->end()) + { + instance = instance_map->find(member_ptr)->second; + PLUGIN_DEBUG_2ARG("getInstanceFromMemberPtr found %p. Instance = %p\n", member_ptr, instance); + } - return instance; + return instance; } /** @@ -79,8 +84,8 @@ void storeInstanceID(void* member_ptr, NPP instance) { - PLUGIN_DEBUG_2ARG("Storing instance %p with key %p\n", instance, member_ptr); - instance_map->insert(std::make_pair(member_ptr, instance)); + PLUGIN_DEBUG_2ARG("Storing instance %p with key %p\n", instance, member_ptr); + instance_map->insert(std::make_pair(member_ptr, instance)); } /** @@ -91,8 +96,10 @@ PluginRequestProcessor::PluginRequestProcessor() { - this->pendingRequests = new std::map<pthread_t, uintmax_t>(); - instance_map = new std::map<void*, NPP>(); + this->pendingRequests = new std::map<pthread_t, uintmax_t>(); + instance_map = new std::map<void*, NPP>(); + + internal_req_ref_counter = 0; } /** @@ -103,11 +110,13 @@ PluginRequestProcessor::~PluginRequestProcessor() { - if (pendingRequests) - delete pendingRequests; + PLUGIN_DEBUG_0ARG("PluginRequestProcessor::~PluginRequestProcessor\n"); - if (instance_map) - delete instance_map; + if (pendingRequests) + delete pendingRequests; + + if (instance_map) + delete instance_map; } @@ -121,66 +130,49 @@ bool PluginRequestProcessor::newMessageOnBus(const char* message) { - PLUGIN_DEBUG_1ARG("PluginRequestProcessor processing %s\n", message); - - std::string type; - std::string command; - int counter = 0; + PLUGIN_DEBUG_1ARG("PluginRequestProcessor processing %s\n", message); - std::vector<std::string>* message_parts = IcedTeaPluginUtilities::strSplit(message, " "); + std::string type; + std::string command; + int counter = 0; - std::vector<std::string>::iterator the_iterator; - the_iterator = message_parts->begin(); - - IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::newMessageOnBus:", message_parts); + std::vector<std::string>* message_parts = IcedTeaPluginUtilities::strSplit(message, " "); - // Prioritize internal requests - if (message_parts->at(0) == "internal") - { - if (message_parts->at(1) == "SendMember") - { - // first item is length, and it is radix 10 - int length = strtol(message_parts->at(3).c_str(), NULL, 10); + std::vector<std::string>::iterator the_iterator; + the_iterator = message_parts->begin(); - std::vector<std::string*>* send_string_req = new std::vector<std::string*>(); - std::string* member_name = new std::string(); + IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::newMessageOnBus:", message_parts); - // pack parent id and member name - send_string_req->push_back(&(message_parts->at(0))); - IcedTeaPluginUtilities::getUTF8String(length, 4 /* start at */, message_parts, member_name); - send_string_req->push_back(member_name); + type = message_parts->at(0); + command = message_parts->at(2); - // make the internal request - this->_sendMember(send_string_req); - - // free the memory - delete send_string_req; - delete message_parts; - - return true; // request processed - } - } - - type = message_parts->at(0); - command = message_parts->at(2); + if (type == "instance") + { + if (command == "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 == "GetMember" || + command == "SetMember" || + command == "ToString") + { - if (type == "instance") - { - if (command == "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 == "GetMember") - { - this->dispatch(&sendMember, message_parts, NULL); - return true; - } - } + // Update queue synchronously + pthread_mutex_lock(&message_queue_mutex); + message_queue->push_back(message_parts); + pthread_mutex_unlock(&message_queue_mutex); - // If we got here, it means we couldn't process the message. Let the caller know. - return false; + return true; + } + + } + + delete message_parts; + + // If we got here, it means we couldn't process the message. Let the caller know. + return false; } /** @@ -198,16 +190,27 @@ void PluginRequestProcessor::dispatch(void* func_ptr (void*), std::vector<std::string>* message_parts, std::string* src) { - pthread_t thread; - ThreadData* tdata = new ThreadData(); + pthread_t thread; + int tries = 0; + ThreadData* tdata = new ThreadData(); - IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::dispatch:", message_parts); + IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::dispatch:", message_parts); + + tdata->source = src; + tdata->message_parts = message_parts; - tdata->source = src; - tdata->message_parts = message_parts; + printf("Threads MAX=%ld, Thread data=%p\n", sysconf(_SC_THREAD_THREADS_MAX), tdata); + while (pthread_create (&thread, NULL, func_ptr, (void*) tdata) == 11 && tries++ < 100) + { + printf("Couldn't create thread. Sleeping and then retrying. TC=%d\n", thread_count); + usleep(1000000); + } + uintmax_t start_time = (uintmax_t) time(NULL); + pthread_mutex_lock(&tc_mutex); + thread_count++; + pthread_mutex_unlock(&tc_mutex); - pthread_create (&thread, NULL, func_ptr, (void*) tdata); - uintmax_t start_time = (uintmax_t) time(NULL); + PLUGIN_DEBUG_2ARG("pthread %p created. Thread count=%d\n", thread, thread_count); } /** @@ -219,38 +222,210 @@ void PluginRequestProcessor::sendWindow(std::vector<std::string>* message_parts) { - std::string type; - std::string command; - std::string* response; - std::string* window_ptr_str; - int id; + std::string type; + std::string command; + std::string* response; + std::string* window_ptr_str; + static NPObject* window_ptr; + int id; + + type = message_parts->at(0); + id = atoi(message_parts->at(1).c_str()); + command = message_parts->at(2); + + NPP instance; + get_instance_from_id(id, instance); + + browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr); + PLUGIN_DEBUG_3ARG("ID=%d, Instance=%p, WindowPTR = %p\n", id, instance, window_ptr); + + window_ptr_str = IcedTeaPluginUtilities::JSIDToString(window_ptr); + + // We need the context 0 for backwards compatibility with the Java side + response = IcedTeaPluginUtilities::constructMessagePrefix(0); + *response += " JavaScriptGetWindow "; + *response += *window_ptr_str; + + plugin_to_java_bus->post(response->c_str()); + + delete response; + delete window_ptr_str; + delete message_parts; + + // store the instance pointer for future reference + storeInstanceID(window_ptr, instance); +} - type = message_parts->at(0); - id = atoi(message_parts->at(1).c_str()); - command = message_parts->at(2); +/** + * 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; + std::string* variant_string; + std::string* variant_string_id; + JavaRequestProcessor* java_request; + JavaResultData* java_result; + std::string* response; + int instance; + + instance = atoi(message_parts->at(1).c_str()); + variant_ptr = message_parts->at(3); + + variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr); + variant_string = IcedTeaPluginUtilities::NPVariantToString(*variant); + + java_request = new JavaRequestProcessor(); + java_result = java_request->newString(*variant_string); - NPP instance; - get_instance_from_id(id, instance); + if (java_result->error_occured) + { + printf("Unable to process NewString request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } + + variant_string_id = java_result->return_string; + + // We need the context 0 for backwards compatibility with the Java side + response = IcedTeaPluginUtilities::constructMessagePrefix(instance); + *response += " JavaScriptToString "; + *response += *variant_string_id; + + plugin_to_java_bus->post(response->c_str()); + + cleanup: + delete java_request; + delete response; + delete variant_string; + delete message_parts; + + pthread_mutex_lock(&tc_mutex); + thread_count--; + pthread_mutex_unlock(&tc_mutex); +} + +/** + * Sets variable to given value + * + * @param message_parts The request message. + */ - static NPObject *window_ptr; - browser_functions.getvalue(instance, NPNVWindowNPObject, &window_ptr); - PLUGIN_DEBUG_3ARG("ID=%d, Instance=%p, WindowPTR = %p\n", id, instance, window_ptr); +void +PluginRequestProcessor::setMember(std::vector<std::string>* message_parts) +{ + std::string valueID; + std::string propertyNameID; + std::string* property_name = new std::string(); + std::string* value = new std::string(); + std::string* type = new std::string(); + std::string* value_variant_ptr_str; + std::vector<std::string*>* internal_request_params = new std::vector<std::string*>(); + + NPObject* member; + nsCOMPtr<nsIRunnable> event; + ResultData* rdata = new ResultData(); + + JavaRequestProcessor* java_request; + JavaResultData* java_result; + + IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::_setMember - ", message_parts); + + member = reinterpret_cast <NPObject*> (IcedTeaPluginUtilities::stringToJSID(message_parts->at(3))); + propertyNameID = message_parts->at(4); + valueID = message_parts->at(5); + + java_request = new JavaRequestProcessor(); + java_result = java_request->getString(propertyNameID); - window_ptr_str = IcedTeaPluginUtilities::JSIDToString(window_ptr); + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occured) + { + printf("Unable to get member name for setMember. Error occurred: %s\n", java_result->error_msg); + goto cleanup; + } + + // Copy into local variable before disposing the object + property_name->append(*(java_result->return_string)); + delete java_request; + + // Based on the value ID, find the type and string value + // FIXME: Complex java objects not yet peered + + java_request = new JavaRequestProcessor(); + java_result = java_request->getClassName(valueID); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occured) + { + printf("Unable to get class name for setMember. Error occurred: %s\n", java_result->error_msg); + goto cleanup; + } + + // Copy into local variable before disposing the object + type->append(*(java_result->return_string)); + delete java_request; - // We need the context 0 for backwards compatibility with the Java side - response = IcedTeaPluginUtilities::constructMessagePrefix(0); - *response += " JavaScriptGetWindow "; - *response += *window_ptr_str; + java_request = new JavaRequestProcessor(); + java_result = java_request->getToStringValue(valueID); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occured) + { + printf("Unable to get value for setMember. Error occurred: %s\n", java_result->error_msg); + goto cleanup; + } + + value->append(*(java_result->return_string)); - plugin_to_java_bus->post(response->c_str()); + internal_request_params->push_back(IcedTeaPluginUtilities::JSIDToString(member)); + internal_request_params->push_back(property_name); + internal_request_params->push_back(type); + internal_request_params->push_back(value); + + rdata->result_ready = false; + event = new IcedTeaRunnableMethod(&_setMember, (void*) internal_request_params, rdata); + NS_DispatchToMainThread(event, 0); + + cleanup: + delete message_parts; + delete java_request; - delete response; - delete window_ptr_str; - delete message_parts; + // property_name, type and value are deleted by _setMember + pthread_mutex_lock(&tc_mutex); + thread_count--; + pthread_mutex_unlock(&tc_mutex); +} - // store the instance pointer for future reference - storeInstanceID(window_ptr, instance); +void +convertToNPVariant(std::string value, std::string type, NPVariant* result_variant) +{ + if (type == "java.lang.Byte" || + type == "java.lang.Char" || + type == "java.lang.Short" || + type == "java.lang.Integer") { + int i = atoi(value.c_str()); + INT32_TO_NPVARIANT(i, *result_variant); + } else if (type == "java.lang.Long" || + type == "java.lang.Double" || + type == "java.lang.Float") + { + double d = atof(value.c_str()); + DOUBLE_TO_NPVARIANT(d, *result_variant); + } else if (type == "java.lang.Boolean") + { + bool b = (value == "true"); + BOOLEAN_TO_NPVARIANT(b, *result_variant); + } else if (type == "java.lang.String") + { + STRINGZ_TO_NPVARIANT(value.c_str(), *result_variant); + } else if (type.substr(0,1) == "[") + { + // FIXME: Set up object peering + } } /** @@ -261,160 +436,299 @@ * does whatever it can seperately, and then makes an internal request that * causes _sendMember to do the rest of the work. * - * @param tdata A ThreadData structure holding information needed by this function. - */ - -void* -sendMember(void* tdata) -{ - // member initialization - std::vector<std::string>* message_parts; - std::vector<std::string>* compound_data; - JavaRequestProcessor* java_request; - JavaRequest* java_request_data; - std::string* member_id = new std::string(); - std::string* parent_id = new std::string(); - std::string* member_name_utf = new std::string(); - std::string* internal_request = new std::string(); - int id; - - /** Data extraction **/ - - // extract data passed from parent thread - ThreadData *data; - data = (ThreadData*) tdata; - message_parts = data->message_parts; - - // debug printout of parent thread data - IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::getMember:", message_parts); - - // store info in local variables for easy access - id = atoi(message_parts->at(1).c_str()); - *parent_id += message_parts->at(3); - *member_id += message_parts->at(4); - - /** Request data from Java **/ - - // create a compound request data structure to pass to getString - compound_data = new std::vector<std::string>(); - compound_data->push_back(*member_id); - - // make a new request for getString, to get the name of the identifier - java_request = new JavaRequestProcessor(); - java_request_data = new JavaRequest(); - java_request_data->instance = id; - java_request_data->data = compound_data; - java_request_data->source = data->source != NULL ? data->source : new std::string("file://"); - JavaResultData* result = java_request->getString(java_request_data); - - // the result we want is in result_string (assuming there was no error) - if (result->error_occured) - { - printf("Unable to process getMember request. Error occurred: %s\n", result->error_msg); - goto cleanup; - } - - /** Make an internal request for the main thread to handle**/ - IcedTeaPluginUtilities::convertStringToUTF8(result->return_string, member_name_utf); - - // Ask main thread to do the send - *internal_request = "internal SendMember "; - *internal_request += *parent_id; - *internal_request += " "; - *internal_request += *member_name_utf; - - java_to_plugin_bus->post(internal_request->c_str()); - - // Now be a good citizen and help keep the heap free of garbage - cleanup: - delete data; // thread data that caller allocated for us - delete java_request; // request object - delete java_request_data; // request data - delete member_id; // member id string - delete compound_data; // compound data object - delete message_parts; // message_parts vector that was allocated by the caller - delete internal_request; // delete the string that held the internal request data -} - -/** - * Given the parent id and the member name, sends the member pointer to Java. - * - * @param message_parts Vector containing the parent pointer and member name + * @param message_parts The request message */ void -PluginRequestProcessor::_sendMember(std::vector<std::string*>* message_parts) +PluginRequestProcessor::sendMember(std::vector<std::string>* message_parts) { - std::string* member_ptr_str; - std::string* member; - std::string* parent; + // member initialization + std::vector<std::string>* args; + JavaRequestProcessor* java_request; + JavaResultData* java_result; + ResultData* member_data; + std::string* member_id = new std::string(); + std::string* parent_id = new std::string(); + std::string* jsObjectClassID = new std::string(); + std::string* jsObjectConstructorID = new std::string(); + std::string* response = new std::string(); + nsCOMPtr<nsIRunnable> event; - NPObject *window_ptr; - NPVariant member_ptr; - NPP instance; - NPIdentifier identifier; - std::string* response; + std::vector<std::string*>* internal_request_params = new std::vector<std::string*>(); + int method_id; + int instance; + long reference; - IcedTeaPluginUtilities::printStringPtrVector(" - ", message_parts); + // debug printout of parent thread data + IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::getMember:", message_parts); + + // store info in local variables for easy access + instance = atoi(message_parts->at(1).c_str()); + *parent_id += message_parts->at(3); + *member_id += message_parts->at(4); + + /** Request data from Java **/ - parent = message_parts->at(0); - member = message_parts->at(1); + // make a new request for getString, to get the name of the identifier + java_request = new JavaRequestProcessor(); + java_result = java_request->getString(*member_id); - std::cout << "MEMBER=" << *member << std::endl; + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occured) + { + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; + } - // Get the corresponding windowId - identifier = browser_functions.getstringidentifier(member->c_str()); + /** Make an internal request for the main thread to handle, to get the member pointer **/ - // Get the window pointer - window_ptr = reinterpret_cast <NPObject*> (IcedTeaPluginUtilities::stringToJSID(parent->c_str())); + reference = internal_req_ref_counter++; + + internal_request_params->push_back(parent_id); + internal_request_params->push_back(java_result->return_string); + + member_data = new ResultData(); + member_data->result_ready = false; - // Get the associated instance - instance = getInstanceFromMemberPtr(window_ptr); + event = new IcedTeaRunnableMethod(&_getMember, (void*) internal_request_params, member_data); + NS_DispatchToMainThread(event, 0); - printf("[2] Instance=%p, window=%p, identifier=%p -- %s::%s\n", instance, window_ptr, identifier, parent->c_str(), member->c_str()); + while (!member_data->result_ready) // wait till ready + { + usleep(2000); + } - // Get the NPVariant corresponding to this member - browser_functions.getproperty(instance, window_ptr, identifier, &member_ptr); + PLUGIN_DEBUG_1ARG("Member PTR after internal request: %s\n", member_data->return_string->c_str()); - PLUGIN_DEBUG_4ARG("[3] Instance=%p, window=%p, identifier=%p, variant=%p\n", instance, window_ptr, identifier, &member_ptr); + internal_req_ref_counter--; - if (NPVARIANT_IS_VOID(member_ptr)) - { - printf("VOID %d\n", member_ptr); - } - else if (NPVARIANT_IS_NULL(member_ptr)) - { - printf("NULL\n", member_ptr); - } - else if (NPVARIANT_IS_BOOLEAN(member_ptr)) + delete java_request; + java_request = new JavaRequestProcessor(); + java_result = java_request->findClass("netscape.javascript.JSObject"); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occured) { - printf("BOOL: %d\n", NPVARIANT_TO_BOOLEAN(member_ptr)); + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; } - else if (NPVARIANT_IS_INT32(member_ptr)) - { - printf("INT32: %d\n", NPVARIANT_TO_INT32(member_ptr)); - } - else if (NPVARIANT_IS_DOUBLE(member_ptr)) + + *jsObjectClassID += *(java_result->return_string); + + // We have the result. Free the request memory + delete java_request; + + java_request = new JavaRequestProcessor(); + + args = new 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_occured) { - printf("DOUBLE: %f\n", NPVARIANT_TO_DOUBLE(member_ptr)); + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; } - else if (NPVARIANT_IS_STRING(member_ptr)) + + *jsObjectConstructorID += *(java_result->return_string); + + delete args; + delete java_request; + + // We have the method id. Now create a new object. + + java_request = new JavaRequestProcessor(); + args = new std::vector<std::string>(); + args->push_back(*(member_data->return_string)); + java_result = java_request->newObject(*jsObjectClassID, + *jsObjectConstructorID, + *args); + + // the result we want is in result_string (assuming there was no error) + if (java_result->error_occured) { - printf("STRING: %s\n", NPVARIANT_TO_STRING(member_ptr).utf8characters); - } - else - { - printf("OBJ: %p\n", NPVARIANT_TO_OBJECT(member_ptr)); + printf("Unable to process getMember request. Error occurred: %s\n", java_result->error_msg); + //goto cleanup; } - member_ptr_str = IcedTeaPluginUtilities::JSIDToString(&member_ptr); response = IcedTeaPluginUtilities::constructMessagePrefix(0); - *response += " JavaScriptGetMember "; - *response += *member_ptr_str; + response->append(" JavaScriptGetMember "); + 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: + delete args; + delete java_request; // request object + delete member_id; // member id string + delete message_parts; // message_parts vector that was allocated by the caller + delete internal_request_params; // delete the internal requests params vector + delete jsObjectClassID; // delete object that holds the jsobject + delete member_data->return_string; + delete member_data; + + pthread_mutex_lock(&tc_mutex); + thread_count--; + pthread_mutex_unlock(&tc_mutex); +} + +void* +queue_processor(void* data) +{ + + PluginRequestProcessor* processor = (PluginRequestProcessor*) data; + std::vector<std::string>* message_parts = NULL; + std::string command; + + PLUGIN_DEBUG_1ARG("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) + { + PLUGIN_DEBUG_0ARG("Processing engaged\n"); + + command = message_parts->at(2); + + if (command == "GetMember") + { + processor->sendMember(message_parts); + } else if (command == "ToString") + { + processor->sendString(message_parts); + } else if (command == "SetMember") + { + processor->setMember(message_parts); + } else + { + // Nothing matched + IcedTeaPluginUtilities::printStringVector("Error: Unable to process message: ", message_parts); + + } + + PLUGIN_DEBUG_0ARG("Processing dis-engaged\n"); + } else + { + usleep(20000); + pthread_testcancel(); + } + + message_parts = NULL; + } + + PLUGIN_DEBUG_0ARG("Queue processing stopped.\n"); +} + +/****************************************** + * Functions delegated to the main thread * + ******************************************/ - plugin_to_java_bus->post(response->c_str()); +void* +_setMember(void* data, ResultData* result) +{ + std::string* property_name; + std::string* value; + std::string* type; + std::string* response; + std::vector<std::string*>* message_parts = (std::vector<std::string*>*) data; + + NPP instance; + NPVariant* value_variant = new NPVariant(); + NPObject* member; + NPIdentifier property; + + IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::_setMember - ", message_parts); + + member = reinterpret_cast <NPObject*> (IcedTeaPluginUtilities::stringToJSID(*(message_parts->at(0)))); + property_name = message_parts->at(1); + type = message_parts->at(2); + value = message_parts->at(3); + + instance = getInstanceFromMemberPtr(member); + convertToNPVariant(*value, *type, value_variant); + + PLUGIN_DEBUG_4ARG("Setting %s on instance %p, object %p to value %s\n", property_name->c_str(), instance, member, value_variant); + + property = browser_functions.getstringidentifier(property_name->c_str()); + browser_functions.setproperty(instance, member, property, value_variant); + + response = IcedTeaPluginUtilities::constructMessagePrefix(0); + response->append(" JavaScriptSetMember "); + plugin_to_java_bus->post(response->c_str()); + + // free memory + IcedTeaPluginUtilities::freeStringPtrVector(message_parts); + delete value_variant; + delete response; + + result->result_ready = true; + +} - delete member_ptr_str; - delete response; +void* +_getMember(void* data, ResultData* result) +{ + std::string* parent_ptr_str; + std::string* member_name; + + NPObject* parent_ptr; + NPVariant member_ptr; + std::string* member_ptr_str; + NPP instance; + NPIdentifier member_identifier; + + std::vector<std::string*>* message_parts = (std::vector<std::string*>*) data; + + IcedTeaPluginUtilities::printStringPtrVector("PluginRequestProcessor::_getMember - ", message_parts); + + parent_ptr_str = message_parts->at(0); + member_name = message_parts->at(1); + + // Get the corresponding windowId + member_identifier = browser_functions.getstringidentifier(member_name->c_str()); + + // Get the window pointer + parent_ptr = reinterpret_cast <NPObject*> (IcedTeaPluginUtilities::stringToJSID(parent_ptr_str->c_str())); + + // Get the associated instance + instance = getInstanceFromMemberPtr(parent_ptr); + + // Get the NPVariant corresponding to this member + PLUGIN_DEBUG_4ARG("Looking for %p %p %p (%s)\n", instance, parent_ptr, member_identifier,member_name->c_str()); + + if (!browser_functions.hasproperty(instance, parent_ptr, member_identifier)) + { + printf("%s not found!\n", member_name->c_str()); + } + browser_functions.getproperty(instance, parent_ptr, member_identifier, &member_ptr); + + IcedTeaPluginUtilities::printNPVariant(member_ptr); + member_ptr_str = IcedTeaPluginUtilities::JSIDToString(NPVARIANT_TO_OBJECT(member_ptr)); + PLUGIN_DEBUG_2ARG("Got variant %p (integer value = %s)\n", NPVARIANT_TO_OBJECT(member_ptr), member_ptr_str->c_str()); + + result->return_string = member_ptr_str; + result->result_ready = true; + + // store member -> instance link + storeInstanceID(NPVARIANT_TO_OBJECT(member_ptr), instance); + + PLUGIN_DEBUG_0ARG("_getMember returning.\n"); + + return result; }
--- a/plugin/icedteanp/IcedTeaPluginRequestProcessor.h Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaPluginRequestProcessor.h Thu Jul 23 11:39:18 2009 -0400 @@ -48,6 +48,7 @@ #include <npapi.h> #include <npupp.h> +#include "IcedTeaRunnable.h" #include "IcedTeaPluginUtils.h" #include "IcedTeaJavaRequestProcessor.h" @@ -61,22 +62,46 @@ std::string* source; } ThreadData; + /* Map holding window pointer<->instance relationships */ static std::map<void*, NPP>* instance_map; +/* Internal request reference counter */ +static long internal_req_ref_counter; + // JS request processor methods static NPP getInstanceFromMemberPtr(void* member_ptr); static void storeInstanceID(void* member_ptr, NPP instance); static void* requestFromMainThread(); -static void* sendMember(void* tdata); -static void* setMember(void* tdata); static void* getSlot(void* tdata); static void* setSlot(void* tdata); static void* eval(void* tdata); static void* removeMember(void* tdata); static void* call(void* tdata); static void* finalize(void* tdata); -static void* toString(void* tdata); + +/* Given a value and type, performs the appropriate Java->JS type + * mapping and puts it in the given variant */ + +static void convertToNPVariant(std::string value, std::string type, NPVariant* result_variant); + +// Internal methods that need to run in main thread +void* _getMember(void* message_parts, ResultData* result); +void* _setMember(void* message_parts, ResultData* result); + +static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER; +static int thread_count = 0; + +void* queue_processor(void* data); + +/* Mutex to ensure that the request queue is accessed synchronously */ +extern pthread_mutex_t message_queue_mutex; + +/* Mutex to ensure synchronized writes */ +extern pthread_mutex_t syn_write_mutex; + +/* Queue for holding messages that get processed in a separate thread */ +extern std::vector< std::vector<std::string>* >* message_queue; /** * Processes requests made TO the plugin (by java or anyone else) @@ -92,17 +117,23 @@ void dispatch(void* func_ptr (void*), std::vector<std::string>* message, std::string* src); /* Send main window pointer to Java */ - void sendWindow(std::vector<std::string>* message); - - /* Given parent id and member name, send member pointer to java */ - void _sendMember(std::vector<std::string*>* message_parts); + void sendWindow(std::vector<std::string>* message_parts); public: - PluginRequestProcessor(); /*Constructor */ + PluginRequestProcessor(); /* Constructor */ ~PluginRequestProcessor(); /* Destructor */ /* Process new requests (if applicable) */ virtual bool newMessageOnBus(const char* message); + + /* Send member ID to Java */ + void sendMember(std::vector<std::string>* message_parts); + + /* Set member to given value */ + void setMember(std::vector<std::string>* message_parts); + + /* Send string value of requested object */ + void sendString(std::vector<std::string>* message_parts); }; #endif // __ICEDTEAPLUGINREQUESTPROCESSOR_H__
--- a/plugin/icedteanp/IcedTeaPluginUtils.cc Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaPluginUtils.cc Thu Jul 23 11:39:18 2009 -0400 @@ -146,15 +146,17 @@ char* id_str = (char*) malloc(sizeof(char)*20); // max = long long = 8446744073709551615 == 19 chars if (sizeof(void*) == sizeof(long long)) + { sprintf(id_str, "%llu", id); - else if (sizeof(void*) == sizeof(long)) - sprintf(id_str, "%lu", id); - else // else addresses are int (32-bit) - sprintf(id_str, "%du", id); + } + else + { + sprintf(id_str, "%lu", id); // else use long + } *result += id_str; - printf("Converting pointer %p to %s\n", id, id_str); + PLUGIN_DEBUG_2ARG("Converting pointer %p to %s\n", id, id_str); free(id_str); return result; @@ -173,19 +175,15 @@ void* ptr; if (sizeof(void*) == sizeof(long long)) { - printf("Casting \"%s\" -- %llu\n", id_str.c_str(), atol(id_str.c_str())); - ptr = reinterpret_cast <void*> ((unsigned long) atol(id_str.c_str())); - } else if (sizeof(void*) == sizeof(long)) - { - printf("Casting \"%s\" -- %lu\n", id_str.c_str(), atoi(id_str.c_str())); - ptr = reinterpret_cast <void*> ((unsigned int) atoi(id_str.c_str())); + PLUGIN_DEBUG_2ARG("Casting (long long) \"%s\" -- %llu\n", id_str.c_str(), strtoull(id_str.c_str(), NULL, 0)); + ptr = reinterpret_cast <void*> ((unsigned long long) strtoull(id_str.c_str(), NULL, 0)); } else { - printf("Casting \"%s\" -- %du\n", id_str.c_str(), atoi(id_str.c_str())); - ptr = reinterpret_cast <void*> ((unsigned int) atoi(id_str.c_str())); + PLUGIN_DEBUG_2ARG("Casting (long) \"%s\" -- %lu\n", id_str.c_str(), strtoul(id_str.c_str(), NULL, 0)); + ptr = reinterpret_cast <void*> ((unsigned long) strtoul(id_str.c_str(), NULL, 0)); } - printf("Casted: %p\n", ptr); + PLUGIN_DEBUG_1ARG("Casted: %p\n", ptr); return ptr; } @@ -444,6 +442,119 @@ delete str; } +std::string* +IcedTeaPluginUtilities::variantToClassName(NPVariant variant) +{ + + std::string* java_type = new std::string(); + + if (NPVARIANT_IS_VOID(variant)) + { + *java_type += "V"; + } else if (NPVARIANT_IS_BOOLEAN(variant)) + { + *java_type += "Z"; + } else if (NPVARIANT_IS_INT32(variant)) + { + *java_type += "I"; + } else if (NPVARIANT_IS_DOUBLE(variant)) + { + *java_type += "D"; + } else if (NPVARIANT_IS_STRING(variant)) + { + *java_type += "Ljava/lang/String;"; + } else if (NPVARIANT_IS_OBJECT(variant)) + { + printf("** Unimplemented: IcedTeaPluginUtilities::variantToClassName(variant type=obj)\n"); + } else if (NPVARIANT_IS_NULL(variant)) + { + printf("** Unimplemented: IcedTeaPluginUtilities::variantToClassName(variant type=null)\n"); + } else + { + printf("** Unimplemented: IcedTeaPluginUtilities::variantToClassName(variant type=unknown)\n"); + } + + return java_type; +} + +void +IcedTeaPluginUtilities::printNPVariant(NPVariant variant) +{ + if (NPVARIANT_IS_VOID(variant)) + { + PLUGIN_DEBUG_1ARG("VOID %d\n", variant); + } + else if (NPVARIANT_IS_NULL(variant)) + { + PLUGIN_DEBUG_1ARG("NULL\n", variant); + } + else if (NPVARIANT_IS_BOOLEAN(variant)) + { + PLUGIN_DEBUG_1ARG("BOOL: %d\n", NPVARIANT_TO_BOOLEAN(variant)); + } + else if (NPVARIANT_IS_INT32(variant)) + { + PLUGIN_DEBUG_1ARG("INT32: %d\n", NPVARIANT_TO_INT32(variant)); + } + else if (NPVARIANT_IS_DOUBLE(variant)) + { + PLUGIN_DEBUG_1ARG("DOUBLE: %f\n", NPVARIANT_TO_DOUBLE(variant)); + } + else if (NPVARIANT_IS_STRING(variant)) + { + PLUGIN_DEBUG_1ARG("STRING: %s\n", NPVARIANT_TO_STRING(variant).utf8characters); + } + else + { + PLUGIN_DEBUG_1ARG("OBJ: %p\n", NPVARIANT_TO_OBJECT(variant)); + } +} + +std::string* +IcedTeaPluginUtilities::NPVariantToString(NPVariant variant) +{ + char* str = (char*) malloc(sizeof(char)*32); // enough for everything except string + + if (NPVARIANT_IS_VOID(variant)) + { + sprintf(str, "%p", variant); + } + else if (NPVARIANT_IS_NULL(variant)) + { + sprintf(str, "NULL"); + } + else if (NPVARIANT_IS_BOOLEAN(variant)) + { + if (NPVARIANT_TO_BOOLEAN(variant)) + sprintf(str, "true"); + else + sprintf(str, "false"); + } + else if (NPVARIANT_IS_INT32(variant)) + { + sprintf(str, "%d", NPVARIANT_TO_INT32(variant)); + } + else if (NPVARIANT_IS_DOUBLE(variant)) + { + sprintf(str, "%f", NPVARIANT_TO_DOUBLE(variant));; + } + else if (NPVARIANT_IS_STRING(variant)) + { + free(str); + str = (char*) malloc(sizeof(char)*NPVARIANT_TO_STRING(variant).utf8length); + sprintf(str, "%s", NPVARIANT_TO_STRING(variant).utf8characters); + } + else + { + sprintf(str, "[Object %p]", variant); + } + + std::string* ret = new std::string(str); + free(str); + + return ret; +} + /****************************************** * Begin JavaMessageSender implementation * ****************************************** @@ -506,6 +617,8 @@ MessageBus::~MessageBus() { + PLUGIN_DEBUG_0ARG("MessageBus::~MessageBus\n"); + int ret; ret = pthread_mutex_destroy(&subscriber_mutex);
--- a/plugin/icedteanp/IcedTeaPluginUtils.h Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/IcedTeaPluginUtils.h Thu Jul 23 11:39:18 2009 -0400 @@ -54,9 +54,6 @@ #include <string> #include <vector> -/* Debug output macros */ -static int plugin_debug = 1; - #define PLUGIN_DEBUG_0ARG(str) \ do \ { \ @@ -175,6 +172,12 @@ /* Prints contents of given string pointer vector */ static void printStringPtrVector(const char* prefix, std::vector<std::string*>* cv); + + static std::string* variantToClassName(NPVariant variant); + + static void printNPVariant(NPVariant variant); + + static std::string* NPVariantToString(NPVariant variant); }; /* @@ -225,11 +228,11 @@ /* Queued messages */ std::queue<char*> msgQueue; - ~MessageBus(); - public: MessageBus(); + ~MessageBus(); + /* subscribe to this bus */ void subscribe(BusSubscriber* b);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedteanp/IcedTeaRunnable.cc Thu Jul 23 11:39:18 2009 -0400 @@ -0,0 +1,74 @@ +/* IcedTeaRunnable.cc + + Copyright (C) 2009 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 <stdio.h> +#include "IcedTeaRunnable.h" + +NS_IMPL_ISUPPORTS1 (IcedTeaRunnable, nsIRunnable) + +IcedTeaRunnable::IcedTeaRunnable () +{ +} + +IcedTeaRunnable::~IcedTeaRunnable () +{ +} + +NS_IMETHODIMP +IcedTeaRunnable::Run () +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +IcedTeaRunnableMethod::IcedTeaRunnableMethod (Method method, void* thread_data, ResultData* result) +: method (method), + thread_data(thread_data), + result(result) +{ +} + +IcedTeaRunnableMethod::~IcedTeaRunnableMethod () +{ + } + +NS_IMETHODIMP +IcedTeaRunnableMethod::Run () +{ + (*method) (thread_data, result); + return NS_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/icedteanp/IcedTeaRunnable.h Thu Jul 23 11:39:18 2009 -0400 @@ -0,0 +1,102 @@ +/* IcedTeaRunnable.h + + Copyright (C) 2009 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. */ + +#ifndef __ICEDTEARUNNABLE_H__ +#define __ICEDTEARUNNABLE_H__ + +#define MOZILLA 1 +#if MOZILLA + +#include <nsIRunnable.h> +#include <string> + +/* + * This struct holds the result from the main-thread dispatched method + */ +typedef struct result_data +{ + // Return identifier (if applicable) + int return_identifier; + + // Return string (if applicable) + std::string* return_string; + + // Return wide/mb string (if applicable) + std::wstring* return_wstring; + + // Error message (if an error occurred) + std::string* error_msg; + + // Boolean indicating if an error occurred + bool error_occured; + + // If this result is ready + bool result_ready; + +} ResultData; + +class IcedTeaRunnable : public nsIRunnable +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + + IcedTeaRunnable (); + + ~IcedTeaRunnable (); +}; + +class IcedTeaRunnableMethod : public IcedTeaRunnable +{ +public: + + typedef void* (*Method) (void*, ResultData*); + + IcedTeaRunnableMethod (Method, void* thread_data, ResultData* result); + NS_IMETHOD Run (); + + ~IcedTeaRunnableMethod (); + + Method method; + void* thread_data; + ResultData* result; +}; + +#endif /* MOZILLA */ + +#endif /* __ICEDTEARUNNABLE_H__ */
--- a/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java Fri Jul 17 06:04:59 2009 -0400 +++ b/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java Thu Jul 23 11:39:18 2009 -0400 @@ -118,6 +118,8 @@ return "double"; case SIGNATURE_ENDFUNC: + return null; + case SIGNATURE_FUNC: return nextTypeName(); @@ -135,6 +137,10 @@ String elem; while (currentIndex < signature.length()) { elem = nextTypeName(); + + if (elem == null) // end of signature + continue; + // System.out.println ("NEXT TYPE: " + elem); Class primitive = primitiveNameToType(elem); if (primitive != null) @@ -169,7 +175,7 @@ } } } - if (typeList.size() == 0) { + if (signature.length() < 2) { throw new IllegalArgumentException("Invalid JNI signature '" + signature + "'"); } @@ -218,7 +224,7 @@ } public Class[] getClassArray() { - return typeList.subList(0, typeList.size() - 1).toArray(new Class[] {}); + return typeList.subList(0, typeList.size()).toArray(new Class[] {}); } } @@ -805,7 +811,25 @@ PluginDebug.debug("Java: GetStringChars: " + o); PluginDebug.debug(" String BYTES: " + buf); write(reference, "GetStringChars " + buf); - } else if (message.startsWith("NewArray")) { + } else if (message.startsWith("GetToStringValue")) { + String[] args = message.split(" "); + Integer objectID = parseCall(args[1], null, Integer.class); + + String o = null; + byte[] b = null; + StringBuffer buf = null; + o = store.getObject(objectID).toString(); + b = o.getBytes("UTF-8"); + buf = new StringBuffer(b.length * 2); + buf.append(b.length); + for (int i = 0; i < b.length; i++) + buf + .append(" " + + Integer + .toString(((int) b[i]) & 0x0ff, 16)); + + write(reference, "GetToStringValue " + buf); + } else if (message.startsWith("NewArray")) { String[] args = message.split(" "); String type = parseCall(args[1], null, String.class); Integer length = parseCall(args[2], null, Integer.class); @@ -879,53 +903,49 @@ write(reference, "NewObject " + store.getIdentifier(ret)); - } else if (message.startsWith("NewString")) { - PluginDebug.debug("MESSAGE: " + message); - String[] args = message.split(" "); - Integer strlength = parseCall(args[1], null, Integer.class); - int bytelength = 2 * strlength; - byte[] byteArray = new byte[bytelength]; - String ret = null; - for (int i = 0; i < strlength; i++) { - int c = parseCall(args[2 + i], null, Integer.class); - PluginDebug.debug("char " + i + " " + c); - // Low. - byteArray[2 * i] = (byte) (c & 0x0ff); - // High. - byteArray[2 * i + 1] = (byte) ((c >> 8) & 0x0ff); - } - ret = new String(byteArray, 0, bytelength, "UTF-16LE"); - PluginDebug.debug("NEWSTRING: " + ret); + } else if (message.startsWith("NewStringUTF")) { + PluginDebug.debug("MESSAGE: " + message); + String[] args = message.split(" "); + int length = new Integer(args[1]); + byte[] byteArray = new byte[length + 1]; + String ret = null; + int i = 2; + int c = Integer.parseInt(args[i++], 16); + while (i < length) { + byteArray[i-2] = (byte) c; + c = Integer.parseInt(args[i++], 16); + } + + byteArray[i] = (byte) 0; + ret = new String(byteArray, "UTF-8"); + PluginDebug.debug("NEWSTRINGUTF: " + ret); - // System.out.println ("NEWOBJ: CALLED: " + ret); - // System.out.println ("NEWOBJ: CALLED: " + - // store.getObject(ret)); - store.reference(ret); - write(reference, "NewString " + store.getIdentifier(ret)); - } else if (message.startsWith("NewStringUTF")) { - PluginDebug.debug("MESSAGE: " + message); - String[] args = message.split(" "); - byte[] byteArray = new byte[60]; - String ret = null; - int i = 0; - int c = 0; - while (((byte) c) != 0) { - c = parseCall(args[1 + i], null, Integer.class); - byteArray[i] = (byte) c; - i++; - if (i == byteArray.length) { - byte[] newByteArray = new byte[2 * byteArray.length]; - System.arraycopy(byteArray, 0, newByteArray, 0, - byteArray.length); - byteArray = newByteArray; - } - } - byteArray[i] = (byte) 0; - ret = new String(byteArray, "UTF-8"); - PluginDebug.debug("NEWSTRINGUTF: " + ret); + store.reference(ret); + write(reference, "NewStringUTF " + store.getIdentifier(ret)); + } else if (message.startsWith("NewString")) { + PluginDebug.debug("MESSAGE: " + message); + String[] args = message.split(" "); + Integer strlength = parseCall(args[1], null, Integer.class); + int bytelength = 2 * strlength; + byte[] byteArray = new byte[bytelength]; + String ret = null; + for (int i = 0; i < strlength; i++) { + int c = parseCall(args[2 + i], null, Integer.class); + PluginDebug.debug("char " + i + " " + c); + // Low. + byteArray[2 * i] = (byte) (c & 0x0ff); + // High. + byteArray[2 * i + 1] = (byte) ((c >> 8) & 0x0ff); + } + ret = new String(byteArray, 0, bytelength, "UTF-16LE"); + PluginDebug.debug("NEWSTRING: " + ret); - store.reference(ret); - write(reference, "NewStringUTF " + store.getIdentifier(ret)); + // System.out.println ("NEWOBJ: CALLED: " + ret); + // System.out.println ("NEWOBJ: CALLED: " + + // store.getObject(ret)); + store.reference(ret); + write(reference, "NewString " + store.getIdentifier(ret)); + } else if (message.startsWith("ExceptionOccurred")) { PluginDebug.debug("EXCEPTION: " + throwable); if (throwable != null) @@ -952,7 +972,12 @@ Integer id = parseCall(args[1], null, Integer.class); store.reference(store.getObject(id)); write(reference, "NewGlobalRef " + id); - } + } else if (message.startsWith("GetClassName")) { + String[] args = message.split(" "); + Integer objectID = parseCall(args[1], null, Integer.class); + Object o = (Object) store.getObject(objectID); + write(reference, "GetClassName " + o.getClass().getName()); + } } catch (Throwable t) { t.printStackTrace(); String msg = t.getCause() != null ? t.getCause().getMessage() : t.getMessage(); @@ -1018,8 +1043,8 @@ prepopulateClass("netscape/javascript/JSObject"); classID = prepopulateClass("netscape/javascript/JSException"); - prepopulateMethod(classID, "<init>", "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V"); - prepopulateMethod(classID, "<init>", "(ILjava/lang/Object;)V"); + prepopulateMethod(classID, "<init>", "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)"); + prepopulateMethod(classID, "<init>", "(ILjava/lang/Object;)"); prepopulateField(classID, "lineno"); prepopulateField(classID, "tokenIndex"); prepopulateField(classID, "source"); @@ -1028,51 +1053,51 @@ prepopulateField(classID, "wrappedException"); classID = prepopulateClass("netscape/javascript/JSUtil"); - prepopulateMethod(classID, "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;"); + prepopulateMethod(classID, "getStackTrace", "(Ljava/lang/Throwable;)"); prepopulateClass("java/lang/Object"); classID = prepopulateClass("java/lang/Class"); - prepopulateMethod(classID, "getMethods", "()[Ljava/lang/reflect/Method;"); - prepopulateMethod(classID, "getConstructors", "()[Ljava/lang/reflect/Constructor;"); - prepopulateMethod(classID, "getFields", "()[Ljava/lang/reflect/Field;"); - prepopulateMethod(classID, "getName", "()Ljava/lang/String;"); - prepopulateMethod(classID, "isArray", "()Z"); - prepopulateMethod(classID, "getComponentType", "()Ljava/lang/Class;"); - prepopulateMethod(classID, "getModifiers", "()I"); + prepopulateMethod(classID, "getMethods", "()"); + prepopulateMethod(classID, "getConstructors", "()"); + prepopulateMethod(classID, "getFields", "()"); + prepopulateMethod(classID, "getName", "()"); + prepopulateMethod(classID, "isArray", "()"); + prepopulateMethod(classID, "getComponentType", "()"); + prepopulateMethod(classID, "getModifiers", "()"); classID = prepopulateClass("java/lang/reflect/Method"); - prepopulateMethod(classID, "getName", "()Ljava/lang/String;"); - prepopulateMethod(classID, "getParameterTypes", "()[Ljava/lang/Class;"); - prepopulateMethod(classID, "getReturnType", "()Ljava/lang/Class;"); - prepopulateMethod(classID, "getModifiers", "()I"); + prepopulateMethod(classID, "getName", "()"); + prepopulateMethod(classID, "getParameterTypes", "()"); + prepopulateMethod(classID, "getReturnType", "()"); + prepopulateMethod(classID, "getModifiers", "()"); classID = prepopulateClass("java/lang/reflect/Constructor"); - prepopulateMethod(classID, "getParameterTypes", "()[Ljava/lang/Class;"); - prepopulateMethod(classID, "getModifiers", "()I"); + prepopulateMethod(classID, "getParameterTypes", "()"); + prepopulateMethod(classID, "getModifiers", "()"); classID = prepopulateClass("java/lang/reflect/Field"); - prepopulateMethod(classID, "getName", "()Ljava/lang/String;"); - prepopulateMethod(classID, "getType", "()Ljava/lang/Class;"); - prepopulateMethod(classID, "getModifiers", "()I"); + prepopulateMethod(classID, "getName", "()"); + prepopulateMethod(classID, "getType", "()"); + prepopulateMethod(classID, "getModifiers", "()"); classID = prepopulateClass("java/lang/reflect/Array"); - prepopulateMethod(classID, "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;"); + prepopulateMethod(classID, "newInstance", "(Ljava/lang/Class;I)"); classID = prepopulateClass("java/lang/Throwable"); - prepopulateMethod(classID, "toString", "()Ljava/lang/String;"); - prepopulateMethod(classID, "getMessage", "()Ljava/lang/String;"); + prepopulateMethod(classID, "toString", "()"); + prepopulateMethod(classID, "getMessage", "()"); classID = prepopulateClass("java/lang/System"); - prepopulateMethod(classID, "identityHashCode", "(Ljava/lang/Object;)I"); + prepopulateMethod(classID, "identityHashCode", "(Ljava/lang/Object;)"); classID = prepopulateClass("java/lang/Boolean"); - prepopulateMethod(classID, "booleanValue", "()D"); - prepopulateMethod(classID, "<init>", "(Z)V"); + prepopulateMethod(classID, "booleanValue", "()"); + prepopulateMethod(classID, "<init>", "(Z)"); classID = prepopulateClass("java/lang/Double"); - prepopulateMethod(classID, "doubleValue", "()D"); - prepopulateMethod(classID, "<init>", "(D)V"); + prepopulateMethod(classID, "doubleValue", "()"); + prepopulateMethod(classID, "<init>", "(D)"); classID = prepopulateClass("java/lang/Void"); prepopulateField(classID, "TYPE");