changeset 1997:c1c108662db8

This commit: - Reworks memory allocation to make it less leaky by using heap as little as possible. - Implements JSObject.call and JSObject.eval which allow invocation of JavaScript methods, and execution of arbitrary scripts. Everything except for array types is currently handled. - Fixes a few new race conditions that surfaced as result of less messages/faster initialization. - Starts laying out call security. - Fixes unicode handling so that UTF-8 is used correctly across the board. Most prominently, new sites that now work include: - Facebook photo uploader - Yahoo! games applets - A whole bunch of banking applets
author Deepak Bhole <dbhole@redhat.com>
date Fri, 14 Aug 2009 15:58:23 -0400
parents dfd69fa0c812
children e0f4520ae470
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/IcedTeaScriptablePluginObject.cc plugin/icedteanp/java/netscape/javascript/JSObject.java plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java plugin/icedteanp/java/sun/applet/PluginAppletViewer.java plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java
diffstat 18 files changed, 1275 insertions(+), 590 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Aug 06 10:43:31 2009 -0400
+++ b/ChangeLog	Fri Aug 14 15:58:23 2009 -0400
@@ -1,3 +1,114 @@
+2009-08-14	Deepak Bhole <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
+	(newMessageOnBus): Handle additional request types.
+	(postAndWaitForResponse): Modify parameter type and reset the result
+	before proceeding.
+	(getToStringValue): Remove all heap allocations and allocate on stack.
+	(getString): Same.
+	(deleteReference): Same.
+	(addReference): Same.
+	(findClass): Same.
+	(getClassName): Same.
+	(getClassID): Same.
+	(getFieldID): Same.
+	(getStaticFieldID): Same.
+	(getField): Same. Also, send the source to Java side.
+	(getStaticField): Same.
+	(getMethodID): Remove all heap allocations and allocate on stack.
+	(getStaticMethodID): Same.
+	(callStaticMethod): Same. Also, send the source to Java side.
+	(callMethod): Same.
+	(call): Same.
+	(getObjectClass): Remove all heap allocations and allocate on stack.
+	(newObject): Same. Also, send the source to Java side.
+	(newString): Remove all heap allocations and allocate on stack.
+	(hasPackage): Same.
+	(hasMethod): Same.
+	(hasField): Same.
+	(isInstanceOf): New method.
+	(getAppletObjectInstance): Remove all heap allocations and allocate on
+	stack.
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.h: Bump timeout to 120 to
+	allow for slower connections. Other misc. changes related to the .cc file
+	changes.
+	* plugin/icedteanp/IcedTeaNPPlugin.cc: Moved GCJPluginData decleration to
+	the header file. Don't initialize message bus and request processors 
+	statically.
+	(GCJ_New): Initialize the buses and processors. Store source url in plugin
+	data struct.
+	(GCJ_Destroy): Cleanup source url pointer.
+	* plugin/icedteanp/IcedTeaNPPlugin.h: Moved GCJPluginData struct
+	decleration to here.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc
+	(getInstanceFromMemberPtr): Moved to plugin utils.
+	(storeInstanceID): Same.
+	(newMessageOnBus): Handle additional request types.
+	(dispatch): Remove unused method.
+	(sendWindow): Remove unnecessary heap allocations and use function stack
+	instead.
+	(eval): New function. Evaluates calls to JavaScript functions and returns
+	the result. Arrays are not yet handled.
+	(call): New function. Evaluates the given script and returns the result.
+	Arrays are not yet handled.
+	(sendString): Remove unnecessary heap allocations and use function stack
+	instead.
+	(setMember): Same.
+	(convertToNPVariant): New function. Narrows given java type to an
+	NPVariant as per type conversion specifications.
+	(sendMember): Remove unnecessary heap allocations and use function stack 
+    instead.
+	(storeVariantInJava): New function. Given an NPVariant, does the
+	appropriate conversion and saves it on the Java side. Arrays are not yet
+	handled.
+	(_eval): New function. Evaluates the script via NPN_Evaluate. Meant to be
+	run in the main thread.
+	(_call): New function. Invokes the function via NPN_Invoke. Meant to be run 
+	in the main thread.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.h: Appropriate changes as
+	necessitated by the above changes in the .cc.
+	* plugin/icedteanp/IcedTeaPluginUtils.cc
+	(constructMessagePrefix): All versions of this functions changed to remove
+	heap allocation, and instead store result in a given pre-allocated parameter.
+	(getReference): Use an ever growing reference number, and cycle when
+	integer max approaches.
+	(releaseReference): Remove code so nothing is done for now.
+	(itoa): Store result in pre-allocated parameter, rather than on heap.
+	(getSourceFromInstance): Given an NPP instance, returns the assocated
+	source.
+	(storeInstanceID): Moved from IcedTeaPluginRequestProcessor. Associates an
+	NPObject with an instance.
+	(getInstanceFromMemberPtr): Moved from IcedTeaPluginRequestProcessor.
+	Given an NPObject, returns the associated instance.
+	(variantToClassName): Remove unused method.
+	* plugin/icedteanp/IcedTeaPluginUtils.h: Appropriate changes as necessitated 
+	by the above changes in the .cc.
+	* plugin/icedteanp/IcedTeaRunnable.cc (IcedTeaRunnableMethod):  Change
+	result parameter type to void* so that caller/callee can use variable
+	formats.
+	* plugin/icedteanp/IcedTeaRunnable.h: Appropriate changes as necessitated
+	by the above changes in the .cc.
+	* plugin/icedteanp/IcedTeaScriptablePluginObject.cc: Call storeInstanceID
+	and getInstanceFromMemberPtr from plugin utils.
+	(IcedTeaScriptableJavaObject::getProperty): Get the source url and send it to
+	Java side when making the request.
+	(IcedTeaScriptableJavaObject::invoke): Same.
+	* plugin/icedteanp/java/netscape/javascript/JSObject.java: Merge
+	constructor access control fixes from older plugin.
+	* plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java: Handle
+	void and null return types.
+	* plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java: Add an
+	additional test case for Boolean.
+	(getPrimitive): Handle java.lang.Boolean (minor bug fix).
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java: Use
+	URLs when comparing source locations for security verification, rather
+	than String which return false negatives.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(handleMessage): Set status to ACTIVE only after initialization finishes.
+	(AppletEventListener::appletStateChanged): Same.
+	* plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java
+	(parseReturn): Handle improper cookies from firefox.
+
 2009-08-06  Deepak Bhole  <dbhole@redhat.com>
 
 	* plugin/icedteanp/IcedTeaJavaRequestProcessor.cc: Handle error messages
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc	Fri Aug 14 15:58:23 2009 -0400
@@ -111,7 +111,8 @@
                     (message_parts->at(4) == "GetFieldID") ||
                     (message_parts->at(4) == "GetField") ||
                     (message_parts->at(4) == "GetStaticField") ||
-                    (message_parts->at(4) == "GetJavaObject"))
+                    (message_parts->at(4) == "GetJavaObject") ||
+                    (message_parts->at(4) == "IsInstanceOf"))
 			{
 				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
@@ -159,6 +160,8 @@
 
 JavaRequestProcessor::JavaRequestProcessor()
 {
+    PLUGIN_DEBUG_0ARG("JavaRequestProcessor constructor\n");
+
 	// caller frees this
 	result = new JavaResultData();
 	result->error_msg = new std::string();
@@ -212,15 +215,17 @@
 }
 
 void
-JavaRequestProcessor::postAndWaitForResponse(std::string* message)
+JavaRequestProcessor::postAndWaitForResponse(std::string message)
 {
     struct timespec t;
     clock_gettime(CLOCK_REALTIME, &t);
     t.tv_sec += REQUESTTIMEOUT; // 1 minute timeout
 
-    result_ready = false;
+    // Clear the result
+    resetResult();
+
     java_to_plugin_bus->subscribe(this);
-    plugin_to_java_bus->post(message->c_str());
+    plugin_to_java_bus->post(message.c_str());
 
     // Wait for result to be filled in.
 	struct timespec curr_t;
@@ -247,7 +252,7 @@
     	result->error_msg->append("Error: Timed out when waiting for response");
 
     	// Report error
-    	PLUGIN_DEBUG_1ARG("Error: Timed out when waiting for response to %s\n", message->c_str());
+    	PLUGIN_DEBUG_1ARG("Error: Timed out when waiting for response to %s\n", message.c_str());
     }
 
     java_to_plugin_bus->unSubscribe(this);
@@ -263,20 +268,19 @@
 JavaResultData*
 JavaRequestProcessor::getToStringValue(std::string object_id)
 {
-	std::string* message;
+	std::string message = std::string();
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
 
-	message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" GetToStringValue "); // get it in UTF8
-    message->append(object_id);
+    message.append(" GetToStringValue "); // get it in UTF8
+    message.append(object_id);
 
     postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
-    delete message;
 
 	return result;
 }
@@ -291,20 +295,19 @@
 JavaResultData*
 JavaRequestProcessor::getString(std::string string_id)
 {
-	std::string* message;
+    std::string message = std::string();
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
 
-	message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" GetStringUTFChars "); // get it in UTF8
-    message->append(string_id);
+    message.append(" GetStringUTFChars "); // get it in UTF8
+    message.append(string_id);
 
     postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
-    delete message;
 
 	return result;
 }
@@ -318,20 +321,19 @@
 void
 JavaRequestProcessor::deleteReference(std::string object_id)
 {
-    std::string* message;
+    std::string message = std::string();
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" DeleteLocalRef ");
-    message->append(object_id);
+    message.append(" DeleteLocalRef ");
+    message.append(object_id);
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
-    delete message;
 }
 
 /**
@@ -343,80 +345,73 @@
 void
 JavaRequestProcessor::addReference(std::string object_id)
 {
-    std::string* message;
+    std::string message = std::string();
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" NewGlobalRef ");
-    message->append(object_id);
+    message.append(" NewGlobalRef ");
+    message.append(object_id);
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
-    delete message;
 
 }
 
 JavaResultData*
 JavaRequestProcessor::findClass(std::string name)
 {
-	std::string* message;
+    std::string message = std::string();
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
 
-	message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" FindClass ");
-    message->append(name);
+    message.append(" FindClass ");
+    message.append(name);
 
     postAndWaitForResponse(message);
 
-    delete message;
-
 	return result;
 }
 
 JavaResultData*
 JavaRequestProcessor::getClassName(std::string objectID)
 {
-	std::string* message;
+    std::string message = std::string();
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
 
-	message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" GetClassName ");
-    message->append(objectID);
+    message.append(" GetClassName ");
+    message.append(objectID);
 
     postAndWaitForResponse(message);
 
-    delete message;
-
 	return result;
 }
 
 JavaResultData*
 JavaRequestProcessor::getClassID(std::string objectID)
 {
-    std::string* message;
+    std::string message = std::string();
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
-    message->append(" GetClassID ");
-    message->append(objectID);
+    message.append(" GetClassID ");
+    message.append(objectID);
 
     postAndWaitForResponse(message);
 
-    delete message;
-
     return result;
 }
 
@@ -425,25 +420,24 @@
 {
 	JavaResultData* java_result;
 	JavaRequestProcessor* java_request = new JavaRequestProcessor();
-	std::string* message;
+	std::string message = std::string();
 
 	java_result = java_request->newString(fieldName);
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
 
-	message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-	message->append(" GetFieldID ");
-	message->append(classID);
-	message->append(" ");
-	message->append(java_result->return_string->c_str());
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message.append(" GetFieldID ");
+	message.append(classID);
+	message.append(" ");
+	message.append(java_result->return_string->c_str());
 
 	postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
 
 	delete java_request;
-	delete message;
 
 	return result;
 }
@@ -453,81 +447,81 @@
 {
     JavaResultData* java_result;
     JavaRequestProcessor* java_request = new JavaRequestProcessor();
-    std::string* message;
+    std::string message = std::string();
 
     java_result = java_request->newString(fieldName);
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    message->append(" GetStaticFieldID ");
-    message->append(classID);
-    message->append(" ");
-    message->append(java_result->return_string->c_str());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" GetStaticFieldID ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
 
     delete java_request;
-    delete message;
 
     return result;
 }
 
 JavaResultData*
-JavaRequestProcessor::getField(std::string classID, std::string fieldName)
+JavaRequestProcessor::getField(std::string source,
+                               std::string classID,
+                               std::string fieldName)
 {
     JavaResultData* java_result;
     JavaRequestProcessor* java_request = new JavaRequestProcessor();
-    std::string* message;
+    std::string message = std::string();
 
     java_result = java_request->getFieldID(classID, fieldName);
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    message->append(" GetField ");
-    message->append(classID);
-    message->append(" ");
-    message->append(java_result->return_string->c_str());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+    message.append(" GetField ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
 
     delete java_request;
-    delete message;
 
     return result;
 }
 
 JavaResultData*
-JavaRequestProcessor::getStaticField(std::string classID, std::string fieldName)
+JavaRequestProcessor::getStaticField(std::string classID, std::string source,
+                                     std::string fieldName)
 {
     JavaResultData* java_result;
     JavaRequestProcessor* java_request = new JavaRequestProcessor();
-    std::string* message;
+    std::string message = std::string();
 
     java_result = java_request->getStaticFieldID(classID, fieldName);
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    message->append(" GetStaticField ");
-    message->append(classID);
-    message->append(" ");
-    message->append(java_result->return_string->c_str());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+    message.append(" GetStaticField ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
 
     delete java_request;
-    delete message;
 
     return result;
 }
@@ -537,7 +531,7 @@
                                   std::vector<std::string> args)
 {
 	JavaRequestProcessor* java_request;
-	std::string* message;
+	std::string message = std::string();
     std::string* signature;
 
     signature = new std::string();
@@ -554,19 +548,18 @@
 	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 += classID;
-	*message += " ";
-	*message += browser_functions.utf8fromidentifier(methodName);
-	*message += " ";
-	*message += *signature;
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message += " GetMethodID ";
+	message += classID;
+	message += " ";
+	message += browser_functions.utf8fromidentifier(methodName);
+	message += " ";
+	message += *signature;
 
 	postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
 	delete signature;
-	delete message;
 
 	return result;
 }
@@ -576,7 +569,7 @@
                                   std::vector<std::string> args)
 {
     JavaRequestProcessor* java_request;
-    std::string* message;
+    std::string message = std::string();
     std::string* signature;
 
     signature = new std::string();
@@ -593,19 +586,18 @@
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    *message += " GetStaticMethodID ";
-    *message += classID;
-    *message += " ";
-    *message += browser_functions.utf8fromidentifier(methodName);
-    *message += " ";
-    *message += *signature;
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message += " GetStaticMethodID ";
+    message += classID;
+    message += " ";
+    message += browser_functions.utf8fromidentifier(methodName);
+    message += " ";
+    message += *signature;
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
     delete signature;
-    delete message;
 
     return result;
 }
@@ -697,7 +689,8 @@
 		jsObjectConstructorID.append(*(java_result->return_string));
 		java_request.resetResult();
 
-		// We have class id and constructor ID. So we know we can create the object.. now create the string
+		// We have class id and constructor ID. So we know we can create the
+		// object.. now create the string that will be provided as the arg
 		java_result = java_request.newString(stringArg);
 
 		if (java_result->error_occurred) {
@@ -705,6 +698,19 @@
 			return 0;
 		}
 
+		// Create the object
+		args.clear();
+		std::string arg = std::string();
+		arg.append(*(java_result->return_string));
+		args.push_back(arg);
+		java_result = java_request.newObject("[System]", jsObjectClassID, jsObjectConstructorID, args);
+
+        if (java_result->error_occurred) {
+            printf("Unable to create requested object\n");
+            return 0;
+        }
+
+
 		return java_result->return_identifier;
 
 	}
@@ -719,39 +725,43 @@
 }
 
 JavaResultData*
-JavaRequestProcessor::callStaticMethod(std::string classID, std::string methodName,
-									   const NPVariant* args, int numArgs)
+JavaRequestProcessor::callStaticMethod(std::string source, std::string classID,
+                                       std::string methodName,
+                                       const NPVariant* args,
+                                       int numArgs)
 {
-    return call(true, classID, methodName, args, numArgs);
+    return call(source, true, classID, methodName, args, numArgs);
 }
 
 JavaResultData*
-JavaRequestProcessor::callMethod(std::string objectID, std::string methodName,
-                                       const NPVariant* args, int numArgs)
+JavaRequestProcessor::callMethod(std::string source,
+                                 std::string objectID, std::string methodName,
+                                 const NPVariant* args, int numArgs)
 {
-    return call(false, objectID, methodName, args, numArgs);
+    return call(source, false, objectID, methodName, args, numArgs);
 }
 
 JavaResultData*
-JavaRequestProcessor::call(bool isStatic, std::string objectID,
+JavaRequestProcessor::call(std::string source,
+                           bool isStatic, std::string objectID,
                            std::string methodName,
                            const NPVariant* args, int numArgs)
 {
-	std::string* message;
+    std::string message = std::string();
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
 
     if (isStatic)
-        *message += " CallStaticMethod ";
+        message += " CallStaticMethod ";
     else
-        *message += " CallMethod ";
+        message += " CallMethod ";
 
-    *message += objectID;
-    *message += " ";
-    *message += methodName;
-    *message += " ";
+    message += objectID;
+    message += " ";
+    message += methodName;
+    message += " ";
 
 	// First, we need to load the arguments into the java-side table
 	for (int i=0; i < numArgs; i++) {
@@ -760,21 +770,19 @@
 		{
 			result->error_occurred = true;
 			result->error_msg->append("Unable to create arguments");
-			delete message;
 			return result;
 		}
 
 		char* id = (char*) malloc(sizeof(char)*32);
 		sprintf(id, "%d", objectID);
-		*message += id;
-		*message += " ";
+		message += id;
+		message += " ";
 		free(id);
 	}
 
 	postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
-    delete message;
 
     return result;
 }
@@ -783,50 +791,49 @@
 JavaRequestProcessor::getObjectClass(std::string objectID)
 {
     JavaRequestProcessor* java_request;
-    std::string* message;
+    std::string message = std::string();
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    *message += " GetObjectClass ";
-    *message += objectID;
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message += " GetObjectClass ";
+    message += objectID;
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
-    delete message;
 
     return result;
 }
 
 JavaResultData*
-JavaRequestProcessor::newObject(std::string objectID, std::string methodID,
-                                  std::vector<std::string> args)
+JavaRequestProcessor::newObject(std::string source, std::string objectID,
+                                std::string methodID,
+                                std::vector<std::string> args)
 {
 	JavaRequestProcessor* java_request;
-	std::string* message;
+	std::string message = std::string();
 
 	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 += " ";
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+	message += " NewObject ";
+	message += objectID;
+	message += " ";
+	message += methodID;
+	message += " ";
 
 	for (int i=0; i < args.size(); i++)
 	{
-		*message += args[i];
-		*message += " ";
+		message += args[i];
+		message += " ";
 	}
 
 	postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
-	delete message;
 
 	return result;
 }
@@ -835,21 +842,20 @@
 JavaRequestProcessor::newString(std::string str)
 {
 	std::string utf_string = std::string();
-	std::string* message;
+	std::string message = std::string();
 
 	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);
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message.append(" NewStringUTF ");
+	message.append(utf_string);
 
 	postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
-	delete message;
 
 	return result;
 }
@@ -859,23 +865,22 @@
 {
 	JavaResultData* java_result;
 	JavaRequestProcessor* java_request = new JavaRequestProcessor();
-	std::string* message;
+	std::string message = std::string();
 
 	java_result = java_request->newString(package_name);
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
 
-	message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-	message->append(" HasPackage ");
-	message->append(java_result->return_string->c_str());
+	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+	message.append(" HasPackage ");
+	message.append(java_result->return_string->c_str());
 
 	postAndWaitForResponse(message);
 
 	IcedTeaPluginUtilities::releaseReference();
 
 	delete java_request;
-	delete message;
 
 	return result;
 }
@@ -885,25 +890,24 @@
 {
     JavaResultData* java_result;
     JavaRequestProcessor* java_request = new JavaRequestProcessor();
-    std::string* message;
+    std::string message = std::string();
 
     java_result = java_request->newString(method_name);
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    message->append(" HasMethod ");
-    message->append(classID);
-    message->append(" ");
-    message->append(java_result->return_string->c_str());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" HasMethod ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
 
     delete java_request;
-    delete message;
 
     return result;
 }
@@ -912,26 +916,44 @@
 JavaRequestProcessor::hasField(std::string classID, std::string method_name)
 {
     JavaResultData* java_result;
-    JavaRequestProcessor* java_request = new JavaRequestProcessor();
-    std::string* message;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    std::string message = std::string();
 
-    java_result = java_request->newString(method_name);
+    java_result = java_request.newString(method_name);
 
     this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
     this->reference = IcedTeaPluginUtilities::getReference();
 
-    message = IcedTeaPluginUtilities::constructMessagePrefix(0, reference);
-    message->append(" HasField ");
-    message->append(classID);
-    message->append(" ");
-    message->append(java_result->return_string->c_str());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" HasField ");
+    message.append(classID);
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
 
     postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
 
-    delete java_request;
-    delete message;
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::isInstanceOf(std::string objectID, std::string classID)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+    message.append(" IsInstanceOf ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(classID);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
 
     return result;
 }
@@ -940,10 +962,11 @@
 JavaRequestProcessor::getAppletObjectInstance(std::string instanceID)
 {
     std::string message = std::string();
-    char* ref_str;
+    std::string ref_str = std::string();
 
+    this->instance = 0;
     this->reference = IcedTeaPluginUtilities::getReference();
-    ref_str = IcedTeaPluginUtilities::itoa(reference);
+    IcedTeaPluginUtilities::itoa(reference, &ref_str);
 
     message = "instance ";
     message += instanceID;
@@ -951,7 +974,7 @@
     message += ref_str;
     message += " GetJavaObject";
 
-    postAndWaitForResponse(&message);
+    postAndWaitForResponse(message);
 
     IcedTeaPluginUtilities::releaseReference();
 
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.h	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.h	Fri Aug 14 15:58:23 2009 -0400
@@ -47,7 +47,7 @@
 #include "IcedTeaPluginUtils.h"
 #include "IcedTeaScriptablePluginObject.h"
 
-#define REQUESTTIMEOUT 20
+#define REQUESTTIMEOUT 120
 
 /*
  * This struct holds data specific to a Java operation requested by the plugin
@@ -102,24 +102,24 @@
     	JavaResultData* result;
 
     	/* Post message on bus and wait */
-    	void postAndWaitForResponse(std::string* message);
+    	void postAndWaitForResponse(std::string message);
 
     	/* Creates a argument on java-side with appropriate type */
     	int createJavaObjectFromVariant(NPVariant variant);
 
     	// Call a method, static or otherwise, depending on supplied arg
-        JavaResultData* call(bool isStatic, std::string objectID,
-                             std::string methodName, const NPVariant* args,
-                             int numArgs);
+        JavaResultData* call(std::string source, bool isStatic,
+                             std::string objectID, std::string methodName,
+                             const NPVariant* args, int numArgs);
+
+        /* Resets the results */
+        void resetResult();
 
     public:
     	JavaRequestProcessor();
     	~JavaRequestProcessor();
     	virtual bool newMessageOnBus(const char* message);
 
-    	/* Resets the results */
-    	void resetResult();
-
     	/* Increments reference count by 1 */
     	void addReference(std::string object_id);
 
@@ -132,15 +132,15 @@
     	/* 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 field object */
-        JavaResultData* getField(std::string classID, std::string fieldName);
+        JavaResultData* getField(std::string source,
+                                 std::string classID,
+                                 std::string fieldName);
 
         /* Returns the static field object */
-        JavaResultData* getStaticField(std::string classID, std::string fieldName);
+        JavaResultData* getStaticField(std::string source,
+                                       std::string classID,
+                                       std::string fieldName);
 
         /* Returns the field id */
         JavaResultData* getFieldID(std::string classID, std::string fieldName);
@@ -157,19 +157,24 @@
                                      std::vector<std::string> args);
 
         /* Calls a static method */
-        JavaResultData* callStaticMethod(std::string classID, std::string methodName,
+        JavaResultData* callStaticMethod(std::string source,
+                                         std::string classID,
+                                         std::string methodName,
                                          const NPVariant* args, int numArgs);
 
         /* Calls a method on an instance */
-        JavaResultData* callMethod(std::string objectID, std::string methodName,
+        JavaResultData* callMethod(std::string source,
+                                   std::string objectID,
+                                   std::string methodName,
 								   const NPVariant* args, int numArgs);
 
         /* Returns the class of the given object */
         JavaResultData* getObjectClass(std::string objectID);
 
     	/* Creates a new object */
-    	JavaResultData* newObject(std::string objectID, std::string methodID,
-                                    std::vector<std::string> args);
+    	JavaResultData* newObject(std::string source,
+                                  std::string objectID, std::string methodID,
+                                  std::vector<std::string> args);
 
     	/* Returns the class ID */
     	JavaResultData* findClass(std::string name);
@@ -192,6 +197,9 @@
         /* Check if field exists */
         JavaResultData* hasField(std::string classID, std::string method_name);
 
+        /* Check if given object is instance of given class */
+        JavaResultData* isInstanceOf(std::string objectID, std::string classID);
+
         /* Returns the instance ID of the java applet */
         JavaResultData* getAppletObjectInstance(std::string instanceID);
 };
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaNPPlugin.cc	Fri Aug 14 15:58:23 2009 -0400
@@ -170,41 +170,18 @@
 NPNetscapeFuncs browser_functions;
 
 // 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* plugin_to_java_bus;
+MessageBus* java_to_plugin_bus;
 //MessageBus* internal_bus = new MessageBus();
 
 // Processor for plugin requests
-PluginRequestProcessor* plugin_req_proc = new PluginRequestProcessor();
+PluginRequestProcessor* plugin_req_proc;
 
 // Sends messages to Java over the bus
-JavaMessageSender* java_req_proc = new JavaMessageSender();
+JavaMessageSender* java_req_proc;
 
 GQuark ITNP_PLUGIN_ERROR = g_quark_from_string("IcedTeaNPPlugin");
 
-// GCJPluginData stores all the data associated with a single plugin
-// instance.  A separate plugin instance is created for each <APPLET>
-// tag.  For now, each plugin instance spawns its own applet viewer
-// process but this may need to change if we find pages containing
-// multiple applets that expect to be running in the same VM.
-struct GCJPluginData
-{
-  // A unique identifier for this plugin window.
-  gchar* instance_string;
-  // Mutex to protect appletviewer_alive.
-  GMutex* appletviewer_mutex;
-  // Back-pointer to the plugin instance to which this data belongs.
-  // This should not be freed but instead simply set to NULL.
-  NPP owner;
-  // The address of the plugin window.  This should not be freed but
-  // instead simply set to NULL.
-  gpointer window_handle;
-  // The last plugin window width sent to us by the browser.
-  guint32 window_width;
-  // The last plugin window height sent to us by the browser.
-  guint32 window_height;
-};
-
 // Documentbase retrieval type-punning union.
 typedef union
 {
@@ -375,6 +352,10 @@
   // Set back-pointer to owner instance.
   data->owner = instance;
 
+  // source of this instance
+  // don't use documentbase, it is cleared later
+  data->source = plugin_get_documentbase(instance);
+
   instance->pdata = data;
 
   goto cleanup_done;
@@ -1715,6 +1696,9 @@
   g_free (tofree->instance_string);
   tofree->instance_string = NULL;
 
+  g_free(tofree->source);
+  tofree->source = NULL;
+
   // cleanup_data:
   // Eliminate back-pointer to plugin instance.
   tofree->owner = NULL;
@@ -1907,10 +1891,14 @@
 
   PLUGIN_DEBUG_0ARG ("NP_Initialize return\n");
 
+  plugin_req_proc = new PluginRequestProcessor();
+  java_req_proc = new JavaMessageSender();
+
+  java_to_plugin_bus = new MessageBus();
+  plugin_to_java_bus = new MessageBus();
+
   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);
@@ -2114,7 +2102,6 @@
 
         instance_id.append(*(java_result->return_string));
 
-        java_request.resetResult();
         java_result = java_request.getClassID(instance_id);
 
         if (java_result->error_occurred)
--- a/plugin/icedteanp/IcedTeaNPPlugin.h	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaNPPlugin.h	Fri Aug 14 15:58:23 2009 -0400
@@ -54,6 +54,31 @@
 #include "IcedTeaPluginUtils.h"
 #include "IcedTeaPluginRequestProcessor.h"
 
+// GCJPluginData stores all the data associated with a single plugin
+// instance.  A separate plugin instance is created for each <APPLET>
+// tag.  For now, each plugin instance spawns its own applet viewer
+// process but this may need to change if we find pages containing
+// multiple applets that expect to be running in the same VM.
+struct GCJPluginData
+{
+  // A unique identifier for this plugin window.
+  gchar* instance_string;
+  // Mutex to protect appletviewer_alive.
+  GMutex* appletviewer_mutex;
+  // Back-pointer to the plugin instance to which this data belongs.
+  // This should not be freed but instead simply set to NULL.
+  NPP owner;
+  // The address of the plugin window.  This should not be freed but
+  // instead simply set to NULL.
+  gpointer window_handle;
+  // The last plugin window width sent to us by the browser.
+  guint32 window_width;
+  // The last plugin window height sent to us by the browser.
+  guint32 window_height;
+  // The source location for this instance
+  gchar* source;
+};
+
 // Queue processing threads
 static pthread_t plugin_request_processor_thread1;
 static pthread_t plugin_request_processor_thread2;
--- a/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc	Fri Aug 14 15:58:23 2009 -0400
@@ -36,6 +36,8 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
+#include <typeinfo>
+
 #include "IcedTeaNPPlugin.h"
 #include "IcedTeaPluginRequestProcessor.h"
 
@@ -50,45 +52,6 @@
 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
- *
- * @param member_ptr The pointer key
- * @return The associated instance
- */
-
-NPP
-getInstanceFromMemberPtr(void* 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);
-
-    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;
-}
-
-/**
- * Stores a window pointer <-> instance mapping
- *
- * @param member_ptr The pointer key
- * @param instance The instance to associate with this pointer
- */
-
-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));
-}
-
-/**
  * PluginRequestProcessor constructor.
  *
  * Initializes various complex data structures used by the class.
@@ -97,7 +60,6 @@
 PluginRequestProcessor::PluginRequestProcessor()
 {
     this->pendingRequests = new std::map<pthread_t, uintmax_t>();
-    instance_map = new std::map<void*, NPP>();
 
     internal_req_ref_counter = 0;
 }
@@ -114,10 +76,6 @@
 
     if (pendingRequests)
         delete pendingRequests;
-
-    if (instance_map)
-        delete instance_map;
-
 }
 
 /**
@@ -156,7 +114,9 @@
             return true;
         } else if (command == "GetMember" ||
                    command == "SetMember" ||
-                   command == "ToString")
+                   command == "ToString"  ||
+                   command == "Call"      ||
+                   command == "Eval")
         {
 
         	// Update queue synchronously
@@ -179,44 +139,6 @@
 }
 
 /**
- * Delegates further processing to a new thread.
- *
- * @param func_ptr Pointer to the function to delegate this request to
- * @param message_parts The full message, as a vector of strings
- * @param src The source URL of the request (may be NULL)
- *
- * The functions called by dispatch() are started in a new thread, and provided
- * a "ThreadData" struct. Since timings are not guaranteed, the struct is
- * allocated on the heap and it is upto the called functions to free the
- * associated memory when it is safe to do so.
- */
-
-void PluginRequestProcessor::dispatch(void* func_ptr (void*), std::vector<std::string>* message_parts, std::string* src)
-{
-    pthread_t thread;
-    int tries = 0;
-    ThreadData* tdata = new ThreadData();
-
-    IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::dispatch:", 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);
-
-    PLUGIN_DEBUG_2ARG("pthread %p created. Thread count=%d\n", thread, thread_count);
-}
-
-/**
  * Sends the window pointer to the Java side.
  *
  * @param message_parts The request message.
@@ -227,8 +149,8 @@
 {
     std::string type;
     std::string command;
-    std::string* response;
-    std::string* window_ptr_str;
+    std::string response = std::string();
+    std::string window_ptr_str = std::string();
     static NPObject* window_ptr;
     int id;
 
@@ -242,21 +164,311 @@
     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);
+    IcedTeaPluginUtilities::JSIDToString(window_ptr, &window_ptr_str);
 
     // We need the context 0 for backwards compatibility with the Java side
-    response = IcedTeaPluginUtilities::constructMessagePrefix(0);
-    *response += " JavaScriptGetWindow ";
-    *response += *window_ptr_str;
+    IcedTeaPluginUtilities::constructMessagePrefix(0, &response);
+    response += " JavaScriptGetWindow ";
+    response += window_ptr_str;
 
-    plugin_to_java_bus->post(response->c_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);
+    IcedTeaPluginUtilities::storeInstanceID(window_ptr, instance);
+}
+
+/**
+ * Evaluates the given script
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::eval(std::vector<std::string>* message_parts)
+{
+    JavaRequestProcessor request_processor = JavaRequestProcessor();
+    JavaResultData* java_result;
+
+    NPObject* window_ptr;
+    NPP instance;
+    std::string script;
+    NPVariant result;
+    std::string response = std::string();
+    std::string return_type = std::string();
+    int id;
+
+    window_ptr = (NPObject*) IcedTeaPluginUtilities::stringToJSID(message_parts->at(3));
+    instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr);
+
+    java_result = request_processor.getString(message_parts->at(4));
+    CHECK_JAVA_RESULT(java_result);
+    script.append(*(java_result->return_string));
+
+    std::vector<void*> internal_request_params = std::vector<void*>();
+    ResultData rdata = ResultData();
+    nsCOMPtr<nsIRunnable> event;
+
+    internal_request_params.push_back(instance);
+    internal_request_params.push_back(window_ptr);
+    internal_request_params.push_back(&script);
+
+    rdata.result_ready = false;
+    event = new IcedTeaRunnableMethod(&_eval, (void*) &internal_request_params, &rdata);
+    NS_DispatchToMainThread(event, 0);
+
+    while (!rdata.result_ready) usleep(2000); // Wait till result is ready
+
+    NPVariant* result_variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(*(rdata.return_string));
+    std::string result_variant_jniid = std::string();
+    storeVariantInJava(*result_variant, &result_variant_jniid);
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, &response);
+    response += " JavaScriptEval ";
+    response += result_variant_jniid;
+
+    plugin_to_java_bus->post(response.c_str());
+
+    delete message_parts;
+
+}
+
+/**
+ * Calls the given javascript script
+ *
+ * @param message_parts The request message.
+ */
+
+void
+PluginRequestProcessor::call(std::vector<std::string>* message_parts)
+{
+    NPP instance;
+    std::string window_ptr_str;
+    void* window_ptr;
+    std::string window_function_name;
+    std::vector<NPVariant> args = std::vector<NPVariant>();
+    std::vector<std::string> arg_ids = std::vector<std::string>();
+    int arg_count;
+    std::string response = std::string();
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+
+    // window
+    window_ptr_str = message_parts->at(3);
+    window_ptr = IcedTeaPluginUtilities::stringToJSID(window_ptr_str);
+
+    // instance
+    instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(window_ptr);
+
+    // function name
+    java_result = java_request.getString(message_parts->at(4));
+    CHECK_JAVA_RESULT(java_result);
+    window_function_name.append(*(java_result->return_string));
+
+    // arguments
+    for (int i=5; i < message_parts->size(); i++)
+    {
+        arg_ids.push_back(message_parts->at(i));
+    }
+
+    std::string number_class_id = std::string();
+    std::string boolean_class_id = std::string();
+    std::string byte_class_id = std::string();
+    std::string char_class_id = std::string();
+    std::string string_class_id = std::string();
+
+    java_result = java_request.findClass("java.lang.Number");
+    CHECK_JAVA_RESULT(java_result);
+    number_class_id.append(*(java_result->return_string));
+
+    java_result = java_request.findClass("java.lang.Boolean");
+    CHECK_JAVA_RESULT(java_result);
+    boolean_class_id.append(*(java_result->return_string));
+
+    java_result = java_request.findClass("java.lang.Byte");
+    CHECK_JAVA_RESULT(java_result);
+    byte_class_id.append(*(java_result->return_string));
+
+    java_result = java_request.findClass("java.lang.Character");
+    CHECK_JAVA_RESULT(java_result);
+    char_class_id.append(*(java_result->return_string));
+
+    java_result = java_request.findClass("java.lang.String");
+    CHECK_JAVA_RESULT(java_result);
+    string_class_id.append(*(java_result->return_string));
+
+    // determine arguments
+    for (int i=0; i < arg_ids.size(); i++)
+    {
+        bool isNum = false;
+        bool isBool = false;
+        bool isByte = false;
+        bool isChar = false;
+        bool isString = false;
+        std::string id = arg_ids[i];
+        std::string arg_class_name = std::string();
+        std::string arg_value = std::string();
+        NPVariant* variant = new NPVariant();
+
+        // instanceOf calls are very fast, so just do them all even
+        // if one of them is true
+
+        // Number
+        java_result = java_request.isInstanceOf(id, number_class_id);
+        CHECK_JAVA_RESULT(java_result);
+        if (*(java_result->return_string) == "1")
+        {
+            isNum = true;
+        }
+
+        // Boolean
+        java_result = java_request.isInstanceOf(id, boolean_class_id);
+        CHECK_JAVA_RESULT(java_result);
+        if (*(java_result->return_string) == "1")
+        {
+            isBool = true;
+        }
+
+        void storeVariantInJava(NPVariant variant, std::string* result);
+        // Byte
+        java_result = java_request.isInstanceOf(id, byte_class_id);
+        CHECK_JAVA_RESULT(java_result);
+        if (*(java_result->return_string) == "1")
+        {
+            isByte = true;
+        }
+
+        // Character
+        java_result = java_request.isInstanceOf(id, char_class_id);
+        CHECK_JAVA_RESULT(java_result);
+        if (*(java_result->return_string) == "1")
+        {
+            isChar = true;
+        }
+
+        // String
+        java_result = java_request.isInstanceOf(id, string_class_id);
+        CHECK_JAVA_RESULT(java_result);
+        if (*(java_result->return_string) == "1")
+        {
+            isString = true;
+        }
+
+        if (isNum)
+        {
+            int i;
+            double d;
+
+            java_result = java_request.getString(id);
+            CHECK_JAVA_RESULT(java_result);
+
+            if (java_result->return_string->find("."))
+            {
+                d = strtod(java_result->return_string->c_str(), NULL);
+                DOUBLE_TO_NPVARIANT(d, *variant);
+            } else
+            {
+                i = atoi(java_result->return_string->c_str());
+                INT32_TO_NPVARIANT(d, *variant);
+            }
+
+
+        } else if (isChar || isByte)
+        {
+            int i;
+            std::string str = std::string();
+
+            java_result = java_request.getString(id);
+            CHECK_JAVA_RESULT(java_result);
+            str.append(*(java_result->return_string));
+
+            // FIXME: No multi-byte char support yet
+            i = str[i];
+
+            INT32_TO_NPVARIANT(i, *variant);
+
+        } else if (isBool)
+        {
+            bool b;
+
+            java_result = java_request.getString(id);
+            CHECK_JAVA_RESULT(java_result);
+
+            if (java_result->return_string->find("true") == 0)
+                b = true;
+            else
+                b = false;
+
+            BOOLEAN_TO_NPVARIANT(b, *variant);
+
+        } else if (isString)
+        {
+            java_result = java_request.getString(id);
+            CHECK_JAVA_RESULT(java_result);
+
+            // string is non-primitive and needs to be allocated on the heap
+            NPUTF8* arg_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
+            strcpy(arg_str, java_result->return_string->c_str());
+
+            STRINGZ_TO_NPVARIANT(arg_str, *variant);
+        } else
+        {
+            // Else complex java object
+
+            std::string class_id; // class id of object
+
+            NPObject* obj;
+
+            java_result = java_request.getClassID(id);
+            CHECK_JAVA_RESULT(java_result);
+            class_id.append(*(java_result->return_string));
+
+            obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, class_id, id);
+
+            OBJECT_TO_NPVARIANT(obj, *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];
+
+    std::vector<void*> internal_request_params = std::vector<void*>();
+    ResultData rdata = ResultData();
+    nsCOMPtr<nsIRunnable> event;
+
+    internal_request_params.push_back(instance);
+    internal_request_params.push_back(window_ptr);
+    internal_request_params.push_back(&window_function_name);
+    internal_request_params.push_back(&arg_count);
+    internal_request_params.push_back(args_array);
+
+    printf("Packing %p [%p] %p %s@%p %p %p\n", instance, internal_request_params.at(0), window_ptr, window_function_name.c_str(), &window_function_name, &arg_count, args_array);
+
+    rdata.result_ready = false;
+    event = new IcedTeaRunnableMethod(&_call, (void*) &internal_request_params, &rdata);
+    NS_DispatchToMainThread(event, 0);
+
+    while (!rdata.result_ready) usleep(2000); // wait till ready
+
+    NPVariant* result_variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(*(rdata.return_string));
+    std::string result_variant_jniid = std::string();
+    storeVariantInJava(*result_variant, &result_variant_jniid);
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, &response);
+    response += " JavaScriptCall ";
+    response += result_variant_jniid;
+
+    plugin_to_java_bus->post(response.c_str());
+
+    cleanup:
+    delete rdata.return_string;
+    free(args_array);
 }
 
 /**
@@ -271,9 +483,9 @@
     NPVariant* variant;
     std::string* variant_string;
     std::string* variant_string_id;
-    JavaRequestProcessor* java_request;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
     JavaResultData* java_result;
-    std::string* response;
+    std::string response = std::string();
     int instance;
 
     instance = atoi(message_parts->at(1).c_str());
@@ -282,8 +494,7 @@
     variant = (NPVariant*) IcedTeaPluginUtilities::stringToJSID(variant_ptr);
     variant_string = IcedTeaPluginUtilities::NPVariantToString(*variant);
 
-    java_request = new JavaRequestProcessor();
-    java_result = java_request->newString(*variant_string);
+    java_result = java_request.newString(*variant_string);
 
     if (java_result->error_occurred)
     {
@@ -294,15 +505,13 @@
     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;
+    IcedTeaPluginUtilities::constructMessagePrefix(instance, &response);
+    response += " JavaScriptToString ";
+    response += *variant_string_id;
 
-    plugin_to_java_bus->post(response->c_str());
+    plugin_to_java_bus->post(response.c_str());
 
     cleanup:
-    delete java_request;
-    delete response;
     delete variant_string;
     delete message_parts;
 
@@ -322,17 +531,18 @@
 {
     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 property_name = std::string();
+    std::string value = std::string();
+    std::string type = std::string();
     std::string* value_variant_ptr_str;
+    std::string member_ptr_str = std::string();
     std::vector<std::string*>* internal_request_params = new std::vector<std::string*>();
 
     NPObject* member;
     nsCOMPtr<nsIRunnable> event;
     ResultData* rdata = new ResultData();
 
-    JavaRequestProcessor* java_request;
+    JavaRequestProcessor* java_request = new JavaRequestProcessor();
     JavaResultData* java_result;
 
     IcedTeaPluginUtilities::printStringVector("PluginRequestProcessor::_setMember - ", message_parts);
@@ -352,7 +562,7 @@
     }
 
     // Copy into local variable before disposing the object
-    property_name->append(*(java_result->return_string));
+    property_name.append(*(java_result->return_string));
     delete java_request;
 
     // Based on the value ID, find the type and string value
@@ -369,7 +579,7 @@
     }
 
     // Copy into local variable before disposing the object
-    type->append(*(java_result->return_string));
+    type.append(*(java_result->return_string));
     delete java_request;
 
     java_request = new JavaRequestProcessor();
@@ -382,18 +592,23 @@
         goto cleanup;
     }
 
-    value->append(*(java_result->return_string));
+    value.append(*(java_result->return_string));
 
-    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);
+    IcedTeaPluginUtilities::JSIDToString(member, &member_ptr_str);
+    internal_request_params->push_back(&member_ptr_str);
+    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);
+    event = new IcedTeaRunnableMethod(&_setMember, (void*) internal_request_params, (void*) rdata);
     NS_DispatchToMainThread(event, 0);
 
+    while (!rdata->result_ready) usleep(2000); // wait till ready
+
     cleanup:
+    delete rdata;
+    delete rdata->return_string;
     delete message_parts;
     delete java_request;
 
@@ -446,18 +661,18 @@
 PluginRequestProcessor::sendMember(std::vector<std::string>* message_parts)
 {
     // member initialization
-    std::vector<std::string>* args;
-    JavaRequestProcessor* java_request;
+    std::vector<std::string> args;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
     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();
+    ResultData member_data;
+    std::string member_id = std::string();
+    std::string parent_id = std::string();
+    std::string jsObjectClassID = std::string();
+    std::string jsObjectConstructorID = std::string();
+    std::string response = std::string();
     nsCOMPtr<nsIRunnable> event;
 
-    std::vector<std::string*>* internal_request_params = new std::vector<std::string*>();
+    std::vector<std::string*> internal_request_params = std::vector<std::string*>();
     int method_id;
     int instance;
     long reference;
@@ -467,14 +682,13 @@
 
     // 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);
+    parent_id += message_parts->at(3);
+    member_id += message_parts->at(4);
 
     /** Request data from Java **/
 
     // make a new request for getString, to get the name of the identifier
-    java_request = new JavaRequestProcessor();
-    java_result = java_request->getString(*member_id);
+    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)
@@ -487,27 +701,22 @@
 
     reference = internal_req_ref_counter++;
 
-    internal_request_params->push_back(parent_id);
-    internal_request_params->push_back(java_result->return_string);
+    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;
+    member_data = ResultData();
+    member_data.result_ready = false;
 
-    event = new IcedTeaRunnableMethod(&_getMember, (void*) internal_request_params, member_data);
+    event = new IcedTeaRunnableMethod(&_getMember, (void*) &internal_request_params, (void*) &member_data);
     NS_DispatchToMainThread(event, 0);
 
-    while (!member_data->result_ready) // wait till ready
-    {
-        usleep(2000);
-    }
+    while (!member_data.result_ready) usleep(2000); // wait till ready
 
-    PLUGIN_DEBUG_1ARG("Member PTR after internal request: %s\n", member_data->return_string->c_str());
+    PLUGIN_DEBUG_1ARG("Member PTR after internal request: %s\n", member_data.return_string->c_str());
 
     internal_req_ref_counter--;
 
-    delete java_request;
-    java_request = new JavaRequestProcessor();
-    java_result = java_request->findClass("netscape.javascript.JSObject");
+    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_occurred)
@@ -516,21 +725,15 @@
         //goto cleanup;
     }
 
-    *jsObjectClassID += *(java_result->return_string);
-
-    // We have the result. Free the request memory
-    delete java_request;
-
-    java_request = new JavaRequestProcessor();
+    jsObjectClassID.append(*(java_result->return_string));
 
-    args = new std::vector<std::string>();
+    args = std::vector<std::string>();
     std::string longArg = "J";
-    args->push_back(longArg);
+    args.push_back(longArg);
 
-    java_result = java_request->getMethodID(
-            *(jsObjectClassID),
-            browser_functions.getstringidentifier("<init>"),
-            *args);
+    java_result = java_request.getMethodID(jsObjectClassID,
+                                           browser_functions.getstringidentifier("<init>"),
+                                           args);
 
     // the result we want is in result_string (assuming there was no error)
     if (java_result->error_occurred)
@@ -539,19 +742,16 @@
         //goto cleanup;
     }
 
-    *jsObjectConstructorID += *(java_result->return_string);
-
-    delete args;
-    delete java_request;
+    jsObjectConstructorID.append(*(java_result->return_string));
 
     // 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);
+    args.clear();
+    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_occurred)
@@ -561,22 +761,16 @@
     }
 
 
-    response = IcedTeaPluginUtilities::constructMessagePrefix(0);
-    response->append(" JavaScriptGetMember ");
-    response->append(java_result->return_string->c_str());
-    plugin_to_java_bus->post(response->c_str());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, &response);
+    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;
+    delete member_data.return_string;
 
     pthread_mutex_lock(&tc_mutex);
     thread_count--;
@@ -620,6 +814,18 @@
             	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
             {
                 // Nothing matched
@@ -639,17 +845,178 @@
     PLUGIN_DEBUG_0ARG("Queue processing stopped.\n");
 }
 
+/* Stores the variant on java side
+ *
+ * @param variant The variant to store
+ * @param result The result
+ */
+void
+PluginRequestProcessor::storeVariantInJava(NPVariant variant, std::string* result)
+{
+
+    // FIXME: Should null and void have some different representation?
+    // the spec doesn't say..
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    JavaResultData* java_result;
+
+    if (NPVARIANT_IS_VOID(variant) || NPVARIANT_IS_NULL(variant))
+    {
+        NPString str = NPVARIANT_TO_STRING(variant);
+        java_result = java_request.newString("");
+        CHECK_JAVA_RESULT(java_result);
+        result->append(*(java_result->return_string));
+    }
+    else if (NPVARIANT_IS_BOOLEAN(variant))
+    {
+        std::string boolean_classid = std::string();
+        std::string boolean_constructor_id = std::string();
+        std::vector<std::string> boolean_args = std::vector<std::string>();
+        std::string value_str;
+        if (NPVARIANT_TO_BOOLEAN(variant))
+            value_str = "true";
+        else
+            value_str = "false";
+
+        java_result = java_request.findClass("java.lang.Boolean");
+        CHECK_JAVA_RESULT(java_result);
+        boolean_classid.append(*(java_result->return_string));
+
+        boolean_args.push_back("Z");
+        java_result = java_request.getMethodID(boolean_classid,
+                                               browser_functions.getstringidentifier("<init>"),
+                                               boolean_args);
+        CHECK_JAVA_RESULT(java_result);
+        boolean_constructor_id.append(*(java_result->return_string));
+
+        boolean_args.clear();
+        boolean_args.push_back(value_str);
+        java_result = java_request.newObject("",
+                                             boolean_classid,
+                                             boolean_constructor_id,
+                                             boolean_args);
+
+        CHECK_JAVA_RESULT(java_result);
+        result->append(*(java_result->return_string));
+    }
+    else if (NPVARIANT_IS_INT32(variant))
+    {
+        std::string integer_classid = std::string();
+        std::string integer_constructor_id = std::string();
+        std::vector<std::string> integer_args = std::vector<std::string>();
+        std::string value_str = std::string();
+        IcedTeaPluginUtilities::itoa(NPVARIANT_TO_INT32(variant), &value_str);
+
+        java_result = java_request.findClass("java.lang.Integer");
+        CHECK_JAVA_RESULT(java_result);
+        integer_classid.append(*(java_result->return_string));
+
+        integer_args.push_back("I");
+        java_result = java_request.getMethodID(integer_classid,
+                                               browser_functions.getstringidentifier("<init>"),
+                                               integer_args);
+        CHECK_JAVA_RESULT(java_result);
+        integer_constructor_id.append(*(java_result->return_string));
+
+        integer_args.clear();
+        integer_args.push_back(value_str);
+        java_result = java_request.newObject("",
+                                             integer_classid,
+                                             integer_constructor_id,
+                                             integer_args);
+
+        CHECK_JAVA_RESULT(java_result);
+        result->append(*(java_result->return_string));
+    }
+    else if (NPVARIANT_IS_DOUBLE(variant))
+    {
+        std::string double_classid = std::string();
+        std::string double_constructor_id = std::string();
+        std::vector<std::string> double_args = std::vector<std::string>();
+        std::string value_str = std::string();
+        IcedTeaPluginUtilities::itoa(NPVARIANT_TO_DOUBLE(variant), &value_str);
+
+        java_result = java_request.findClass("java.lang.Double");
+        CHECK_JAVA_RESULT(java_result);
+        double_classid.append(*(java_result->return_string));
+
+        double_args.push_back("J");
+        java_result = java_request.getMethodID(double_classid,
+                                               browser_functions.getstringidentifier("<init>"),
+                                               double_args);
+        CHECK_JAVA_RESULT(java_result);
+        double_constructor_id.append(*(java_result->return_string));
+
+        double_args.clear();
+        double_args.push_back(value_str);
+        java_result = java_request.newObject("",
+                                             double_classid,
+                                             double_constructor_id,
+                                             double_args);
+
+        CHECK_JAVA_RESULT(java_result);
+        result->append(*(java_result->return_string));
+    }
+    else if (NPVARIANT_IS_STRING(variant))
+    {
+        NPString str = NPVARIANT_TO_STRING(variant);
+        java_result = java_request.newString(str.utf8characters);
+        CHECK_JAVA_RESULT(java_result);
+        result->append(*(java_result->return_string));
+    } else {
+
+
+        // Else it is a complex object
+        if (typeid(IcedTeaScriptableJavaObject*) == typeid(NPVARIANT_TO_OBJECT(variant)))
+        {
+            IcedTeaScriptableJavaObject* obj;
+            obj = (IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant);
+            result->append(obj->getInstanceID());
+        } else {
+            // Else store it as a JSObject
+            std::string jsobject_classid = std::string();
+            std::string jsobject_constructor_id = std::string();
+            std::vector<std::string> jsobject_args = std::vector<std::string>();
+            std::string value_str = std::string();
+            printf("Got NPObject %p\n", NPVARIANT_TO_OBJECT(variant));
+            IcedTeaPluginUtilities::JSIDToString(NPVARIANT_TO_OBJECT(variant), &value_str);
+
+            java_result = java_request.findClass("netscape.javascript.JSObject");
+            CHECK_JAVA_RESULT(java_result);
+            jsobject_classid.append(*(java_result->return_string));
+
+            jsobject_args.push_back("J");
+            java_result = java_request.getMethodID(jsobject_classid,
+                                                   browser_functions.getstringidentifier("<init>"),
+                                                   jsobject_args);
+            CHECK_JAVA_RESULT(java_result);
+            jsobject_constructor_id.append(*(java_result->return_string));
+
+            jsobject_args.clear();
+            jsobject_args.push_back(value_str);
+            java_result = java_request.newObject("",
+                                                 jsobject_classid,
+                                                 jsobject_constructor_id,
+                                                 jsobject_args);
+
+            CHECK_JAVA_RESULT(java_result);
+            result->append(*(java_result->return_string));
+        }
+    }
+
+}
+
+
 /******************************************
  * Functions delegated to the main thread *
  ******************************************/
 
 void*
-_setMember(void* data, ResultData* result)
+_setMember(void* data, void* result)
 {
     std::string* property_name;
     std::string* value;
     std::string* type;
-    std::string* response;
+    std::string response = std::string();
     std::vector<std::string*>* message_parts = (std::vector<std::string*>*) data;
 
     NPP instance;
@@ -664,7 +1031,7 @@
     type = message_parts->at(2);
     value = message_parts->at(3);
 
-    instance = getInstanceFromMemberPtr(member);
+    instance = IcedTeaPluginUtilities::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);
@@ -672,28 +1039,26 @@
     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());
+    IcedTeaPluginUtilities::constructMessagePrefix(0, &response);
+    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;
+    ((ResultData*) result)->result_ready = true;
 
 }
 
 void*
-_getMember(void* data, ResultData* result)
+_getMember(void* data, void* result)
 {
     std::string* parent_ptr_str;
     std::string* member_name;
 
     NPObject* parent_ptr;
     NPVariant member_ptr;
-    std::string* member_ptr_str;
+    std::string member_ptr_str = std::string();
     NPP instance;
     NPIdentifier member_identifier;
 
@@ -711,7 +1076,7 @@
     parent_ptr = reinterpret_cast <NPObject*> (IcedTeaPluginUtilities::stringToJSID(parent_ptr_str->c_str()));
 
     // Get the associated instance
-    instance = getInstanceFromMemberPtr(parent_ptr);
+    instance = IcedTeaPluginUtilities::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());
@@ -723,16 +1088,85 @@
     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());
+    IcedTeaPluginUtilities::JSIDToString(NPVARIANT_TO_OBJECT(member_ptr), &member_ptr_str);
+    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;
+    ((ResultData*) result)->return_string = new std::string();
+    ((ResultData*) result)->return_string->append(member_ptr_str);
+    ((ResultData*) result)->result_ready = true;
 
     // store member -> instance link
-    storeInstanceID(NPVARIANT_TO_OBJECT(member_ptr), instance);
+    IcedTeaPluginUtilities::storeInstanceID(NPVARIANT_TO_OBJECT(member_ptr), instance);
 
     PLUGIN_DEBUG_0ARG("_getMember returning.\n");
+}
 
-    return result;
+void*
+_eval(void* data, void* result)
+{
+    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_0ARG("_eval called\n");
+
+    std::vector<void*>* call_data = (std::vector<void*>*) data;
+
+    instance = (NPP) call_data->at(0);
+    window_ptr = (NPObject*) call_data->at(1);
+    script_str = (std::string*) call_data->at(2);
+
+    script.utf8characters = script_str->c_str();
+    script.utf8length = script_str->size();
+
+    PLUGIN_DEBUG_1ARG("Evaluating: %s\n", script.utf8characters);
+    browser_functions.evaluate(instance, window_ptr, &script, eval_result);
+    IcedTeaPluginUtilities::printNPVariant(*eval_result);
+
+    IcedTeaPluginUtilities::JSIDToString(eval_result, &eval_result_ptr_str);
+    ((ResultData*) result)->return_string = new std::string();
+    ((ResultData*) result)->return_string->append(eval_result_ptr_str);
+    ((ResultData*) result)->result_ready = true;
+
+    PLUGIN_DEBUG_0ARG("_eval returning\n");
 }
+
+
+void*
+_call(void* data, void* result)
+{
+    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_0ARG("_call called\n");
+
+    std::vector<void*>* call_data = (std::vector<void*>*) data;
+
+    instance = (NPP) call_data->at(0);
+    window_ptr = (NPObject*) call_data->at(1);
+    function_name = (std::string*) call_data->at(2);
+    function = browser_functions.getstringidentifier(function_name->c_str());
+    arg_count = (int*) call_data->at(3);
+    args = (NPVariant*) call_data->at(4);
+
+    printf("Extracted %p -- %p -- %s@%p -- %d -- %p\n", instance, window_ptr, function_name->c_str(), function_name, *arg_count, args);
+
+    browser_functions.invoke(instance, window_ptr, function, args, *arg_count, call_result);
+
+    IcedTeaPluginUtilities::JSIDToString(&call_result, &call_result_ptr_str);
+    ((ResultData*) result)->return_string = new std::string();
+    ((ResultData*) result)->return_string->append(call_result_ptr_str);
+    ((ResultData*) result)->result_ready = true;
+
+    PLUGIN_DEBUG_0ARG("_call returning\n");
+}
--- a/plugin/icedteanp/IcedTeaPluginRequestProcessor.h	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaPluginRequestProcessor.h	Fri Aug 14 15:58:23 2009 -0400
@@ -62,20 +62,13 @@
 	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
-extern NPP getInstanceFromMemberPtr(void* member_ptr);
-extern void storeInstanceID(void* member_ptr, NPP instance);
 static void* requestFromMainThread();
 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);
@@ -86,8 +79,10 @@
 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);
+void* _getMember(void* message_parts, void* result);
+void* _setMember(void* message_parts, void* result);
+void* _call(void* data, void* result);
+void* _eval(void* data, void* result);
 
 static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER;
 static int thread_count = 0;
@@ -119,6 +114,9 @@
     	/* Send main window pointer to Java */
     	void sendWindow(std::vector<std::string>* message_parts);
 
+    	/* Stores the variant on java side */
+    	void storeVariantInJava(NPVariant variant, std::string* result);
+
     public:
     	PluginRequestProcessor(); /* Constructor */
     	~PluginRequestProcessor(); /* Destructor */
@@ -134,6 +132,13 @@
 
         /* Send string value of requested object */
         void sendString(std::vector<std::string>* message_parts);
+
+        /* Evaluate the given script */
+        void eval(std::vector<std::string>* message_parts);
+
+        /* Evaluate the given script */
+        void call(std::vector<std::string>* message_parts);
+
 };
 
 #endif // __ICEDTEAPLUGINREQUESTPROCESSOR_H__
--- a/plugin/icedteanp/IcedTeaPluginUtils.cc	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaPluginUtils.cc	Fri Aug 14 15:58:23 2009 -0400
@@ -50,6 +50,7 @@
 // Initialize static variables
 int IcedTeaPluginUtilities::reference = 0;
 pthread_mutex_t IcedTeaPluginUtilities::reference_mutex = PTHREAD_MUTEX_INITIALIZER;
+std::map<void*, NPP>* IcedTeaPluginUtilities::instance_map = new std::map<void*, NPP>();
 
 /**
  * Given a context number, constructs a message prefix to send to Java
@@ -58,19 +59,17 @@
  * @return The string prefix (allocated on heap)
  */
 
-std::string*
-IcedTeaPluginUtilities::constructMessagePrefix(int context)
+void
+IcedTeaPluginUtilities::constructMessagePrefix(int context, std::string *result)
 {
-	std::string* result = new std::string();
-	char* context_str = itoa(context);
+	std::string context_str = std::string();
 
-	*result += "context ";
-	result->append(context_str);
-	*result += " reference -1";
+	itoa(context, &context_str);
 
-	free(context_str);
+	result->append("context ");
+	result->append(context_str);
+	result->append(" reference -1");
 
-	return result;
 }
 
 /**
@@ -79,29 +78,24 @@
  *
  * @param context The context of the request
  * @param rerefence The reference number of the request
- * @return The string prefix (allocated on heap)
+ * @param result The message
  */
 
-std::string*
-IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference)
+void
+IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference, std::string* result)
 {
     // Until security is implemented, use file:// source for _everything_
 
-	/*std::string* result = new std::string();
-	char* context_str = itoa(context);
-	char* reference_str = itoa(reference);
+	std::string context_str = std::string();
+	std::string reference_str = std::string();
+
+	itoa(context, &context_str);
+	itoa(reference, &reference_str);
 
 	*result += "context ";
 	result->append(context_str);
 	*result += " reference ";
 	result->append(reference_str);
-
-	free(context_str);
-	free(reference_str);
-
-	return result;*/
-
-    return IcedTeaPluginUtilities::constructMessagePrefix(context, reference, "file://");
 }
 
 /**
@@ -111,42 +105,43 @@
  * @param context The context of the request
  * @param rerefence The reference number of the request
  * @param address The address for the script that made the request
- * @return The string prefix (allocated on heap)
+ * @param result The message
  */
 
-std::string*
+void
 IcedTeaPluginUtilities::constructMessagePrefix(int context, int reference,
-		                                       const char* address)
+		                                       std::string address,
+		                                       std::string* result)
 {
-	std::string* result = new std::string();
-	char* context_str = itoa(context);
-	char* reference_str = itoa(reference);
+	std::string context_str = std::string();
+	std::string reference_str = std::string();
+
+	itoa(context, &context_str);
+	itoa(reference, &reference_str);
 
 	*result += "context ";
 	result->append(context_str);
 	*result += " reference ";
 	result->append(reference_str);
-	*result += " src ";
-	result->append(address);
 
-	free(context_str);
-	free(reference_str);
-
-	return result;
+	if (address.length() > 0)
+	{
+	    *result += " src ";
+        result->append(address);
+	}
 }
 
 /**
  * Returns a string representation of a void pointer
  *
  * @param id The pointer
- * @return The string representation (Allocated on heap)
+ * @param result The string representation
  */
 
-std::string*
-IcedTeaPluginUtilities::JSIDToString(void* id)
+void
+IcedTeaPluginUtilities::JSIDToString(void* id, std::string* result)
 {
 
-	std::string* result = new std::string();
 	char* id_str = (char*) malloc(sizeof(char)*20); // max = long long = 8446744073709551615 == 19 chars
 
 	if (sizeof(void*) == sizeof(long long))
@@ -158,12 +153,10 @@
 		sprintf(id_str, "%lu", id); // else use long
 	}
 
-	*result += id_str;
+	result->append(id_str);
 
 	PLUGIN_DEBUG_2ARG("Converting pointer %p to %s\n", id, id_str);
 	free(id_str);
-
-	return result;
 }
 
 /**
@@ -201,6 +194,12 @@
 IcedTeaPluginUtilities::getReference()
 {
 	pthread_mutex_lock(&reference_mutex);
+
+	// If we are nearing the max, reset
+	if (reference > 0x7FFFFFFF - 10) {
+	    reference = 0;
+	}
+
 	reference++;
 	pthread_mutex_unlock(&reference_mutex);
 
@@ -215,25 +214,24 @@
 void
 IcedTeaPluginUtilities::releaseReference()
 {
-	pthread_mutex_lock(&reference_mutex);
-	reference--;
-	pthread_mutex_unlock(&reference_mutex);
+    // do nothing for now
 }
 
 /**
  * Converts integer to char*
  *
  * @param i The integer to convert to ascii
- * @return The converted string (allocated on heap)
+ * @param result The resulting string
  */
-char*
-IcedTeaPluginUtilities::itoa(int i)
+void
+IcedTeaPluginUtilities::itoa(int i, std::string* result)
 {
 	// largest possible integer is 10 digits long
-	char* result = (char*) malloc(sizeof(char)*11);
-	sprintf(result, "%d", i);
+	char* int_str = (char*) malloc(sizeof(char)*11);
+	sprintf(int_str, "%d", i);
+	result->append(int_str);
 
-	return result;
+	free(int_str);
 }
 
 /**
@@ -332,16 +330,17 @@
 {
 	std::ostringstream ostream;
 
-	char* length = itoa(str->length());
+	std::string length = std::string();
+	itoa(str->length(), &length);
+
 	ostream << length;
-	free(length);
 
 	// UTF-8 characters are 4-bytes max + space + '\0'
 	char* hex_value = (char*) malloc(sizeof(char)*10);
 
 	for (int i = 0; i < str->length(); i++)
 	{
-		sprintf(hex_value, " %x", (*str)[i]);
+		sprintf(hex_value, " %hx", str->at(i));
 		ostream << hex_value;
 	}
 
@@ -419,6 +418,54 @@
 	delete str;
 }
 
+gchar*
+IcedTeaPluginUtilities::getSourceFromInstance(NPP instance)
+{
+    GCJPluginData* data = (GCJPluginData*) instance->pdata;
+    return data->source;
+}
+
+
+/**
+ * Stores a window pointer <-> instance mapping
+ *
+ * @param member_ptr The pointer key
+ * @param instance The instance to associate with this pointer
+ */
+
+void
+IcedTeaPluginUtilities::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));
+}
+
+
+/**
+ * Given the window pointer, returns the instance associated with it
+ *
+ * @param member_ptr The pointer key
+ * @return The associated instance
+ */
+
+NPP
+IcedTeaPluginUtilities::getInstanceFromMemberPtr(void* 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);
+
+    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;
+}
+
 /*
  * Similar to printStringVector, but takes a vector of string pointers instead
  *
@@ -446,41 +493,6 @@
 	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)
 {
--- a/plugin/icedteanp/IcedTeaPluginUtils.h	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaPluginUtils.h	Fri Aug 14 15:58:23 2009 -0400
@@ -49,11 +49,17 @@
 #include <cstring>
 #include <iostream>
 #include <list>
+#include <map>
 #include <queue>
 #include <sstream>
 #include <string>
 #include <vector>
 
+#include <npapi.h>
+#include <npupp.h>
+
+#include "IcedTeaNPPlugin.h"
+
 #define PLUGIN_DEBUG_0ARG(str) \
   do                                        \
   {                                         \
@@ -104,6 +110,16 @@
     }                                                \
   } while (0)
 
+#define CHECK_JAVA_RESULT(result_data)                               \
+{                                                                    \
+    if (((JavaResultData*) result_data)->error_occurred)             \
+    {                                                                \
+        printf("Error: Error occurred on Java side: %s.\n",          \
+               ((JavaResultData*) result_data)->error_msg->c_str()); \
+        return;                                                      \
+    }                                                                \
+}
+
 /*
  * Misc. utility functions
  *
@@ -119,20 +135,26 @@
         /* Mutex lock for updating reference count */
         static pthread_mutex_t reference_mutex;
 
+        /* Map holding window pointer<->instance relationships */
+        static std::map<void*, NPP>* instance_map;
+
     public:
 
     	/* Constructs message prefix with given context */
-    	static std::string* constructMessagePrefix(int context);
+    	static void constructMessagePrefix(int context,
+                                           std::string* result);
 
     	/* Constructs message prefix with given context and reference */
-    	static std::string* constructMessagePrefix(int context, int reference);
+    	static void constructMessagePrefix(int context, int reference,
+                                           std::string* result);
 
     	/* Constructs message prefix with given context, reference and src */
-    	static std::string* constructMessagePrefix(int context, int reference,
-    			                    const char* address);
+    	static void constructMessagePrefix(int context, int reference,
+                                           std::string address,
+                                           std::string* result);
 
     	/* Converts given pointer to a string representation */
-    	static std::string* JSIDToString(void* id);
+    	static void JSIDToString(void* id, std::string* result);
 
     	/* Converts the given string representation to a pointer */
     	static void* stringToJSID(std::string id_str);
@@ -143,8 +165,8 @@
     	/* Decrements reference count */
     	static void releaseReference();
 
-    	/* Converts the given interget to char* array */
-    	static char* itoa(int i);
+    	/* Converts the given integer to a string */
+    	static void itoa(int i, std::string* result);
 
     	/* Frees the given vector and the strings that its contents point to */
     	static void freeStringPtrVector(std::vector<std::string*>* v);
@@ -178,6 +200,12 @@
     	static void printNPVariant(NPVariant variant);
 
     	static std::string* NPVariantToString(NPVariant variant);
+
+    	static gchar* getSourceFromInstance(NPP instance);
+
+    	static void storeInstanceID(void* member_ptr, NPP instance);
+
+    	static NPP getInstanceFromMemberPtr(void* member_ptr);
 };
 
 /*
@@ -244,11 +272,4 @@
         void post(const char* message);
 };
 
-/*
- * JNI map used for mediating between NPVariants and Java objects
- *
- *
- *
- */
-
 #endif // __ICEDTEAPLUGINUTILS_H__
--- a/plugin/icedteanp/IcedTeaRunnable.cc	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaRunnable.cc	Fri Aug 14 15:58:23 2009 -0400
@@ -55,7 +55,7 @@
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-IcedTeaRunnableMethod::IcedTeaRunnableMethod (Method method, void* thread_data, ResultData* result)
+IcedTeaRunnableMethod::IcedTeaRunnableMethod (Method method, void* thread_data, void* result)
 : method (method),
   thread_data(thread_data),
   result(result)
@@ -69,6 +69,7 @@
 NS_IMETHODIMP
 IcedTeaRunnableMethod::Run ()
 {
+    printf("Running method...\n");
     (*method) (thread_data, result);
     return NS_OK;
 }
--- a/plugin/icedteanp/IcedTeaRunnable.h	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaRunnable.h	Fri Aug 14 15:58:23 2009 -0400
@@ -48,7 +48,7 @@
 /*
  * This struct holds the result from the main-thread dispatched method
  */
-typedef struct java_result
+typedef struct result_data
 {
 	// Return identifier (if applicable)
     int return_identifier;
@@ -85,16 +85,16 @@
 {
 public:
 
-  typedef void* (*Method) (void*, ResultData*);
+  typedef void* (*Method) (void*, void*);
 
-  IcedTeaRunnableMethod (Method, void* thread_data, ResultData* result);
+  IcedTeaRunnableMethod (Method, void* thread_data, void* result);
   NS_IMETHOD Run ();
 
   ~IcedTeaRunnableMethod ();
 
   Method method;
   void* thread_data;
-  ResultData* result;
+  void* result;
 };
 
 #endif /* MOZILLA */
--- a/plugin/icedteanp/IcedTeaScriptablePluginObject.cc	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/IcedTeaScriptablePluginObject.cc	Fri Aug 14 15:58:23 2009 -0400
@@ -41,7 +41,7 @@
 IcedTeaScriptablePluginObject::IcedTeaScriptablePluginObject(NPP instance)
 {
 	this->instance = instance;
-	storeInstanceID(this, instance);
+	IcedTeaPluginUtilities::storeInstanceID(this, instance);
 }
 
 void
@@ -163,7 +163,7 @@
 
     ((IcedTeaScriptableJavaPackageObject*) scriptable_object)->setPackageName(name);
 
-	storeInstanceID(scriptable_object, instance);
+    IcedTeaPluginUtilities::storeInstanceID(scriptable_object, instance);
 
 	return scriptable_object;
 }
@@ -253,7 +253,6 @@
 	// No such package. Do we have a class with that name?
 	if (!hasProperty)
 	{
-		java_request->resetResult();
 		java_result = java_request->findClass(property_name);
 	}
 
@@ -290,13 +289,15 @@
 	{
 		PLUGIN_DEBUG_0ARG("Returning package object\n");
 		obj = IcedTeaScriptablePluginObject::get_scriptable_java_package_object(
-                                  getInstanceFromMemberPtr(npobj),
+                                  IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
                                   property_name.c_str());
 	}
 	else
 	{
 		PLUGIN_DEBUG_0ARG("Returning Java object\n");
-		obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(getInstanceFromMemberPtr(npobj), *(java_result->return_string), "0");
+		obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+		                IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+		                *(java_result->return_string), "0");
 	}
 
 	OBJECT_TO_NPVARIANT(obj, *result);
@@ -368,7 +369,7 @@
 	if (instance_id != "0")
 	    ((IcedTeaScriptableJavaObject*) scriptable_object)->setInstanceIdentifier(instance_id);
 
-	storeInstanceID(scriptable_object, instance);
+	IcedTeaPluginUtilities::storeInstanceID(scriptable_object, instance);
 
 	return scriptable_object;
 }
@@ -450,16 +451,22 @@
     std::string callee;
     std::string source;
 
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+
     if (instance_id.length() == 0) // Static
     {
         printf("Calling static method\n");
         callee = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
-        java_result = java_request.callStaticMethod(callee, browser_functions.utf8fromidentifier(name), args, argCount);
+        java_result = java_request.callStaticMethod(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        callee, browser_functions.utf8fromidentifier(name), args, argCount);
     } else
     {
         printf("Calling method normally\n");
         callee = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
-        java_result = java_request.callMethod(callee, browser_functions.utf8fromidentifier(name), args, argCount);
+        java_result = java_request.callMethod(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        callee, browser_functions.utf8fromidentifier(name), args, argCount);
     }
 
     if (java_result->error_occurred)
@@ -509,7 +516,6 @@
         return_obj_instance_id.append(*(java_result->return_string));
 
         // Find out the class name first, because string is a special case
-        java_request.resetResult();
         java_result = java_request.getClassName(return_obj_instance_id);
 
         if (java_result->error_occurred)
@@ -522,7 +528,6 @@
         if (return_obj_class_name == "java.lang.String")
         {
             // String is a special case as NPVariant can handle it directly
-            java_request.resetResult();
             java_result = java_request.getString(return_obj_instance_id);
 
             if (java_result->error_occurred)
@@ -531,7 +536,7 @@
             }
 
             // needs to be on the heap
-            NPUTF8* return_str = (NPUTF8*) browser_functions.memalloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
+            NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
             strcpy(return_str, java_result->return_string->c_str());
 
             PLUGIN_DEBUG_1ARG("Method call returned a string %s\n", return_str);
@@ -544,8 +549,6 @@
 
             // Else this is a regular class. Reference the class object so
             // we can construct an NPObject with it and the instance
-
-            java_request.resetResult();
             java_result = java_request.findClass(return_obj_class_name);
 
             if (java_result->error_occurred)
@@ -556,7 +559,9 @@
             return_obj_class_id.append(*(java_result->return_string));
 
             NPObject* obj;
-            obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(getInstanceFromMemberPtr(npobj), return_obj_class_id, return_obj_instance_id);
+            obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                            IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+                            return_obj_class_id, return_obj_instance_id);
 
             OBJECT_TO_NPVARIANT(obj, *result);
         }
@@ -609,12 +614,14 @@
     std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
     std::string callee = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
 
-    java_result = java_request.getField(callee, browser_functions.utf8fromidentifier(name));
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+    java_result = java_request.getField(
+                    IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                    callee, browser_functions.utf8fromidentifier(name));
 
     std::string object_id = *(java_result->return_string);
 
     // get the class of this object
-    java_request.resetResult();
     java_result = java_request.getObjectClass(object_id);
 
     if (java_result->error_occurred)
@@ -622,7 +629,9 @@
         return false;
     }
 
-    obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(getInstanceFromMemberPtr(npobj), *(java_result->return_string), object_id);
+    obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                    IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+                    *(java_result->return_string), object_id);
 
     OBJECT_TO_NPVARIANT(obj, *result);
 
--- a/plugin/icedteanp/java/netscape/javascript/JSObject.java	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/java/netscape/javascript/JSObject.java	Fri Aug 14 15:58:23 2009 -0400
@@ -47,6 +47,10 @@
 package netscape.javascript;
 
 import java.applet.Applet;
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.BasicPermission;
 
 import sun.applet.PluginAppletViewer;
 import sun.applet.PluginDebug;
@@ -102,13 +106,37 @@
     /**
      * it is illegal to construct a JSObject manually
      */
-    // FIXME: make private!
     public JSObject(int jsobj_addr) {
-        PluginDebug.debug ("JSObject int CONSTRUCTOR");
-        internal = jsobj_addr;
+        this((long) jsobj_addr);
     }
 
     public JSObject(long jsobj_addr) {
+        
+        // See if the caller has permission
+        
+        try {
+            AccessController.getContext().checkPermission(new JSObjectCreatePermission());
+        } catch (AccessControlException ace) {
+            
+            // If not, only caller with JSObject.getWindow on the stack may 
+            // make this call unprivileged.
+            
+            // Although this check is inefficient, it should happen only once
+            // during applet init, so we look the other way
+
+            StackTraceElement[] stack =  Thread.currentThread().getStackTrace();
+            boolean mayProceed = false;
+            
+            for (int i=0; i < stack.length; i++) {
+                if (stack[i].getClassName().equals("netscape.javascript.JSObject") &&
+                    stack[i].getMethodName().equals("getWindow")) {
+                    mayProceed = true;
+                }
+            }
+
+            if (!mayProceed) throw ace;
+        }
+
         PluginDebug.debug ("JSObject long CONSTRUCTOR");
         internal = jsobj_addr;
     }
@@ -234,7 +262,7 @@
         internal = ((PluginAppletViewer)
                     applet.getAppletContext()).getWindow();
         PluginDebug.debug ("GOT IT: " + internal);
-        return new JSObject(internal);
+        return new JSObject((long) internal);
     }
 
 
@@ -259,5 +287,4 @@
 
         return false;
     }
-
 }
--- a/plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java	Fri Aug 14 15:58:23 2009 -0400
@@ -49,9 +49,10 @@
     public void parseReturn(String message) {
     	PluginDebug.debug ("GetMEMBerparseReturn GOT: " + message);
         String[] args = message.split(" ");
-        // FIXME: add thread ID to messages to support multiple
-        // threads using the netscape.javascript package.
-        object = AppletSecurityContextManager.getSecurityContext(0).getObject(Integer.parseInt(args[1]));
+        // FIXME: Is it even possible to distinguish between null and void
+        // here?
+        if (args[1] != "null" && args[1] != "void")
+        	object = AppletSecurityContextManager.getSecurityContext(0).getObject(Integer.parseInt(args[1]));
         setDone(true);
     }
 
--- a/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java	Fri Aug 14 15:58:23 2009 -0400
@@ -138,6 +138,11 @@
         Object[] o14 = { fc.getClass(), "foo_noargs" };
         list.add(o14);
         
+        // method which takes a primitive bool, given a Boolean
+        String s15 = "foo_boolonly()";
+        Object[] o15 = { fc.getClass(), "foo_boolonly", new Boolean(true) };
+        list.add(o15);
+
         for (Object[] o : list) {
             Object[] methodAndArgs = getMatchingMethod(o);
             if (debugging)
@@ -312,6 +317,8 @@
             return java.lang.Float.TYPE;
         } else if (o instanceof java.lang.Double) {
             return java.lang.Double.TYPE;
+        } else if (o instanceof java.lang.Boolean) {
+            return java.lang.Boolean.TYPE;
         }
 
         return o.getClass();
@@ -408,16 +415,6 @@
 
 class FooClass {
 
-    // Normal, null => non primitive type
-    public void foo(Boolean b) {
-
-    }
-
-    // Class -> primitive
-    public void foo(boolean b) {
-
-    }
-
     // First type full match, second Class -> Primitive
     public void foo(Boolean b, int i) {
 
@@ -472,6 +469,8 @@
     public void foo_int_only (int i) {}
     
     public void foo_noargs() {}
+
+    public void foo_boolonly(boolean b) {}
 }
 
 class BarClass1 {}
--- a/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java	Fri Aug 14 15:58:23 2009 -0400
@@ -60,6 +60,7 @@
 import sun.reflect.generics.repository.MethodRepository;
 
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import netscape.javascript.JSObjectCreatePermission;
 
 
 
@@ -232,7 +233,7 @@
 
 public class PluginAppletSecurityContext {
 	
-	public static Hashtable<ClassLoader, String> classLoaders = new Hashtable<ClassLoader, String>();
+	public static Hashtable<ClassLoader, URL> classLoaders = new Hashtable<ClassLoader, URL>();
 
 	// FIXME: make private
 	public PluginObjectStore store = new PluginObjectStore();
@@ -260,8 +261,16 @@
 		}
 
 		JNLPRuntime.disableExit();
+		
+		URL u = null;
+		try {
+		    u = new URL("file://");
+		} catch (Exception e) {
+		    e.printStackTrace();
+		}
+		
 
-		this.classLoaders.put(liveconnectLoader, "file://");
+		this.classLoaders.put(liveconnectLoader, u);
 	}
 
 	private static <V> V parseCall(String s, ClassLoader cl, Class<V> c) {
@@ -300,7 +309,7 @@
 			return store.getObject(new Integer(s));
 	}
 
-	public void associateSrc(ClassLoader cl, String src) {
+	public void associateSrc(ClassLoader cl, URL src) {
 		PluginDebug.debug("Associating " + cl + " with " + src);
 		this.classLoaders.put(cl, src);
 	}
@@ -610,7 +619,7 @@
 				arguments[1] = methodName;
                 for (int i = 0; i < args.length - 3; i++) {
                     arguments[i+2] = store.getObject(parseCall(args[3 + i], null, Integer.class));
-                    PluginDebug.debug("GOT ARG: " + arguments[i]);
+                    PluginDebug.debug("GOT ARG: " + arguments[i+2]);
                 }
 
                 Object[] matchingMethodAndArgs = MethodOverloadResolver.getMatchingMethod(arguments);
@@ -954,7 +963,7 @@
                 while (i < length) {
                     c = Integer.parseInt(args[j++], 16);
                     byteArray[i++] = (byte) c;
-                }
+                } 
 
                 ret = new String(byteArray, "UTF-8");
                 PluginDebug.debug("NEWSTRINGUTF: " + ret);
@@ -1065,12 +1074,18 @@
 		if (target.getClassLoader() == null)
 			return;
 
-		String classSrc = this.classLoaders.get(target.getClassLoader());
+		URL classSrcURL = this.classLoaders.get(target.getClassLoader());
+		URL jsSrcURL = null;
+		try {
+		    jsSrcURL = new URL(jsSrc);
+		} catch (Exception e) {
+		    e.printStackTrace();
+		}
 
-		PluginDebug.debug("target = " + target + " jsSrc=" + jsSrc + " classSrc=" + classSrc);
+		PluginDebug.debug("target = " + target + " jsSrc=" + jsSrc + " classSrc=" + classSrcURL);
 		
 		// if src is not a file and class loader does not map to the same base, UniversalBrowserRead (BrowserReadPermission) must be set
-		if (!jsSrc.equals("file://") && !jsSrc.equals("[System]") && !classSrc.equals(jsSrc)) {
+		if (!jsSrc.equals("file://") && !jsSrc.equals("[System]") && !classSrcURL.equals(jsSrcURL)) {
 			acc.checkPermission(new BrowserReadPermission());
 		}
 	}
@@ -1354,12 +1369,15 @@
 
 		CodeSource cs = new CodeSource((URL) null, (java.security.cert.Certificate  [])null);
 		
-		if (src != null) {
+		if (src != null && src.length() > 0) {
 			try {
 				cs = new CodeSource(new URL(src + "/"), (java.security.cert.Certificate[]) null);
 			} catch (MalformedURLException mfue) {
 				// do nothing
 			}
+		} else {
+		    JSObjectCreatePermission perm = new JSObjectCreatePermission();
+		    grantedPermissions.add(perm);
 		}
 
 		ProtectionDomain pd = new ProtectionDomain(cs, grantedPermissions, null, null);
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	Fri Aug 14 15:58:23 2009 -0400
@@ -346,7 +346,7 @@
     	}
     }
 
-    AppletSecurityContextManager.getSecurityContext(0).associateSrc(a.getClass().getClassLoader(), codeBase);
+    AppletSecurityContextManager.getSecurityContext(0).associateSrc(a.getClass().getClassLoader(), doc);
     
  	try {
  	    write("initialized");
@@ -354,6 +354,16 @@
  		ioe.printStackTrace();
  	}
  	
+    // Panel initialization cannot be aborted mid-way. 
+    // Once it is initialized, double check to see if this 
+    // panel needs to stay around..
+    if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) {
+        PluginDebug.debug("Inactive flag set. Destroying applet instance " + identifier);
+        applets.get(identifier).handleMessage(-1, "destroy");
+    } else {
+        status.put(identifier, PAV_INIT_STATUS.ACTIVE);
+    }
+ 	
      }
 
  	public static void setStreamhandler(PluginStreamHandler sh) {
@@ -415,16 +425,6 @@
         						 new StringReader(request.tag),
         						 new URL(request.documentbase));
         				 requests.remove(identifier);
-        				 
-        				 // Panel initialization cannot be aborted mid-way. 
-        				 // Once it is initialized, double check to see if this 
-        				 // panel needs to stay around..
-        				 if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) {
-        				     PluginDebug.debug("Inactive flag set. Destroying applet instance " + identifier);
-        				     applets.get(identifier).handleMessage(-1, "destroy");
-        				 } else {
-        				     status.put(identifier, PAV_INIT_STATUS.ACTIVE);
-        				 }
 
         			 } else {
         				 PluginDebug.debug ("REQUEST HANDLE NOT SET: " + request.handle + ". BYPASSING");
@@ -467,16 +467,6 @@
             			 PluginDebug.debug ("REQUEST HANDLE, DONE PARSING " +
             					 Thread.currentThread());
 
-                         // Panel initialization cannot be aborted mid-way. 
-                         // Once it is initialized, double check to see if this 
-                         // panel needs to stay around..
-                         if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) {
-                             PluginDebug.debug("Inactive flag set. Destroying applet instance " + identifier);
-                             applets.get(identifier).handleMessage(-1, "destroy");
-                         } else {
-                             status.put(identifier, PAV_INIT_STATUS.ACTIVE);
-                         }
-
             		 } else {
             			 PluginDebug.debug ("REQUEST TAG NOT SET: " + request.tag + ". BYPASSING");
             		 }
@@ -526,6 +516,8 @@
              }
          } catch (Exception e) {
 
+             e.printStackTrace();
+             
              // If an exception happened during pre-init, we need to update status
              if (status.get(identifier).equals(PAV_INIT_STATUS.PRE_INIT))
                  status.put(identifier, PAV_INIT_STATUS.INACTIVE);
@@ -589,7 +581,8 @@
 
              // Wait for the panel to initialize
              // (happens in a separate thread)
-             while ((o = panel.getApplet()) == null && ((NetxPanel) panel).isAlive()) {
+             System.err.println("PANEL = " + panel);
+             while (panel == null || ((o = panel.getApplet()) == null && ((NetxPanel) panel).isAlive())) {
             	 try {
             		 Thread.sleep(2000);
             		 PluginDebug.debug("Waiting for applet to initialize...");
@@ -1075,12 +1068,18 @@
          // FIXME: convenience method for this long line.
     	 AppletSecurityContextManager.getSecurityContext(0).store(name);
          int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
-         AppletSecurityContextManager.getSecurityContext(0).store(args);
-         int argsID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(args);
+         
+         String argIDs = "";
+         for (Object arg : args)
+         {
+             AppletSecurityContextManager.getSecurityContext(0).store(arg);
+             argIDs += AppletSecurityContextManager.getSecurityContext(0).getIdentifier(arg) + " ";
+         }
+         argIDs = argIDs.trim();
  
          // Prefix with dummy instance for convenience.
          PluginCallRequest request = requestFactory.getPluginCallRequest("member",
-        		 							"instance " + 0 + " Call " + internal + " " + nameID + " " + argsID, 
+        		 							"instance " + 0 + " Call " + internal + " " + nameID + " " + argIDs, 
         		 							"JavaScriptCall");
          streamhandler.postCallRequest(request);
          streamhandler.write(request.getMessage());
--- a/plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java	Thu Aug 06 10:43:31 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java	Fri Aug 14 15:58:23 2009 -0400
@@ -91,15 +91,20 @@
 
     	        String cookie = cookies[i];
     	        cookie = cookie.trim();
-    	        String cookieName = cookie.substring(0, cookie.indexOf("="));
-    	        String cookieValue = cookie.substring(cookie.indexOf("=")+1);
+    	        String cookieName; 
+    	        String cookieValue; 
+
+    	        if (cookie.indexOf("=") > 0) {
+    	            cookieName = cookie.substring(0, cookie.indexOf("="));
+    	            cookieValue = cookie.substring(cookie.indexOf("=")+1);
 
-    	        HttpCookie httpCookieObj = new HttpCookie(cookieName, cookieValue);
-    	        httpCookieObj.setPath(siteURI.getPath());
-    	        httpCookieObj.setVersion(0); // force v0
+    	            HttpCookie httpCookieObj = new HttpCookie(cookieName, cookieValue);
+    	            httpCookieObj.setPath(siteURI.getPath());
+    	            httpCookieObj.setVersion(0); // force v0
 
-    	        PluginDebug.debug("Adding cookie info COOKIEN=" + cookieName + " and COOKIEV=" + cookieValue);
-    	        cookieObjects.add(httpCookieObj);
+    	            PluginDebug.debug("Adding cookie info COOKIEN=" + cookieName + " and COOKIEV=" + cookieValue);
+    	            cookieObjects.add(httpCookieObj);
+    	        }
     	    }
     	}